diff --git a/contrib/capsicum-test/README.md b/contrib/capsicum-test/README.md index 918534557725..a8c8c6686759 100644 --- a/contrib/capsicum-test/README.md +++ b/contrib/capsicum-test/README.md @@ -5,7 +5,7 @@ object-capabilities. The tests exercise the syscall interface to a Capsicum-enab currently either [FreeBSD >=10.x](http://www.freebsd.org) or a modified Linux kernel (the [capsicum-linux](http://github.com/google/capsicum-linux) project). -The tests are written in C++98, and use the [Google Test](https://code.google.com/p/googletest/) +The tests are written in C++11 and use the [Google Test](https://code.google.com/p/googletest/) framework, with some additions to fork off particular tests (because a process that enters capability mode cannot leave it again). diff --git a/contrib/capsicum-test/capmode.cc b/contrib/capsicum-test/capmode.cc index c274f5e1c9f3..ba2de19879a0 100644 --- a/contrib/capsicum-test/capmode.cc +++ b/contrib/capsicum-test/capmode.cc @@ -3,6 +3,9 @@ // whether or not they return the expected ECAPMODE. #include #include +#ifdef __FreeBSD__ +#include +#endif #include #include #include @@ -11,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -203,6 +207,39 @@ FORK_TEST_F(WithFiles, AllowedSocketSyscalls) { if (fd_pair[1] >= 0) close(fd_pair[1]); } +FORK_TEST_F(WithFiles, AllowedSocketSyscallsIfRoot) { + GTEST_SKIP_IF_NOT_ROOT(); + + EXPECT_OK(cap_enter()); // Enter capability mode. + + // Creation of raw sockets is not permitted in capability mode. + EXPECT_CAPMODE(socket(AF_INET, SOCK_RAW, 0)); + EXPECT_CAPMODE(socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)); + EXPECT_CAPMODE(socket(AF_INET, SOCK_RAW, IPPROTO_TCP)); + EXPECT_CAPMODE(socket(AF_INET, SOCK_RAW, IPPROTO_UDP)); + + EXPECT_CAPMODE(socket(AF_INET6, SOCK_RAW, IPPROTO_ICMP)); + EXPECT_CAPMODE(socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)); + EXPECT_CAPMODE(socket(AF_INET6, SOCK_RAW, IPPROTO_TCP)); + EXPECT_CAPMODE(socket(AF_INET6, SOCK_RAW, IPPROTO_UDP)); + + EXPECT_CAPMODE(socket(AF_ROUTE, SOCK_RAW, 0)); + + // Interface configuration ioctls are not permitted in capability + // mode. +#ifdef __FreeBSD__ + struct if_clonereq req; + + req.ifcr_total = 0; + req.ifcr_count = 1; + req.ifcr_buffer = static_cast(malloc(IFNAMSIZ)); + + EXPECT_CAPMODE(ioctl(fd_socket_, SIOCIFGCLONERS, &req)); + + free(req.ifcr_buffer); +#endif +} + #ifdef HAVE_SEND_RECV_MMSG FORK_TEST(Capmode, AllowedMmsgSendRecv) { int fd_socket = socket(PF_INET, SOCK_DGRAM, 0); diff --git a/contrib/capsicum-test/capsicum-test.cc b/contrib/capsicum-test/capsicum-test.cc index ba7936c788fc..1e722089761f 100644 --- a/contrib/capsicum-test/capsicum-test.cc +++ b/contrib/capsicum-test/capsicum-test.cc @@ -76,7 +76,10 @@ char ProcessState(int pid) { errno = 0; struct kinfo_proc *p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &count); if (p == NULL || count == 0) { - if (verbose) fprintf(stderr, "procstat_getprocs failed with %p/%d: %s\n", p, count, strerror(errno)); + if (verbose) { + fprintf(stderr, "procstat_getprocs failed with %p/%d: %s\n", (void *)p, + count, strerror(errno)); + } procstat_close(prstat); return '\0'; }