From: Dmitry V. Levin Date: Sat, 8 Jul 2017 19:27:26 +0000 (+0000) Subject: tests: check decoding of SO_PEERCRED socket option X-Git-Tag: v4.19~311 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dd95f5ae69f0bc84d2fc0d33924f0fd89e42b242;p=strace tests: check decoding of SO_PEERCRED socket option * tests/so_peercred.c: New file. * tests/gen_tests.in (so_peercred): New entry. * tests/pure_executables.list: Add so_peercred. * tests/.gitignore: Likewise. --- diff --git a/tests/.gitignore b/tests/.gitignore index ec6f4273..34423132 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -349,6 +349,7 @@ sigreturn sigsuspend sleep so_linger +so_peercred sock_filter-v socketcall splice diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 8320337f..986b9cc4 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -300,6 +300,7 @@ sigprocmask -a34 sigreturn -esignal='!USR1' sigsuspend -a19 -esignal=none so_linger -e trace=getsockopt,setsockopt +so_peercred -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt socketcall -a20 splice diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 6bdb99cc..aca5b1ce 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -288,6 +288,7 @@ sigprocmask sigreturn sigsuspend so_linger +so_peercred sock_filter-v socketcall splice diff --git a/tests/so_peercred.c b/tests/so_peercred.c new file mode 100644 index 00000000..53bf0719 --- /dev/null +++ b/tests/so_peercred.c @@ -0,0 +1,117 @@ +/* + * Check decoding of SO_PEERCRED socket option. + * + * Copyright (c) 2017 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" + +#include +#include +#include +#include + +#include "print_fields.h" + +static const char *errstr; + +static int +get_peercred(int fd, void *val, socklen_t *len) +{ + int rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, val, len); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + TAIL_ALLOC_OBJECT_CONST_PTR(struct ucred, peercred); + TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); + + int sv[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) + perror_msg_and_skip("socketpair AF_UNIX SOCK_STREAM"); + + /* classic getsockopt */ + *len = sizeof(*peercred); + get_peercred(sv[0], peercred, len); + printf("getsockopt(%d, SOL_SOCKET, SO_PEERCRED", sv[0]); + PRINT_FIELD_D(", {", *peercred, pid); + PRINT_FIELD_UID(", ", *peercred, uid); + PRINT_FIELD_UID(", ", *peercred, gid); + printf("}, [%d]) = %s\n", *len, errstr); + + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + perror_msg_and_skip("socket AF_UNIX SOCK_STREAM"); + + /* getsockopt with optlen larger than necessary - shortened */ + *len = sizeof(*peercred) + 1; + get_peercred(fd, peercred, len); + printf("getsockopt(%d, SOL_SOCKET, SO_PEERCRED", fd); + PRINT_FIELD_D(", {", *peercred, pid); + PRINT_FIELD_UID(", ", *peercred, uid); + PRINT_FIELD_UID(", ", *peercred, gid); + printf("}, [%u->%d]) = %s\n", + (unsigned int) sizeof(*peercred) + 1, *len, errstr); + + /* getsockopt with optlen smaller than usual - truncated to ucred.pid */ + *len = sizeof(peercred->pid); + get_peercred(fd, peercred, len); + printf("getsockopt(%d, SOL_SOCKET, SO_PEERCRED", fd); + PRINT_FIELD_D(", {", *peercred, pid); + printf("}, [%d]) = %s\n", *len, errstr); + + /* getsockopt with optlen smaller than usual - truncated to ucred.uid */ + *len = offsetof(struct ucred, gid); + get_peercred(fd, peercred, len); + printf("getsockopt(%d, SOL_SOCKET, SO_PEERCRED", fd); + PRINT_FIELD_D(", {", *peercred, pid); + PRINT_FIELD_UID(", ", *peercred, uid); + printf("}, [%d]) = %s\n", *len, errstr); + + /* getsockopt with optlen larger than usual - truncated to raw */ + *len = sizeof(*peercred) - 1; + get_peercred(fd, peercred, len); + printf("getsockopt(%d, SOL_SOCKET, SO_PEERCRED, ", fd); + print_quoted_hex(peercred, *len); + printf(", [%d]) = %s\n", *len, errstr); + + /* getsockopt optval EFAULT */ + *len = sizeof(*peercred); + get_peercred(fd, &peercred->uid, len); + printf("getsockopt(%d, SOL_SOCKET, SO_PEERCRED, %p, [%d]) = %s\n", + fd, &peercred->uid, *len, errstr); + + /* getsockopt optlen EFAULT */ + get_peercred(fd, peercred, len + 1); + printf("getsockopt(%d, SOL_SOCKET, SO_PEERCRED, %p, %p) = %s\n", + fd, peercred, len + 1, errstr); + + puts("+++ exited with 0 +++"); + return 0; +}