From d0e943077d94e6266ece9856789c5d5313676e38 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 12 Apr 2021 11:20:39 -0400 Subject: [PATCH] Update capsicum-test to ea66424d921bb393539b298c108a46edee5c3051 This adds regression tests for a recent FreeBSD commit to restrict certain socket operations in capability mode. --- README.md | 2 +- capmode.cc | 37 +++++++++++++++++++++++++++++++++++++ capsicum-test.cc | 7 +++++-- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 918534557725..a8c8c6686759 100644 --- a/README.md +++ b/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/capmode.cc b/capmode.cc index c274f5e1c9f3..ba2de19879a0 100644 --- a/capmode.cc +++ b/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/capsicum-test.cc b/capsicum-test.cc index dedad464a4d9..1e722089761f 100644 --- a/capsicum-test.cc +++ b/capsicum-test.cc @@ -72,11 +72,14 @@ char ProcessState(int pid) { } unsigned int count = 0; struct procstat *prstat = procstat_open_sysctl(); - EXPECT_NE(NULL, prstat) << "procstat_open_sysctl failed."; + EXPECT_NE(nullptr, prstat) << "procstat_open_sysctl failed."; 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'; }