diff options
| -rw-r--r-- | tests/sys/capsicum/capability-fd.cc | 10 | ||||
| -rw-r--r-- | tests/sys/capsicum/capmode.cc | 2 | ||||
| -rw-r--r-- | tests/sys/capsicum/capsicum-freebsd.h | 15 | ||||
| -rw-r--r-- | tests/sys/capsicum/capsicum-test-main.cc | 8 | ||||
| -rw-r--r-- | tests/sys/capsicum/capsicum-test.h | 36 | ||||
| -rw-r--r-- | tests/sys/capsicum/fexecve.cc | 12 | ||||
| -rw-r--r-- | tests/sys/capsicum/procdesc.cc | 6 | ||||
| -rw-r--r-- | tests/sys/capsicum/sctp.cc | 30 | ||||
| -rw-r--r-- | tests/sys/capsicum/socket.cc | 70 |
9 files changed, 107 insertions, 82 deletions
diff --git a/tests/sys/capsicum/capability-fd.cc b/tests/sys/capsicum/capability-fd.cc index a9e4d30ac4b9..d79f3e4be917 100644 --- a/tests/sys/capsicum/capability-fd.cc +++ b/tests/sys/capsicum/capability-fd.cc @@ -974,6 +974,8 @@ FORK_TEST_ON(Capability, SocketTransfer, TmpFile("cap_fd_transfer")) { pid_t child = fork(); if (child == 0) { + int child_cap_fd; + // Child: enter cap mode EXPECT_OK(cap_enter()); // Child: send startup notification @@ -984,16 +986,16 @@ FORK_TEST_ON(Capability, SocketTransfer, TmpFile("cap_fd_transfer")) { EXPECT_OK(rc); EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen); cmptr = CMSG_FIRSTHDR(&mh); - int cap_fd = *(int*)CMSG_DATA(cmptr); + memcpy(&child_cap_fd, CMSG_DATA(cmptr), sizeof(child_cap_fd)); EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len); cmptr = CMSG_NXTHDR(&mh, cmptr); EXPECT_TRUE(cmptr == NULL); // Child: confirm we can do the right operations on the capability cap_rights_t rights; - EXPECT_OK(cap_rights_get(cap_fd, &rights)); + EXPECT_OK(cap_rights_get(child_cap_fd, &rights)); EXPECT_RIGHTS_EQ(&r_rs, &rights); - TryReadWrite(cap_fd); + TryReadWrite(child_cap_fd); // Child: acknowledge that we have received and tested the file descriptor SEND_INT_MESSAGE(sock_fds[0], MSG_CHILD_FD_RECEIVED); @@ -1024,7 +1026,7 @@ FORK_TEST_ON(Capability, SocketTransfer, TmpFile("cap_fd_transfer")) { cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; cmptr->cmsg_len = CMSG_LEN(sizeof(int)); - *(int *)CMSG_DATA(cmptr) = cap_fd; + memcpy(CMSG_DATA(cmptr), &cap_fd, sizeof(cap_fd)); buffer1[0] = 0; iov[0].iov_len = 1; int rc = sendmsg(sock_fds[1], &mh, 0); diff --git a/tests/sys/capsicum/capmode.cc b/tests/sys/capsicum/capmode.cc index fdc572f11b5b..4cf6f24420e3 100644 --- a/tests/sys/capsicum/capmode.cc +++ b/tests/sys/capsicum/capmode.cc @@ -158,7 +158,7 @@ FORK_TEST_F(WithFiles, AllowedSocketSyscalls) { if (rc < 0) { EXPECT_EQ(EAGAIN, errno); } - char ch; + char ch = 'a'; EXPECT_OK(write(fd_file_, &ch, sizeof(ch))); // These calls will fail for lack of e.g. a proper name to send to, diff --git a/tests/sys/capsicum/capsicum-freebsd.h b/tests/sys/capsicum/capsicum-freebsd.h index 9cb3149a05a4..82ee9cf9d91c 100644 --- a/tests/sys/capsicum/capsicum-freebsd.h +++ b/tests/sys/capsicum/capsicum-freebsd.h @@ -4,15 +4,15 @@ * FreeBSD Capsicum Functionality. ************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif +#include <sys/cdefs.h> + +__BEGIN_DECLS /* FreeBSD definitions. */ -#include <errno.h> #include <sys/param.h> #include <sys/capsicum.h> #include <sys/procdesc.h> +#include <errno.h> #define AT_SYSCALLS_IN_CAPMODE #define HAVE_CAP_RIGHTS_GET @@ -27,9 +27,7 @@ typedef unsigned long cap_ioctl_t; #define HAVE_OPENAT_INTERMEDIATE_DOTDOT -#ifdef __cplusplus -} -#endif +__END_DECLS // Use fexecve_() in tests to allow Linux variant to bypass glibc version. #define fexecve_(F, A, E) fexecve(F, A, E) @@ -50,4 +48,7 @@ typedef unsigned long cap_ioctl_t; // FreeBSD generates a capability from sctp_peeloff(cap_fd,...). #define CAP_FROM_PEELOFF +#define HAVE_PIPE2 +#define HAVE_SEND_RECV_MMSG + #endif /*__CAPSICUM_FREEBSD_H__*/ diff --git a/tests/sys/capsicum/capsicum-test-main.cc b/tests/sys/capsicum/capsicum-test-main.cc index 2a2c75000039..2e9839a755d9 100644 --- a/tests/sys/capsicum/capsicum-test-main.cc +++ b/tests/sys/capsicum/capsicum-test-main.cc @@ -75,12 +75,16 @@ std::string capsicum_test_bindir; // Adds a directory to $PATH. static void AddDirectoryToPath(const char *dir) { char *new_path, *old_path; + int rc [[maybe_unused]]; old_path = getenv("PATH"); assert(old_path); - assert(asprintf(&new_path, "%s:%s", dir, old_path) > 0); - assert(setenv("PATH", new_path, 1) == 0); + rc = asprintf(&new_path, "%s:%s", dir, old_path); + assert(rc != -1); + rc = setenv("PATH", new_path, 1); + assert(rc == 0); + free(new_path); } int main(int argc, char* argv[]) { diff --git a/tests/sys/capsicum/capsicum-test.h b/tests/sys/capsicum/capsicum-test.h index 7433814b31c8..5503a7ef260f 100644 --- a/tests/sys/capsicum/capsicum-test.h +++ b/tests/sys/capsicum/capsicum-test.h @@ -67,7 +67,7 @@ const char *TmpFile(const char *pathname); // Implemented as a macro to allow access to the test case instance's // HasFailure() method, which is reported as the forked process's // exit status. -#define _RUN_FORKED(INNERCODE, TESTCASENAME, TESTNAME) \ +#define _RUN_FORKED(INNERCODE, TESTCASENAME, TESTNAME) do { \ pid_t pid = force_nofork ? 0 : fork(); \ if (pid == 0) { \ INNERCODE; \ @@ -95,10 +95,13 @@ const char *TmpFile(const char *pathname); strerror(errno), errno); \ ADD_FAILURE() << "Failed to wait for child"; \ } else { \ - int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1; \ - EXPECT_EQ(0, rc); \ + int exit_status = \ + WIFEXITED(status) ? WEXITSTATUS(status) : -1; \ + EXPECT_EQ(0, exit_status); \ } \ - } + } \ +} while (0) + #define _RUN_FORKED_MEM(THIS, TESTFN, TESTCASENAME, TESTNAME) \ _RUN_FORKED(MaybeRunWithThread(THIS, &TESTFN), TESTCASENAME, TESTNAME); #define _RUN_FORKED_FN(TESTFN, TESTCASENAME, TESTNAME) \ @@ -137,15 +140,28 @@ const char *TmpFile(const char *pathname); // Emit errno information on failure #define EXPECT_OK(v) EXPECT_LE(0, v) << " errno " << errno << " " << strerror(errno) -// Expect a syscall to fail with the given error. -#define EXPECT_SYSCALL_FAIL(E, C) \ +// Expect a syscall to fail with the given error (inner). +// +// This is required because unfortunately googletest "computes" trace variables +// using line numbers instead of another unique ID and 2 calls to +// `SCOPED_TRACE(..)` via the same macro results in `-Wshadow`-related compiler +// errors: https://github.com/google/googletest/issues/5143 +#define EXPECT_SYSCALL_FAIL_NO_TRACE(E, C) \ do { \ - SCOPED_TRACE(#C); \ EXPECT_GT(0, C); \ EXPECT_EQ(E, errno) << "expected '" << strerror(E) \ << "' but got '" << strerror(errno) << "'"; \ } while (0) +// Expect a syscall to fail with the given error (with tracing). +// +// See the comment above (for `EXPECT_SYSCALL_FAIL_NO_TRACE`). +#define EXPECT_SYSCALL_FAIL(E, C) \ + do { \ + SCOPED_TRACE(#C); \ + EXPECT_SYSCALL_FAIL_NO_TRACE((E), (C)); \ + } while (0) + // Expect a syscall to fail with anything other than the given error. #define EXPECT_SYSCALL_FAIL_NOT(E, C) \ do { \ @@ -169,9 +185,9 @@ const char *TmpFile(const char *pathname); SCOPED_TRACE(GTEST_STRINGIFY_(openat((fd), (path), (flags)))); \ const int result = openat((fd), (path), (flags)); \ if (((flags) & O_BENEATH) == O_BENEATH) { \ - EXPECT_SYSCALL_FAIL(E_NO_TRAVERSE_O_BENEATH, result); \ + EXPECT_SYSCALL_FAIL_NO_TRACE(E_NO_TRAVERSE_O_BENEATH, result); \ } else { \ - EXPECT_SYSCALL_FAIL(E_NO_TRAVERSE_CAPABILITY, result); \ + EXPECT_SYSCALL_FAIL_NO_TRACE(E_NO_TRAVERSE_CAPABILITY, result); \ } \ if (result >= 0) { close(result); } \ } while (0) @@ -180,7 +196,7 @@ const char *TmpFile(const char *pathname); do { \ SCOPED_TRACE(GTEST_STRINGIFY_(openat((fd), (path), (flags)))); \ const int result = openat((fd), (path), (flags)); \ - EXPECT_SYSCALL_FAIL(E_NO_TRAVERSE_CAPABILITY, result); \ + EXPECT_SYSCALL_FAIL_NO_TRACE(E_NO_TRAVERSE_CAPABILITY, result); \ if (result >= 0) { close(result); } \ } while (0) #endif diff --git a/tests/sys/capsicum/fexecve.cc b/tests/sys/capsicum/fexecve.cc index 86df2af06388..6ff5a657c35a 100644 --- a/tests/sys/capsicum/fexecve.cc +++ b/tests/sys/capsicum/fexecve.cc @@ -32,9 +32,9 @@ class Execve : public ::testing::Test { if (exec_fd_ < 0) { fprintf(stderr, "Error! Failed to open %s\n", exec_prog_.c_str()); } - argv_checkroot_[0] = (char*)exec_prog_.c_str(); - argv_fail_[0] = (char*)exec_prog_.c_str(); - argv_pass_[0] = (char*)exec_prog_.c_str(); + argv_checkroot_[0] = __DECONST(char*, exec_prog_.c_str()); + argv_fail_[0] = __DECONST(char*, exec_prog_.c_str()); + argv_pass_[0] = __DECONST(char*, exec_prog_.c_str()); } ~Execve() { if (exec_fd_ >= 0) { @@ -43,9 +43,9 @@ class Execve : public ::testing::Test { } } protected: - char* argv_checkroot_[3] = {nullptr, (char*)"--checkroot", nullptr}; - char* argv_fail_[3] = {nullptr, (char*)"--fail", nullptr}; - char* argv_pass_[3] = {nullptr, (char*)"--pass", nullptr}; + char* argv_checkroot_[3] = {nullptr, __DECONST(char*, "--checkroot"), nullptr}; + char* argv_fail_[3] = {nullptr, __DECONST(char*, "--fail"), nullptr}; + char* argv_pass_[3] = {nullptr, __DECONST(char*, "--pass"), nullptr}; std::string exec_prog_, exec_prog_noexec_, exec_prog_setuid_; int exec_fd_; }; diff --git a/tests/sys/capsicum/procdesc.cc b/tests/sys/capsicum/procdesc.cc index f25324e4efc7..c92edaf4b695 100644 --- a/tests/sys/capsicum/procdesc.cc +++ b/tests/sys/capsicum/procdesc.cc @@ -983,6 +983,8 @@ TEST_F(PipePdfork, PassProcessDescriptor) { if (verbose) fprintf(stderr, "[%d] about to fork()\n", getpid_()); pid_t child2 = fork(); if (child2 == 0) { + int pd; + // Child: close our copy of the original process descriptor. close(pd_); SEND_INT_MESSAGE(sock_fds[0], MSG_CHILD_STARTED); @@ -992,7 +994,7 @@ TEST_F(PipePdfork, PassProcessDescriptor) { EXPECT_OK(rc); EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen); cmptr = CMSG_FIRSTHDR(&mh); - int pd = *(int*)CMSG_DATA(cmptr); + memcpy(&pd, CMSG_DATA(cmptr), sizeof(pd)); EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len); cmptr = CMSG_NXTHDR(&mh, cmptr); EXPECT_TRUE(cmptr == NULL); @@ -1024,7 +1026,7 @@ TEST_F(PipePdfork, PassProcessDescriptor) { cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; cmptr->cmsg_len = CMSG_LEN(sizeof(int)); - *(int *)CMSG_DATA(cmptr) = pd_; + memcpy(CMSG_DATA(cmptr), &pd_, sizeof(pd_)); buffer1[0] = 0; iov[0].iov_len = 1; if (verbose) fprintf(stderr, "[%d] send process descriptor %d on socket\n", getpid_(), pd_); diff --git a/tests/sys/capsicum/sctp.cc b/tests/sys/capsicum/sctp.cc index aa84653c5b2a..a36a242f8c9b 100644 --- a/tests/sys/capsicum/sctp.cc +++ b/tests/sys/capsicum/sctp.cc @@ -92,13 +92,13 @@ TEST(Sctp, Socket) { addr.sin_family = AF_INET; addr.sin_port = htons(0); addr.sin_addr.s_addr = htonl(INADDR_ANY); - socklen_t len = sizeof(addr); + socklen_t addr_len = sizeof(addr); // Can only bind the fully-capable socket. - EXPECT_NOTCAPABLE(bind(cap_sock_rw, (struct sockaddr *)&addr, len)); - EXPECT_OK(bind(cap_sock_all, (struct sockaddr *)&addr, len)); + EXPECT_NOTCAPABLE(bind(cap_sock_rw, (struct sockaddr *)&addr, addr_len)); + EXPECT_OK(bind(cap_sock_all, (struct sockaddr *)&addr, addr_len)); - EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr *)&addr, &len)); + EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr *)&addr, &addr_len)); int port = ntohs(addr.sin_port); // Now we know the port involved, fork off children to run clients. @@ -128,43 +128,43 @@ TEST(Sctp, Socket) { EXPECT_OK(listen(cap_sock_all, 3)); // Can only do socket operations on the fully-capable socket. - len = sizeof(addr); - EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &len)); + addr_len = sizeof(addr); + EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &addr_len)); struct sctp_event_subscribe events; memset(&events, 0, sizeof(events)); events.sctp_association_event = 1; events.sctp_data_io_event = 1; EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events))); - len = sizeof(events); - EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, &len)); + socklen_t eventslen = sizeof(events); + EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, &eventslen)); memset(&events, 0, sizeof(events)); events.sctp_association_event = 1; events.sctp_data_io_event = 1; EXPECT_OK(setsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events))); - len = sizeof(events); - EXPECT_OK(getsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, &len)); + eventslen = sizeof(events); + EXPECT_OK(getsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, &eventslen)); - len = sizeof(addr); + addr_len = sizeof(addr); memset(&addr, 0, sizeof(addr)); - EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &len)); + EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &addr_len)); EXPECT_EQ(AF_INET, addr.sin_family); EXPECT_EQ(htons(port), addr.sin_port); struct sockaddr_in client_addr; - socklen_t addr_len = sizeof(client_addr); + socklen_t client_addr_len = sizeof(client_addr); unsigned char buffer[1024]; struct sctp_sndrcvinfo sri; memset(&sri, 0, sizeof(sri)); int flags = 0; EXPECT_NOTCAPABLE(sctp_recvmsg(cap_sock_wo, buffer, sizeof(buffer), - (struct sockaddr*)&client_addr, &addr_len, + (struct sockaddr*)&client_addr, &client_addr_len, &sri, &flags)); while (true) { retry: memset(&sri, 0, sizeof(sri)); int len = sctp_recvmsg(cap_sock_rw, buffer, sizeof(buffer), - (struct sockaddr*)&client_addr, &addr_len, + (struct sockaddr*)&client_addr, &client_addr_len, &sri, &flags); if (len < 0 && errno == EAGAIN) goto retry; EXPECT_OK(len); diff --git a/tests/sys/capsicum/socket.cc b/tests/sys/capsicum/socket.cc index 5bb7e9d3e180..ff21d3020a83 100644 --- a/tests/sys/capsicum/socket.cc +++ b/tests/sys/capsicum/socket.cc @@ -166,26 +166,26 @@ TEST(Socket, TCP) { AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_CHILD_SHOULD_RUN); // Create sockets - int sock = socket(AF_INET, SOCK_STREAM, 0); - EXPECT_OK(sock); - if (sock < 0) return; - int cap_sock_rw = dup(sock); - EXPECT_OK(cap_sock_rw); - EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw)); - int cap_sock_all = dup(sock); - EXPECT_OK(cap_sock_all); - EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all)); - close(sock); + int child_sock = socket(AF_INET, SOCK_STREAM, 0); + EXPECT_OK(child_sock); + if (child_sock < 0) return; + int child_cap_sock_rw = dup(child_sock); + EXPECT_OK(child_cap_sock_rw); + EXPECT_OK(cap_rights_limit(child_cap_sock_rw, &r_rw)); + int child_cap_sock_all = dup(child_sock); + EXPECT_OK(child_cap_sock_all); + EXPECT_OK(cap_rights_limit(child_cap_sock_all, &r_all)); + close(child_sock); // Connect socket - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); // Pick unused port - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - socklen_t len = sizeof(addr); - EXPECT_NOTCAPABLE(connect_(cap_sock_rw, (struct sockaddr *)&addr, len)); - EXPECT_OK(connect_(cap_sock_all, (struct sockaddr *)&addr, len)); + struct sockaddr_in child_addr; + memset(&child_addr, 0, sizeof(child_addr)); + child_addr.sin_family = AF_INET; + child_addr.sin_port = htons(port); // Pick unused port + child_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + socklen_t child_addr_len = sizeof(child_addr); + EXPECT_NOTCAPABLE(connect_(child_cap_sock_rw, (struct sockaddr *)&child_addr, child_addr_len)); + EXPECT_OK(connect_(child_cap_sock_all, (struct sockaddr *)&child_addr, child_addr_len)); exit(HasFailure()); } @@ -291,15 +291,15 @@ TEST(Socket, UDP) { pid_t child = fork(); if (child == 0) { - int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - EXPECT_OK(sock); - int cap_sock_rw = dup(sock); - EXPECT_OK(cap_sock_rw); - EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw)); - int cap_sock_connect = dup(sock); + int child_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + EXPECT_OK(child_sock); + int child_cap_sock_rw = dup(child_sock); + EXPECT_OK(child_cap_sock_rw); + EXPECT_OK(cap_rights_limit(child_cap_sock_rw, &r_rw)); + int cap_sock_connect = dup(child_sock); EXPECT_OK(cap_sock_connect); EXPECT_OK(cap_rights_limit(cap_sock_connect, &r_connect)); - close(sock); + close(child_sock); // Can only sendmsg(2) to an address over a socket with CAP_CONNECT. unsigned char buffer[256]; @@ -313,25 +313,25 @@ TEST(Socket, UDP) { mh.msg_iov = &iov; mh.msg_iovlen = 1; - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - mh.msg_name = &addr; - mh.msg_namelen = sizeof(addr); + struct sockaddr_in child_addr; + memset(&child_addr, 0, sizeof(child_addr)); + child_addr.sin_family = AF_INET; + child_addr.sin_port = htons(port); + child_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + mh.msg_name = &child_addr; + mh.msg_namelen = sizeof(child_addr); - EXPECT_NOTCAPABLE(sendmsg(cap_sock_rw, &mh, 0)); + EXPECT_NOTCAPABLE(sendmsg(child_cap_sock_rw, &mh, 0)); EXPECT_OK(sendmsg(cap_sock_connect, &mh, 0)); #ifdef HAVE_SEND_RECV_MMSG struct mmsghdr mv; memset(&mv, 0, sizeof(mv)); memcpy(&mv.msg_hdr, &mh, sizeof(struct msghdr)); - EXPECT_NOTCAPABLE(sendmmsg(cap_sock_rw, &mv, 1, 0)); + EXPECT_NOTCAPABLE(sendmmsg(child_cap_sock_rw, &mv, 1, 0)); EXPECT_OK(sendmmsg(cap_sock_connect, &mv, 1, 0)); #endif - close(cap_sock_rw); + close(child_cap_sock_rw); close(cap_sock_connect); exit(HasFailure()); } |
