From owner-freebsd-bugs@FreeBSD.ORG Tue Feb 10 17:40:02 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5BDC21065670 for ; Tue, 10 Feb 2009 17:40:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 3300D8FC0C for ; Tue, 10 Feb 2009 17:40:02 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n1AHe1Vk039403 for ; Tue, 10 Feb 2009 17:40:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n1AHe1E6039402; Tue, 10 Feb 2009 17:40:01 GMT (envelope-from gnats) Resent-Date: Tue, 10 Feb 2009 17:40:01 GMT Resent-Message-Id: <200902101740.n1AHe1E6039402@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Andrey Simonenko Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 31B60106564A for ; Tue, 10 Feb 2009 17:39:13 +0000 (UTC) (envelope-from simon@comsys.ntu-kpi.kiev.ua) Received: from comsys.ntu-kpi.kiev.ua (comsys.ntu-kpi.kiev.ua [77.47.192.42]) by mx1.freebsd.org (Postfix) with ESMTP id 728178FC1D for ; Tue, 10 Feb 2009 17:38:38 +0000 (UTC) (envelope-from simon@comsys.ntu-kpi.kiev.ua) Received: from pm513-1.comsys.ntu-kpi.kiev.ua (pm513-1.comsys.ntu-kpi.kiev.ua [10.18.52.101]) (authenticated bits=0) by comsys.ntu-kpi.kiev.ua (8.13.7/8.13.7) with ESMTP id n1AHhId5010054 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 10 Feb 2009 19:43:18 +0200 (EET) Received: by pm513-1.comsys.ntu-kpi.kiev.ua (Postfix, from userid 1001) id 9951A1CC3F; Tue, 10 Feb 2009 19:38:25 +0200 (EET) Message-Id: <20090210173825.GA69591@pm513-1.comsys.ntu-kpi.kiev.ua> Date: Tue, 10 Feb 2009 19:38:25 +0200 From: Andrey Simonenko To: FreeBSD-gnats-submit@FreeBSD.org Cc: Subject: bin/131567: Update for regression/sockets/unix_cmsg X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Feb 2009 17:40:03 -0000 >Number: 131567 >Category: bin >Synopsis: Update for regression/sockets/unix_cmsg >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Tue Feb 10 17:40:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Andrey Simonenko >Release: FreeBSD 7.1-STABLE amd64 >Organization: >Environment: >Description: This is update for unix_cmsg tests: 1. Added test for LOCAL_PEERCRED in unix_cmsg.c and its description to README. As a result some test numbers were changed in unix_cmsg.t. 2. If some incorrect data was found, then finish test, do not check next data. 3. unix_cmsg.c code was simplified, some parts were modified to match style(9). 4. Now timeout in unix_cmsg.c is 5 seconds (previous value was 60 seconds). Now "prove unix_cmsg.t" takes 10 seconds (previous version took 120 seconds). This version of unix_cmsg was tested on 7.1 and 8.0 on amd64. >How-To-Repeat: >Fix: diff -ruN unix_cmsg.orig/README unix_cmsg/README --- unix_cmsg.orig/README 2006-05-29 21:40:55.000000000 +0300 +++ unix_cmsg/README 2009-02-03 17:41:42.000000000 +0200 @@ -1,7 +1,7 @@ $FreeBSD: src/tools/regression/sockets/unix_cmsg/README,v 1.1 2006/05/29 18:40:55 maxim Exp $ About unix_cmsg -================ +=============== This program is a collection of regression tests for ancillary (control) data for PF_LOCAL sockets (local domain or Unix domain sockets). There @@ -13,8 +13,8 @@ messages to Server. It is better to change the owner of unix_cmsg to some safe user -(eg. nobody:nogroup) and set SUID and SGID bits, else some tests -can give correct results for wrong implementation. +(eg. nobody:nogroup) and set SUID and SGID bits, else some tests that +check credentials can give correct results for wrong implementation. Available options ================= @@ -24,7 +24,7 @@ -h Output help message and exit. --t +-t socktype Run tests only for the given socket type: "stream" or "dgram". With this option it is possible to run only particular test, not all of them. @@ -90,6 +90,13 @@ message with data and control message with SCM_TIMESTAMP type followed by struct timeval{}. + 6: Check LOCAL_PEERCRED socket option + + This test does not use control data for PF_LOCAL sockets, but can be + implemented here. Client connects to Server. Both Client and Server + verify that credentials of the peer are correct using LOCAL_PEERCRED + socket option. + For SOCK_DGRAM sockets: ---------------------- @@ -110,7 +117,7 @@ structure should contain correct information. 3: Sending cmsgcred, receiving sockcred - + Server creates datagram socket and set socket option LOCAL_CREDS for it. Client sends one message with data and control message with SOCK_CREDS type to Server. Server should receive one message with diff -ruN unix_cmsg.orig/unix_cmsg.c unix_cmsg/unix_cmsg.c --- unix_cmsg.orig/unix_cmsg.c 2006-05-31 11:10:34.000000000 +0300 +++ unix_cmsg/unix_cmsg.c 2009-02-10 19:11:11.000000000 +0200 @@ -27,10 +27,11 @@ #include __FBSDID("$FreeBSD: src/tools/regression/sockets/unix_cmsg/unix_cmsg.c,v 1.2 2006/05/31 08:10:34 maxim Exp $"); -#include +#include #include #include #include +#include #include #include @@ -68,7 +69,7 @@ * * Each function which can block, is run under TIMEOUT, if timeout * occurs, then test function returns -2 or a client process exits - * with nonzero return code. + * with non-zero return code. */ #ifndef LISTENQ @@ -76,14 +77,14 @@ #endif #ifndef TIMEOUT -# define TIMEOUT 60 +# define TIMEOUT 5 #endif #define EXTRA_CMSG_SPACE 512 /* Memory for not expected control data. */ static int t_cmsgcred(void), t_sockcred_stream1(void); static int t_sockcred_stream2(void), t_cmsgcred_sockcred(void); -static int t_sockcred_dgram(void), t_timestamp(void); +static int t_sockcred_dgram(void), t_timestamp(void), t_peercred(void); struct test_func { int (*func)(void); /* Pointer to function. */ @@ -91,31 +92,57 @@ }; static struct test_func test_stream_tbl[] = { - { NULL, " 0: All tests" }, - { t_cmsgcred, " 1: Sending, receiving cmsgcred" }, - { t_sockcred_stream1, " 2: Receiving sockcred (listening socket has LOCAL_CREDS)" }, - { t_sockcred_stream2, " 3: Receiving sockcred (accepted socket has LOCAL_CREDS)" }, - { t_cmsgcred_sockcred, " 4: Sending cmsgcred, receiving sockcred" }, - { t_timestamp, " 5: Sending, receiving timestamp" }, - { NULL, NULL } + { .func = NULL, + .desc = "All tests" + }, + { .func = t_cmsgcred, + .desc = "Sending, receiving cmsgcred" + }, + { .func = t_sockcred_stream1, + .desc = "Receiving sockcred (listening socket has LOCAL_CREDS)" + }, + { .func = t_sockcred_stream2, + .desc = "Receiving sockcred (accepted socket has LOCAL_CREDS)" + }, + { .func = t_cmsgcred_sockcred, + .desc = "Sending cmsgcred, receiving sockcred" + }, + { .func = t_timestamp, + .desc = "Sending, receiving timestamp" + }, + { .func = t_peercred, + .desc = "Check LOCAL_PEERCRED socket option" + } }; +#define TEST_STREAM_TBL_SIZE \ + (sizeof(test_stream_tbl) / sizeof(test_stream_tbl[0])) + static struct test_func test_dgram_tbl[] = { - { NULL, " 0: All tests" }, - { t_cmsgcred, " 1: Sending, receiving cmsgcred" }, - { t_sockcred_dgram, " 2: Receiving sockcred" }, - { t_cmsgcred_sockcred, " 3: Sending cmsgcred, receiving sockcred" }, - { t_timestamp, " 4: Sending, receiving timestamp" }, - { NULL, NULL } + { .func = NULL, + .desc = "All tests" + }, + { .func = t_cmsgcred, + .desc = "Sending, receiving cmsgcred" + }, + { .func = t_sockcred_dgram, + .desc = "Receiving sockcred" + }, + { .func = t_cmsgcred_sockcred, + .desc = "Sending cmsgcred, receiving sockcred" + }, + { .func = t_timestamp, + .desc = "Sending, receiving timestamp" + } }; -#define TEST_STREAM_NO_MAX (sizeof(test_stream_tbl) / sizeof(struct test_func) - 2) -#define TEST_DGRAM_NO_MAX (sizeof(test_dgram_tbl) / sizeof(struct test_func) - 2) +#define TEST_DGRAM_TBL_SIZE \ + (sizeof(test_dgram_tbl) / sizeof(test_dgram_tbl[0])) -static const char *myname = "SERVER"; /* "SERVER" or "CLIENT" */ +static const char *myname; /* "SERVER" or "CLIENT" */ -static int debug = 0; /* 1, if -d. */ -static int no_control_data = 0; /* 1, if -z. */ +static int debug = 0; /* -d */ +static int no_control_data = 0; /* -z */ static u_int nfailed = 0; /* Number of failed tests. */ @@ -164,24 +191,23 @@ static void usage(int quick) { - const struct test_func *test_func; + u_int i; - fprintf(stderr, "Usage: %s [-dhz] [-t ] [testno]\n", + fprintf(stderr, "usage: %s [-dhz] [-t socktype] [testno]\n", __progname); if (quick) return; fprintf(stderr, "\n Options are:\n\ -d\t\t\tOutput debugging information\n\ -h\t\t\tOutput this help message and exit\n\ - -t \t\tRun test only for the given socket type:\n\ -\t\t\tstream or dgram\n\ + -t socktype\t\tRun test only for socket type: stream or dgram\n\ -z\t\t\tDo not send real control data if possible\n\n"); fprintf(stderr, " Available tests for stream sockets:\n"); - for (test_func = test_stream_tbl; test_func->desc != NULL; ++test_func) - fprintf(stderr, " %s\n", test_func->desc); + for (i = 0; i < TEST_STREAM_TBL_SIZE; ++i) + fprintf(stderr, " %u: %s\n", i, test_stream_tbl[i].desc); fprintf(stderr, "\n Available tests for datagram sockets:\n"); - for (test_func = test_dgram_tbl; test_func->desc != NULL; ++test_func) - fprintf(stderr, " %s\n", test_func->desc); + for (i = 0; i < TEST_DGRAM_TBL_SIZE; ++i) + fprintf(stderr, " %u: %s\n", i, test_dgram_tbl[i].desc); } /* @@ -210,8 +236,7 @@ va_list ap; int errno_save; - errno_save = errno; /* Save errno. */ - + errno_save = errno; va_start(ap, format); if (vsnprintf(buf, sizeof(buf), format, ap) < 0) err(EX_SOFTWARE, "logmsg: vsnprintf failed"); @@ -220,8 +245,7 @@ else output("%s: %s: %s\n", myname, buf, strerror(errno_save)); va_end(ap); - - errno = errno_save; /* Restore errno. */ + errno = errno_save; } /* @@ -241,22 +265,35 @@ } /* - * Run tests from testno1 to testno2. + * Run tests for the given socket type. */ static int -run_tests(u_int testno1, u_int testno2) +run_tests(int type, u_int testno1) { - const struct test_func *test_func; - u_int i, nfailed1; + const struct test_func *tf; + u_int i, nfailed1, testno2; - output("Running tests for %s sockets:\n", sock_type_str); - test_func = (sock_type == SOCK_STREAM ? - test_stream_tbl : test_dgram_tbl) + testno1; + sock_type = type; + if (type == SOCK_STREAM) { + sock_type_str = "SOCK_STREAM"; + tf = test_stream_tbl; + i = TEST_STREAM_TBL_SIZE - 1; + } else { + sock_type_str = "SOCK_DGRAM"; + tf = test_dgram_tbl; + i = TEST_DGRAM_TBL_SIZE - 1; + } + if (testno1 == 0) { + testno1 = 1; + testno2 = i; + } else + testno2 = testno1; + output("Running tests for %s sockets:\n", sock_type_str); nfailed1 = 0; - for (i = testno1; i <= testno2; ++test_func, ++i) { - output(" %s\n", test_func->desc); - switch (test_func->func()) { + for (i = testno1, tf += testno1; i <= testno2; ++tf, ++i) { + output(" %u: %s\n", i, tf->desc); + switch (tf->func()) { case -1: ++nfailed1; break; @@ -300,22 +337,35 @@ struct sigaction sa; sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - if (sigaction(SIGPIPE, &sa, (struct sigaction *)NULL) < 0) + if (sigaction(SIGPIPE, &sa, (struct sigaction *)NULL) < 0) err(EX_OSERR, "sigaction(SIGPIPE)"); sa.sa_handler = sig_alrm; + sigemptyset(&sa.sa_mask); if (sigaction(SIGALRM, &sa, (struct sigaction *)NULL) < 0) err(EX_OSERR, "sigaction(SIGALRM)"); } +static int +fork_client(void) +{ + client_pid = fork(); + if (client_pid == 0) + myname = "CLIENT"; + else if (client_pid == (pid_t)-1) { + logmsg("fork"); + return (-1); + } + return (0); +} + int main(int argc, char *argv[]) { const char *errstr; - int opt, dgramflag, streamflag; - u_int testno1, testno2; + u_int testno; + int opt, rv, dgramflag, streamflag; dgramflag = streamflag = 0; while ((opt = getopt(argc, argv, "dht:z")) != -1) @@ -332,7 +382,7 @@ else if (strcmp(optarg, "dgram") == 0) dgramflag = 1; else - errx(EX_USAGE, "wrong socket type in -t option"); + errx(EX_USAGE, "option -t: wrong socket type"); break; case 'z': no_control_data = 1; @@ -346,38 +396,40 @@ if (optind < argc) { if (optind + 1 != argc) errx(EX_USAGE, "too many arguments"); - testno1 = strtonum(argv[optind], 0, UINT_MAX, &errstr); + testno = strtonum(argv[optind], 0, UINT_MAX, &errstr); if (errstr != NULL) errx(EX_USAGE, "wrong test number: %s", errstr); } else - testno1 = 0; + testno = 0; if (dgramflag == 0 && streamflag == 0) dgramflag = streamflag = 1; - if (dgramflag && streamflag && testno1 != 0) - errx(EX_USAGE, "you can use particular test, only with datagram or stream sockets"); + if (dgramflag && streamflag && testno != 0) + errx(EX_USAGE, "you can use particular test, only with " + "datagram or stream sockets"); if (streamflag) { - if (testno1 > TEST_STREAM_NO_MAX) - errx(EX_USAGE, "given test %u for stream sockets does not exist", - testno1); + if (testno >= TEST_STREAM_TBL_SIZE) + errx(EX_USAGE, "given test %u for stream sockets " + "does not exist", testno); } else { - if (testno1 > TEST_DGRAM_NO_MAX) - errx(EX_USAGE, "given test %u for datagram sockets does not exist", - testno1); + if (testno >= TEST_DGRAM_TBL_SIZE) + errx(EX_USAGE, "given test %u for datagram sockets " + "does not exist", testno); } my_uid = getuid(); my_euid = geteuid(); my_gid = getgid(); my_egid = getegid(); - switch (my_ngids = getgroups(sizeof(my_gids) / sizeof(my_gids[0]), my_gids)) { + my_ngids = getgroups(sizeof(my_gids) / sizeof(my_gids[0]), my_gids); + switch (my_ngids) { case -1: err(EX_SOFTWARE, "getgroups"); /* NOTREACHED */ case 0: - errx(EX_OSERR, "getgroups returned 0 groups"); + errx(EX_OSERR, "getgroups returned no groups"); } sig_init(); @@ -385,42 +437,21 @@ if (mkdtemp(tempdir) == NULL) err(EX_OSERR, "mkdtemp"); - if (streamflag) { - sock_type = SOCK_STREAM; - sock_type_str = "SOCK_STREAM"; - if (testno1 == 0) { - testno1 = 1; - testno2 = TEST_STREAM_NO_MAX; - } else - testno2 = testno1; - if (run_tests(testno1, testno2) < 0) - goto failed; - testno1 = 0; - } - - if (dgramflag) { - sock_type = SOCK_DGRAM; - sock_type_str = "SOCK_DGRAM"; - if (testno1 == 0) { - testno1 = 1; - testno2 = TEST_DGRAM_NO_MAX; - } else - testno2 = testno1; - if (run_tests(testno1, testno2) < 0) - goto failed; - } + myname = "SERVER"; + rv = EX_OK; + if (streamflag) + if (run_tests(SOCK_STREAM, testno) < 0) + rv = EX_OSERR; + if (dgramflag && rv == EX_OK) + if (run_tests(SOCK_DGRAM, testno) < 0) + rv = EX_OSERR; if (rmdir(tempdir) < 0) { logmsg("rmdir(%s)", tempdir); - return (EX_OSERR); + rv = EX_OSERR; } - return (nfailed ? EX_OSERR : EX_OK); - -failed: - if (rmdir(tempdir) < 0) - logmsg("rmdir(%s)", tempdir); - return (EX_OSERR); + return (nfailed ? EX_OSERR : rv); } /* @@ -433,27 +464,30 @@ { int rv, fd; - if ((fd = socket(PF_LOCAL, sock_type, 0)) < 0) { + fd = socket(PF_LOCAL, sock_type, 0); + if (fd < 0) { logmsg("create_socket: socket(PF_LOCAL, %s, 0)", sock_type_str); return (-1); } if (sock_path != NULL) { - if ((rv = snprintf(sock_path, sock_path_len, "%s/%s", - tempdir, myname)) < 0) { + rv = snprintf(sock_path, sock_path_len, "%s/%s", tempdir, + myname); + if (rv < 0) { logmsg("create_socket: snprintf failed"); goto failed; } if ((size_t)rv >= sock_path_len) { - logmsgx("create_socket: too long path name for given buffer"); + logmsgx("create_socket: too long path name for given " + "buffer"); goto failed; } memset(addr, 0, sizeof(addr)); addr->sun_family = AF_LOCAL; if (strlen(sock_path) >= sizeof(addr->sun_path)) { - logmsgx("create_socket: too long path name (>= %lu) for local domain socket", - (u_long)sizeof(addr->sun_path)); + logmsgx("create_socket: too long path name (>= %zu) " + "for local domain socket", sizeof(addr->sun_path)); goto failed; } strcpy(addr->sun_path, sock_path); @@ -479,7 +513,8 @@ static int create_server_socket(void) { - return (create_socket(serv_sock_path, sizeof(serv_sock_path), &servaddr)); + return (create_socket(serv_sock_path, sizeof(serv_sock_path), + &servaddr)); } /* @@ -498,12 +533,13 @@ static int close_socket(const char *sock_path, int fd) { - int error = 0; + int error; if (close(fd) < 0) { logmsg("close_socket: close"); error = -1; - } + } else + error = 0; if (sock_path != NULL) if (unlink(sock_path) < 0) { logmsg("close_socket: unlink(%s)", sock_path); @@ -540,17 +576,16 @@ { ssize_t nsent; - dbgmsg(("sending %lu bytes", (u_long)n)); + dbgmsg(("sending %zu bytes", n)); if (sigsetjmp(env_alrm, 1) != 0) { - logmsgx("sendmsg_timeout: cannot send message to %s (timeout)", serv_sock_path); + logmsgx("sendmsg_timeout: cannot send message to %s (timeout)", + serv_sock_path); return (-1); } (void)alarm(TIMEOUT); - nsent = sendmsg(fd, msg, 0); - (void)alarm(0); if (nsent < 0) { @@ -559,8 +594,8 @@ } if ((size_t)nsent != n) { - logmsgx("sendmsg_timeout: sendmsg: short send: %ld of %lu bytes", - (long)nsent, (u_long)n); + logmsgx("sendmsg_timeout: sendmsg: short send: %zd of %zu " + "bytes", nsent, n); return (-1); } @@ -583,9 +618,7 @@ } (void)alarm(TIMEOUT); - fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL); - (void)alarm(0); if (fd < 0) { @@ -604,7 +637,7 @@ { ssize_t nread; - dbgmsg(("receiving %lu bytes", (u_long)n)); + dbgmsg(("receiving %zu bytes", n)); if (sigsetjmp(env_alrm, 1) != 0) { logmsgx("recvmsg_timeout: cannot receive message (timeout)"); @@ -612,9 +645,7 @@ } (void)alarm(TIMEOUT); - nread = recvmsg(fd, msg, MSG_WAITALL); - (void)alarm(0); if (nread < 0) { @@ -623,8 +654,8 @@ } if ((size_t)nread != n) { - logmsgx("recvmsg_timeout: recvmsg: short read: %ld of %lu bytes", - (long)nread, (u_long)n); + logmsgx("recvmsg_timeout: recvmsg: short read: %zd of %zu " + "bytes", nread, n); return (-1); } @@ -648,9 +679,7 @@ } (void)alarm(TIMEOUT); - nread = read(fd, &buf, 1); - (void)alarm(0); if (nread < 0) { @@ -659,8 +688,7 @@ } if (nread != 1) { - logmsgx("sync_recv: read: short read: %ld of 1 byte", - (long)nread); + logmsgx("sync_recv: read: short read: %zd of 1 byte", nread); return (-1); } @@ -683,9 +711,7 @@ } (void)alarm(TIMEOUT); - nsent = write(fd, "", 1); - (void)alarm(0); if (nsent < 0) { @@ -694,8 +720,7 @@ } if (nsent != 1) { - logmsgx("sync_send: write: short write: %ld of 1 byte", - (long)nsent); + logmsgx("sync_send: write: short write: %zd of 1 byte", nsent); return (-1); } @@ -712,15 +737,13 @@ pid_t pid; if (sigsetjmp(env_alrm, 1) != 0) { - logmsgx("wait_client: cannot get exit status of client PID %ld (timeout)", - (long)client_pid); + logmsgx("wait_client: cannot get exit status of client " + "PID %ld (timeout)", (long)client_pid); return (-1); } - (void)alarm(TIMEOUT); - + (void)alarm(TIMEOUT * 2); pid = waitpid(client_pid, &status, 0); - (void)alarm(0); if (pid == (pid_t)-1) { @@ -730,17 +753,19 @@ if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) { - logmsgx("wait_client: exit status of client PID %ld is %d", - (long)client_pid, WEXITSTATUS(status)); + logmsgx("wait_client: exit status of client PID %ld " + "is %d", (long)client_pid, WEXITSTATUS(status)); return (-1); } } else { if (WIFSIGNALED(status)) - logmsgx("wait_client: abnormal termination of client PID %ld, signal %d%s", - (long)client_pid, WTERMSIG(status), WCOREDUMP(status) ? " (core file generated)" : ""); + logmsgx("wait_client: abnormal termination of client " + "PID %ld, signal %d%s", (long)client_pid, + WTERMSIG(status), WCOREDUMP(status) ? + " (core file generated)" : ""); else - logmsgx("wait_client: termination of client PID %ld, unknown status", - (long)client_pid); + logmsgx("wait_client: termination of client PID %ld, " + "unknown status", (long)client_pid); return (-1); } @@ -754,12 +779,12 @@ static int check_groups(const gid_t *gids, int n) { + int i, j, error; char match[NGROUPS_MAX] = { 0 }; - int error, i, j; if (n != my_ngids - 1) { - logmsgx("wrong number of groups %d != %d (returned from getgroups() - 1)", - n, my_ngids - 1); + logmsgx("wrong number of groups %d != %d (returned from " + "getgroups() - 1)", n, my_ngids - 1); error = -1; } else error = 0; @@ -782,7 +807,8 @@ } for (j = 1; j < my_ngids; ++j) if (match[j] == 0) { - logmsgx("did not receive supplementary GID %u", my_gids[j]); + logmsgx("did not receive supplementary GID %lu", + (u_long)my_gids[j]); error = -1; } return (error); @@ -802,16 +828,19 @@ struct msghdr msg; struct iovec iov[1]; struct cmsghdr *cmptr; - int fd; u_int i; + int fd, error; assert(n == 1 || n == 2); - if ((fd = create_unbound_socket()) < 0) + error = 1; + + fd = create_unbound_socket(); + if (fd < 0) goto failed; if (connect_server(fd) < 0) - goto failed_close; + goto done; iov[0].iov_base = ipc_message; iov[0].iov_len = IPC_MESSAGE_SIZE; @@ -835,19 +864,15 @@ dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) - goto failed_close; + goto done; } - if (close_socket((const char *)NULL, fd) < 0) - goto failed; - - _exit(0); - -failed_close: - (void)close_socket((const char *)NULL, fd); - + error = 0; +done: + if (close_socket((char *)NULL, fd)) + error = 1; failed: - _exit(1); + _exit(error); } /* @@ -858,29 +883,28 @@ static int t_cmsgcred_server(int fd1) { - char buf[IPC_MESSAGE_SIZE]; union { struct cmsghdr cm; - char control[CMSG_SPACE(sizeof(struct cmsgcred)) + EXTRA_CMSG_SPACE]; + char control[CMSG_SPACE(sizeof(struct cmsgcred)) + + EXTRA_CMSG_SPACE]; } control_un; struct msghdr msg; struct iovec iov[1]; struct cmsghdr *cmptr; - const struct cmsgcred *cmcredptr; - socklen_t controllen; - int error, error2, fd2; + const struct cmsgcred *cmcred; u_int i; + int fd2, error; + char buf[IPC_MESSAGE_SIZE]; if (sock_type == SOCK_STREAM) { - if ((fd2 = accept_timeout(fd1)) < 0) + fd2 = accept_timeout(fd1); + if (fd2 < 0) return (-2); } else fd2 = fd1; error = 0; - controllen = sizeof(control_un.control); - for (i = 0; i < 2; ++i) { iov[0].iov_base = buf; iov[0].iov_len = sizeof(buf); @@ -890,29 +914,31 @@ msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = control_un.control; - msg.msg_controllen = controllen; + msg.msg_controllen = sizeof(control_un.control); msg.msg_flags = 0; - controllen = CMSG_SPACE(sizeof(struct cmsgcred)); - - if (recvmsg_timeout(fd2, &msg, sizeof(buf)) < 0) - goto failed; + if (recvmsg_timeout(fd2, &msg, sizeof(buf)) < 0) { + error = -2; + break; + } if (msg.msg_flags & MSG_CTRUNC) { - logmsgx("#%u control data was truncated, MSG_CTRUNC flag is on", - i); - goto next_error; + logmsgx("#%u control data was truncated, MSG_CTRUNC " + "flag is on", i); + goto next; } if (msg.msg_controllen < sizeof(struct cmsghdr)) { - logmsgx("#%u msg_controllen %u < %lu (sizeof(struct cmsghdr))", - i, (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); - goto next_error; + logmsgx("#%u msg_controllen %u < %zu " + "(sizeof(struct cmsghdr))", i, + (u_int)msg.msg_controllen, sizeof(struct cmsghdr)); + goto next; } - if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { + cmptr = CMSG_FIRSTHDR(&msg); + if (cmptr == NULL) { logmsgx("CMSG_FIRSTHDR is NULL"); - goto next_error; + goto next; } dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, @@ -921,96 +947,90 @@ if (cmptr->cmsg_level != SOL_SOCKET) { logmsgx("#%u cmsg_level %d != SOL_SOCKET", i, cmptr->cmsg_level); - goto next_error; + goto next; } if (cmptr->cmsg_type != SCM_CREDS) { logmsgx("#%u cmsg_type %d != SCM_CREDS", i, cmptr->cmsg_type); - goto next_error; + goto next; } if (cmptr->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred))) { - logmsgx("#%u cmsg_len %u != %lu (CMSG_LEN(sizeof(struct cmsgcred))", - i, (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(sizeof(struct cmsgcred))); - goto next_error; + logmsgx("#%u cmsg_len %u != %zu " + "(CMSG_LEN(sizeof(struct cmsgcred))", i, + (u_int)cmptr->cmsg_len, + CMSG_LEN(sizeof(struct cmsgcred))); + goto next; } - cmcredptr = (const struct cmsgcred *)CMSG_DATA(cmptr); + cmcred = (struct cmsgcred *)CMSG_DATA(cmptr); - error2 = 0; - if (cmcredptr->cmcred_pid != client_pid) { + if (cmcred->cmcred_pid != client_pid) { logmsgx("#%u cmcred_pid %ld != %ld (PID of client)", - i, (long)cmcredptr->cmcred_pid, (long)client_pid); - error2 = 1; + i, (long)cmcred->cmcred_pid, (long)client_pid); + goto next; } - if (cmcredptr->cmcred_uid != my_uid) { - logmsgx("#%u cmcred_uid %lu != %lu (UID of current process)", - i, (u_long)cmcredptr->cmcred_uid, (u_long)my_uid); - error2 = 1; - } - if (cmcredptr->cmcred_euid != my_euid) { - logmsgx("#%u cmcred_euid %lu != %lu (EUID of current process)", - i, (u_long)cmcredptr->cmcred_euid, (u_long)my_euid); - error2 = 1; - } - if (cmcredptr->cmcred_gid != my_gid) { - logmsgx("#%u cmcred_gid %lu != %lu (GID of current process)", - i, (u_long)cmcredptr->cmcred_gid, (u_long)my_gid); - error2 = 1; + if (cmcred->cmcred_uid != my_uid) { + logmsgx("#%u cmcred_uid %lu != %lu (UID of current " + "process)", i, (u_long)cmcred->cmcred_uid, + (u_long)my_uid); + goto next; + } + if (cmcred->cmcred_euid != my_euid) { + logmsgx("#%u cmcred_euid %lu != %lu (EUID of current " + "process)", i, (u_long)cmcred->cmcred_euid, + (u_long)my_euid); + goto next; + } + if (cmcred->cmcred_gid != my_gid) { + logmsgx("#%u cmcred_gid %lu != %lu (GID of current " + "process)", i, (u_long)cmcred->cmcred_gid, + (u_long)my_gid); + goto next; } - if (cmcredptr->cmcred_ngroups == 0) { + if (cmcred->cmcred_ngroups == 0) { logmsgx("#%u cmcred_ngroups = 0, this is wrong", i); - error2 = 1; - } else { - if (cmcredptr->cmcred_ngroups > NGROUPS_MAX) { - logmsgx("#%u cmcred_ngroups %d > %u (NGROUPS_MAX)", - i, cmcredptr->cmcred_ngroups, NGROUPS_MAX); - error2 = 1; - } else if (cmcredptr->cmcred_ngroups < 0) { - logmsgx("#%u cmcred_ngroups %d < 0", - i, cmcredptr->cmcred_ngroups); - error2 = 1; - } else { - dbgmsg(("#%u cmcred_ngroups = %d", i, - cmcredptr->cmcred_ngroups)); - if (cmcredptr->cmcred_groups[0] != my_egid) { - logmsgx("#%u cmcred_groups[0] %lu != %lu (EGID of current process)", - i, (u_long)cmcredptr->cmcred_groups[0], (u_long)my_egid); - error2 = 1; - } - if (check_groups(cmcredptr->cmcred_groups + 1, cmcredptr->cmcred_ngroups - 1) < 0) { - logmsgx("#%u cmcred_groups has wrong GIDs", i); - error2 = 1; - } - } + goto next; } - - if (error2) - goto next_error; - - if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { - logmsgx("#%u control data has extra header", i); - goto next_error; + if (cmcred->cmcred_ngroups > NGROUPS_MAX) { + logmsgx("#%u cmcred_ngroups %d > %u (NGROUPS_MAX)", + i, cmcred->cmcred_ngroups, NGROUPS_MAX); + goto next; + } + if (cmcred->cmcred_ngroups < 0) { + logmsgx("#%u cmcred_ngroups %d < 0", i, + cmcred->cmcred_ngroups); + goto next; + } + + dbgmsg(("#%u cmcred_ngroups = %d", i, cmcred->cmcred_ngroups)); + if (cmcred->cmcred_groups[0] != my_egid) { + logmsgx("#%u cmcred_groups[0] %lu != %lu (EGID of " + "current process)", i, + (u_long)cmcred->cmcred_groups[0], (u_long)my_egid); + goto next; + } + if (check_groups(cmcred->cmcred_groups + 1, + cmcred->cmcred_ngroups - 1) < 0) { + logmsgx("#%u cmcred_groups has wrong GIDs", i); + goto next; + } + + if (CMSG_NXTHDR(&msg, cmptr) != NULL) { + logmsgx("#%u control data has extra header, this is " + "wrong", i); + goto next; } - continue; -next_error: +next: error = -1; } if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) { - logmsg("close"); - return (-2); - } + if (close_socket((char *)NULL, fd2) < 0) + error = -2; return (error); - -failed: - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) - logmsg("close"); - return (-2); } static int @@ -1018,45 +1038,35 @@ { int error, fd; - if ((fd = create_server_socket()) < 0) + fd = create_server_socket(); + if (fd < 0) return (-2); + error = -2; + if (sock_type == SOCK_STREAM) if (listen(fd, LISTENQ) < 0) { logmsg("listen"); - goto failed; + goto done; } - if ((client_pid = fork()) == (pid_t)-1) { - logmsg("fork"); - goto failed; - } + if (fork_client() < 0) + goto done; if (client_pid == 0) { - myname = "CLIENT"; - if (close_socket((const char *)NULL, fd) < 0) + if (close_socket((char *)NULL, fd) < 0) _exit(1); t_cmsgcred_client(2); } - if ((error = t_cmsgcred_server(fd)) == -2) { - (void)wait_client(); - goto failed; - } + error = t_cmsgcred_server(fd); if (wait_client() < 0) - goto failed; - - if (close_socket(serv_sock_path, fd) < 0) { - logmsgx("close_socket failed"); - return (-2); - } - return (error); - -failed: + error = -2; +done: if (close_socket(serv_sock_path, fd) < 0) - logmsgx("close_socket failed"); - return (-2); + error = -2; + return (error); } /* @@ -1067,20 +1077,23 @@ { struct msghdr msg; struct iovec iov[1]; - int fd; u_int i; + int fd, error; assert(type == 0 || type == 1); - if ((fd = create_unbound_socket()) < 0) + error = 1; + + fd = create_unbound_socket(); + if (fd < 0) goto failed; if (connect_server(fd) < 0) - goto failed_close; + goto done; if (type == 1) if (sync_recv(fd) < 0) - goto failed_close; + goto done; iov[0].iov_base = ipc_message; iov[0].iov_len = IPC_MESSAGE_SIZE; @@ -1095,18 +1108,14 @@ for (i = 0; i < 2; ++i) if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) - goto failed_close; - - if (close_socket((const char *)NULL, fd) < 0) - goto failed; - - _exit(0); - -failed_close: - (void)close_socket((const char *)NULL, fd); + goto done; + error = 0; +done: + if (close_socket((char *)NULL, fd) < 0) + error = 1; failed: - _exit(1); + _exit(error); } /* @@ -1122,33 +1131,37 @@ char buf[IPC_MESSAGE_SIZE]; union { struct cmsghdr cm; - char control[CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX)) + EXTRA_CMSG_SPACE]; + char control[CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX)) + + EXTRA_CMSG_SPACE]; } control_un; struct msghdr msg; struct iovec iov[1]; struct cmsghdr *cmptr; const struct sockcred *sockcred; - int error, error2, fd2, optval; u_int i; + int fd2, error, optval; assert(n == 1 || n == 2); assert(type == 0 || type == 1); + error = -2; + if (sock_type == SOCK_STREAM) { - if ((fd2 = accept_timeout(fd1)) < 0) + fd2 = accept_timeout(fd1); + if (fd2 < 0) return (-2); if (type == 1) { optval = 1; - if (setsockopt(fd2, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { - logmsg("setsockopt(LOCAL_CREDS) for accepted socket"); - if (errno == ENOPROTOOPT) { + if (setsockopt(fd2, 0, LOCAL_CREDS, &optval, + sizeof(optval)) < 0) { + logmsg("setsockopt(LOCAL_CREDS) for accepted " + "socket"); + if (errno == ENOPROTOOPT) error = -1; - goto done_close; - } - goto failed; + goto done; } if (sync_send(fd2) < 0) - goto failed; + goto done; } } else fd2 = fd1; @@ -1157,132 +1170,131 @@ for (i = 0; i < n; ++i) { iov[0].iov_base = buf; - iov[0].iov_len = sizeof buf; + iov[0].iov_len = sizeof(buf); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = control_un.control; - msg.msg_controllen = sizeof control_un.control; + msg.msg_controllen = sizeof(control_un.control); msg.msg_flags = 0; - if (recvmsg_timeout(fd2, &msg, sizeof buf) < 0) - goto failed; + if (recvmsg_timeout(fd2, &msg, sizeof(buf)) < 0) { + error = -2; + break; + } if (msg.msg_flags & MSG_CTRUNC) { - logmsgx("control data was truncated, MSG_CTRUNC flag is on"); - goto next_error; + logmsgx("control data was truncated, MSG_CTRUNC flag " + "is on"); + goto next; } + dbgmsg(("#%u msg_controllen = %u", i, + (u_int)msg.msg_controllen)); + if (i != 0 && sock_type == SOCK_STREAM) { if (msg.msg_controllen != 0) { - logmsgx("second message has control data, this is wrong for stream sockets"); - goto next_error; + logmsgx("second message has control data, " + "this is wrong for stream sockets"); + goto next; } - dbgmsg(("#%u msg_controllen = %u", i, - (u_int)msg.msg_controllen)); continue; } if (msg.msg_controllen < sizeof(struct cmsghdr)) { - logmsgx("#%u msg_controllen %u < %lu (sizeof(struct cmsghdr))", - i, (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); - goto next_error; + logmsgx("#%u msg_controllen %u < %zu " + "(sizeof(struct cmsghdr))", i, + (u_int)msg.msg_controllen, sizeof(struct cmsghdr)); + goto next; } - if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { + cmptr = CMSG_FIRSTHDR(&msg); + if (cmptr == NULL) { logmsgx("CMSG_FIRSTHDR is NULL"); - goto next_error; + goto next; } - dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, - (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); + dbgmsg(("#%u cmsg_len = %u", i, (u_int)cmptr->cmsg_len)); if (cmptr->cmsg_level != SOL_SOCKET) { logmsgx("#%u cmsg_level %d != SOL_SOCKET", i, cmptr->cmsg_level); - goto next_error; + goto next; } if (cmptr->cmsg_type != SCM_CREDS) { logmsgx("#%u cmsg_type %d != SCM_CREDS", i, cmptr->cmsg_type); - goto next_error; + goto next; } if (cmptr->cmsg_len < CMSG_LEN(SOCKCREDSIZE(1))) { - logmsgx("#%u cmsg_len %u != %lu (CMSG_LEN(SOCKCREDSIZE(1)))", - i, (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(SOCKCREDSIZE(1))); - goto next_error; + logmsgx("#%u cmsg_len %u != %zu " + "(CMSG_LEN(SOCKCREDSIZE(1)))", i, + (u_int)cmptr->cmsg_len, CMSG_LEN(SOCKCREDSIZE(1))); + goto next; } - sockcred = (const struct sockcred *)CMSG_DATA(cmptr); + sockcred = (struct sockcred *)CMSG_DATA(cmptr); - error2 = 0; if (sockcred->sc_uid != my_uid) { - logmsgx("#%u sc_uid %lu != %lu (UID of current process)", - i, (u_long)sockcred->sc_uid, (u_long)my_uid); - error2 = 1; + logmsgx("#%u sc_uid %lu != %lu (UID of current " + "process)", i, (u_long)sockcred->sc_uid, + (u_long)my_uid); + goto next; } if (sockcred->sc_euid != my_euid) { - logmsgx("#%u sc_euid %lu != %lu (EUID of current process)", - i, (u_long)sockcred->sc_euid, (u_long)my_euid); - error2 = 1; + logmsgx("#%u sc_euid %lu != %lu (EUID of current " + "process)", i, (u_long)sockcred->sc_euid, + (u_long)my_euid); + goto next; } if (sockcred->sc_gid != my_gid) { - logmsgx("#%u sc_gid %lu != %lu (GID of current process)", - i, (u_long)sockcred->sc_gid, (u_long)my_gid); - error2 = 1; + logmsgx("#%u sc_gid %lu != %lu (GID of current " + "process)", i, (u_long)sockcred->sc_gid, + (u_long)my_gid); + goto next; } if (sockcred->sc_egid != my_egid) { - logmsgx("#%u sc_egid %lu != %lu (EGID of current process)", - i, (u_long)sockcred->sc_gid, (u_long)my_egid); - error2 = 1; + logmsgx("#%u sc_egid %lu != %lu (EGID of current " + "process)", i, (u_long)sockcred->sc_gid, + (u_long)my_egid); + goto next; } if (sockcred->sc_ngroups > NGROUPS_MAX) { logmsgx("#%u sc_ngroups %d > %u (NGROUPS_MAX)", i, sockcred->sc_ngroups, NGROUPS_MAX); - error2 = 1; - } else if (sockcred->sc_ngroups < 0) { - logmsgx("#%u sc_ngroups %d < 0", - i, sockcred->sc_ngroups); - error2 = 1; - } else { - dbgmsg(("#%u sc_ngroups = %d", i, sockcred->sc_ngroups)); - if (check_groups(sockcred->sc_groups, sockcred->sc_ngroups) < 0) { - logmsgx("#%u sc_groups has wrong GIDs", i); - error2 = 1; - } + goto next; + } + if (sockcred->sc_ngroups < 0) { + logmsgx("#%u sc_ngroups %d < 0", i, + sockcred->sc_ngroups); + goto next; } - if (error2) - goto next_error; - - if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { - logmsgx("#%u control data has extra header, this is wrong", - i); - goto next_error; + dbgmsg(("#%u sc_ngroups = %d", i, sockcred->sc_ngroups)); + if (check_groups(sockcred->sc_groups, + sockcred->sc_ngroups) < 0) { + logmsgx("#%u sc_groups has wrong GIDs", i); + goto next; } + if (CMSG_NXTHDR(&msg, cmptr) != NULL) { + logmsgx("#%u control data has extra header, this is " + "wrong", i); + goto next; + } continue; -next_error: +next: error = -1; } - -done_close: +done: if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) { - logmsg("close"); - return (-2); - } + if (close_socket((char *)NULL, fd2) < 0) + error = -2; return (error); - -failed: - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) - logmsg("close"); - return (-2); } static int @@ -1292,59 +1304,47 @@ assert(type == 0 || type == 1); - if ((fd = create_server_socket()) < 0) + fd = create_server_socket(); + if (fd < 0) return (-2); + error = -2; + if (sock_type == SOCK_STREAM) if (listen(fd, LISTENQ) < 0) { logmsg("listen"); - goto failed; + goto done; } if (type == 0) { optval = 1; - if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { + if (setsockopt(fd, 0, LOCAL_CREDS, &optval, + sizeof(optval)) < 0) { logmsg("setsockopt(LOCAL_CREDS) for %s socket", - sock_type == SOCK_STREAM ? "stream listening" : "datagram"); - if (errno == ENOPROTOOPT) { + sock_type_str); + if (errno == ENOPROTOOPT) error = -1; - goto done_close; - } - goto failed; + goto done; } } - if ((client_pid = fork()) == (pid_t)-1) { - logmsg("fork"); - goto failed; - } + if (fork_client() < 0) + goto done; if (client_pid == 0) { - myname = "CLIENT"; - if (close_socket((const char *)NULL, fd) < 0) + if (close_socket((char *)NULL, fd) < 0) _exit(1); t_sockcred_client(type); } - if ((error = t_sockcred_server(type, fd, 2)) == -2) { - (void)wait_client(); - goto failed; - } + error = t_sockcred_server(type, fd, 2); if (wait_client() < 0) - goto failed; - -done_close: - if (close_socket(serv_sock_path, fd) < 0) { - logmsgx("close_socket failed"); - return (-2); - } - return (error); - -failed: + error = -2; +done: if (close_socket(serv_sock_path, fd) < 0) - logmsgx("close_socket failed"); - return (-2); + error = -2; + return (error); } static int @@ -1368,59 +1368,45 @@ static int t_cmsgcred_sockcred(void) { - int error, fd, optval; + int fd, error, optval; - if ((fd = create_server_socket()) < 0) + fd = create_server_socket(); + if (fd < 0) return (-2); + error = -2; + if (sock_type == SOCK_STREAM) if (listen(fd, LISTENQ) < 0) { logmsg("listen"); - goto failed; + goto done; } optval = 1; - if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { - logmsg("setsockopt(LOCAL_CREDS) for %s socket", - sock_type == SOCK_STREAM ? "stream listening" : "datagram"); - if (errno == ENOPROTOOPT) { + if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof(optval)) < 0) { + logmsg("setsockopt(LOCAL_CREDS) for %s socket", sock_type_str); + if (errno == ENOPROTOOPT) error = -1; - goto done_close; - } - goto failed; + goto done; } - if ((client_pid = fork()) == (pid_t)-1) { - logmsg("fork"); - goto failed; - } + if (fork_client() < 0) + goto done; if (client_pid == 0) { - myname = "CLIENT"; - if (close_socket((const char *)NULL, fd) < 0) + if (close_socket((char *)NULL, fd) < 0) _exit(1); t_cmsgcred_client(1); } - if ((error = t_sockcred_server(0, fd, 1)) == -2) { - (void)wait_client(); - goto failed; - } + error = t_sockcred_server(0, fd, 1); if (wait_client() < 0) - goto failed; - -done_close: - if (close_socket(serv_sock_path, fd) < 0) { - logmsgx("close_socket failed"); - return (-2); - } - return (error); - -failed: + error = -2; +done: if (close_socket(serv_sock_path, fd) < 0) - logmsgx("close_socket failed"); - return (-2); + error = -2; + return (error); } /* @@ -1437,13 +1423,16 @@ struct msghdr msg; struct iovec iov[1]; struct cmsghdr *cmptr; - int fd; + int fd, error; - if ((fd = create_unbound_socket()) < 0) + error = 1; + + fd = create_unbound_socket(); + if (fd < 0) goto failed; if (connect_server(fd) < 0) - goto failed_close; + goto done; iov[0].iov_base = ipc_message; iov[0].iov_len = IPC_MESSAGE_SIZE; @@ -1454,7 +1443,7 @@ msg.msg_iovlen = 1; msg.msg_control = control_un.control; msg.msg_controllen = no_control_data ? - sizeof(struct cmsghdr) :sizeof control_un.control; + sizeof(struct cmsghdr) : sizeof(control_un.control); msg.msg_flags = 0; cmptr = CMSG_FIRSTHDR(&msg); @@ -1467,18 +1456,14 @@ (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) - goto failed_close; - - if (close_socket((const char *)NULL, fd) < 0) - goto failed; - - _exit(0); - -failed_close: - (void)close_socket((const char *)NULL, fd); + goto done; + error = 0; +done: + if (close_socket((char *)NULL, fd) < 0) + error = 1; failed: - _exit(1); + _exit(error); } /* @@ -1490,34 +1475,38 @@ { union { struct cmsghdr cm; - char control[CMSG_SPACE(sizeof(struct timeval)) + EXTRA_CMSG_SPACE]; + char control[CMSG_SPACE(sizeof(struct timeval)) + + EXTRA_CMSG_SPACE]; } control_un; - char buf[IPC_MESSAGE_SIZE]; - int error, fd2; struct msghdr msg; struct iovec iov[1]; struct cmsghdr *cmptr; const struct timeval *timeval; + int error, fd2; + char buf[IPC_MESSAGE_SIZE]; if (sock_type == SOCK_STREAM) { - if ((fd2 = accept_timeout(fd1)) < 0) + fd2 = accept_timeout(fd1); + if (fd2 < 0) return (-2); } else fd2 = fd1; iov[0].iov_base = buf; - iov[0].iov_len = sizeof buf; + iov[0].iov_len = sizeof(buf); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = control_un.control; - msg.msg_controllen = sizeof control_un.control;; + msg.msg_controllen = sizeof(control_un.control); msg.msg_flags = 0; - if (recvmsg_timeout(fd2, &msg, sizeof buf) < 0) - goto failed; + if (recvmsg_timeout(fd2, &msg, sizeof(buf)) < 0) { + error = -2; + goto done; + } error = -1; @@ -1527,12 +1516,13 @@ } if (msg.msg_controllen < sizeof(struct cmsghdr)) { - logmsgx("msg_controllen %u < %lu (sizeof(struct cmsghdr))", - (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); + logmsgx("msg_controllen %u < %zu (sizeof(struct cmsghdr))", + (u_int)msg.msg_controllen, sizeof(struct cmsghdr)); goto done; } - if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { + cmptr = CMSG_FIRSTHDR(&msg); + if (cmptr == NULL) { logmsgx("CMSG_FIRSTHDR is NULL"); goto done; } @@ -1551,36 +1541,27 @@ } if (cmptr->cmsg_len != CMSG_LEN(sizeof(struct timeval))) { - logmsgx("cmsg_len %u != %lu (CMSG_LEN(sizeof(struct timeval))", - (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(sizeof(struct timeval))); + logmsgx("cmsg_len %u != %zu (CMSG_LEN(sizeof(struct timeval))", + (u_int)cmptr->cmsg_len, CMSG_LEN(sizeof(struct timeval))); goto done; } - timeval = (const struct timeval *)CMSG_DATA(cmptr); + timeval = (struct timeval *)CMSG_DATA(cmptr); dbgmsg(("timeval tv_sec %jd, tv_usec %jd", (intmax_t)timeval->tv_sec, (intmax_t)timeval->tv_usec)); - if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { - logmsgx("control data has extra header"); + if (CMSG_NXTHDR(&msg, cmptr) != NULL) { + logmsgx("control data has extra header, this is wrong"); goto done; } error = 0; - done: if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) { - logmsg("close"); - return (-2); - } + if (close_socket((char *)NULL, fd2) < 0) + error = -2; return (error); - -failed: - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) - logmsg("close"); - return (-2); } static int @@ -1588,43 +1569,174 @@ { int error, fd; - if ((fd = create_server_socket()) < 0) + fd = create_server_socket(); + if (fd < 0) return (-2); + error = -2; + if (sock_type == SOCK_STREAM) if (listen(fd, LISTENQ) < 0) { logmsg("listen"); - goto failed; + goto done; } - if ((client_pid = fork()) == (pid_t)-1) { - logmsg("fork"); - goto failed; - } + if (fork_client() < 0) + goto done; if (client_pid == 0) { - myname = "CLIENT"; - if (close_socket((const char *)NULL, fd) < 0) + if (close_socket((char *)NULL, fd) < 0) _exit(1); t_timestamp_client(); } - if ((error = t_timestamp_server(fd)) == -2) { - (void)wait_client(); - goto failed; - } + error = t_timestamp_server(fd); if (wait_client() < 0) + error = -2; +done: + if (close_socket(serv_sock_path, fd) < 0) + error = -2; + return (error); +} + +/* + * Verify that xucred structure has correct credentials. + */ +static int +check_xucred(const struct xucred *xuc) +{ + if (xuc->cr_version != XUCRED_VERSION) { + logmsgx("cr_version %u != %d (XUCRED_VERSION)", + xuc->cr_version, XUCRED_VERSION); + return (-1); + } + if (xuc->cr_uid != my_euid) { + logmsgx("cr_uid %lu != %lu (EUID of current process)", + (u_long)xuc->cr_uid, (u_long)my_euid); + return (-1); + } + if (xuc->cr_ngroups == 0) { + logmsgx("cr_ngroups = 0, this is wrong"); + return (-1); + } + if (xuc->cr_ngroups > NGROUPS) { + logmsgx("cr_ngroups %hu > %d (NGROUPS)", + xuc->cr_ngroups, NGROUPS); + return (-1); + } + if (xuc->cr_groups[0] != my_egid) { + logmsgx("cr_groups[0] %lu != %lu (EGID of current process)", + (u_long)xuc->cr_groups[0], (u_long)my_egid); + return (-1); + } + if (check_groups(xuc->cr_groups + 1, xuc->cr_ngroups - 1) < 0) { + logmsgx("cr_groups has wrong GIDs"); + return (-1); + } + return (0); +} + +/* + * Connect to server and set LOCAL_PEERCRED socket option for connected + * socket. Verify that credentials of the peer are correct. + */ +static void +t_peercred_client(void) +{ + struct xucred xuc; + socklen_t len; + int fd, error; + + error = 1; + + fd = create_unbound_socket(); + if (fd < 0) goto failed; - if (close_socket(serv_sock_path, fd) < 0) { - logmsgx("close_socket failed"); + if (connect_server(fd) < 0) + goto done; + + len = sizeof(xuc); + if (getsockopt(fd, 0, LOCAL_PEERCRED, &xuc, &len) < 0) { + logmsg("getsockopt(LOCAL_PEERCRED)"); + goto done; + } + + if (check_xucred(&xuc) < 0) + goto done; +done: + error = close_socket((char *)NULL, fd) < 0 ? 1 : 0; +failed: + _exit(error); +} + +/* + * Accept connection from client and set LOCAL_PEERCRED socket option for + * connected socket. Verify that credentials of the peer are correct. + */ +static int +t_peercred_server(int fd1) +{ + struct xucred xuc; + socklen_t len; + int fd2, error; + + fd2 = accept_timeout(fd1); + if (fd2 < 0) return (-2); + + len = sizeof(xuc); + if (getsockopt(fd2, 0, LOCAL_PEERCRED, &xuc, &len) < 0) { + logmsg("getsockopt(LOCAL_PEERCRED)"); + error = -2; + goto done; } + + if (check_xucred(&xuc) < 0) { + error = -1; + goto done; + } + + error = 0; +done: + if (close_socket((char *)NULL, fd2) < 0) + error = -2; return (error); +} -failed: +static int +t_peercred(void) +{ + int fd, error; + + fd = create_server_socket(); + if (fd < 0) + return (-2); + + error = -2; + + if (sock_type == SOCK_STREAM) + if (listen(fd, LISTENQ) < 0) { + logmsg("listen"); + goto done; + } + + if (fork_client() < 0) + goto done; + + if (client_pid == 0) { + if (close_socket((char *)NULL, fd) < 0) + _exit(1); + t_peercred_client(); + } + + error = t_peercred_server(fd); + + if (wait_client() < 0) + error = -2; +done: if (close_socket(serv_sock_path, fd) < 0) - logmsgx("close_socket failed"); - return (-2); + error = -2; + return (error); } diff -ruN unix_cmsg.orig/unix_cmsg.t unix_cmsg/unix_cmsg.t --- unix_cmsg.orig/unix_cmsg.t 2006-05-29 21:40:55.000000000 +0300 +++ unix_cmsg/unix_cmsg.t 2009-01-30 15:44:49.000000000 +0200 @@ -23,14 +23,15 @@ done } -echo "1..15" +echo "1..16" for desc in \ "Sending, receiving cmsgcred" \ "Receiving sockcred (listening socket has LOCAL_CREDS) # TODO" \ "Receiving sockcred (accepted socket has LOCAL_CREDS) # TODO" \ "Sending cmsgcred, receiving sockcred # TODO" \ - "Sending, receiving timestamp" + "Sending, receiving timestamp" \ + "Check LOCAL_PEERCRED socket option" do n=`expr ${n} + 1` run ${n} stream "" ${n} "STREAM ${desc}" @@ -48,10 +49,10 @@ run ${n} dgram "" ${i} "DGRAM ${desc}" done -run 10 stream -z 1 "STREAM Sending, receiving cmsgcred (no control data)" -run 11 stream -z 4 "STREAM Sending cmsgcred, receiving sockcred (no control data) # TODO" -run 12 stream -z 5 "STREAM Sending, receiving timestamp (no control data)" +run 11 stream -z 1 "STREAM Sending, receiving cmsgcred (no control data)" +run 12 stream -z 4 "STREAM Sending cmsgcred, receiving sockcred (no control data) # TODO" +run 13 stream -z 5 "STREAM Sending, receiving timestamp (no control data)" -run 13 dgram -z 1 "DGRAM Sending, receiving cmsgcred (no control data)" -run 14 dgram -z 3 "DGRAM Sending cmsgcred, receiving sockcred (no control data) # TODO" -run 15 dgram -z 4 "DGRAM Sending, receiving timestamp (no control data)" +run 14 dgram -z 1 "DGRAM Sending, receiving cmsgcred (no control data)" +run 15 dgram -z 3 "DGRAM Sending cmsgcred, receiving sockcred (no control data) # TODO" +run 16 dgram -z 4 "DGRAM Sending, receiving timestamp (no control data)" >Release-Note: >Audit-Trail: >Unformatted: