July 31, 2017
July 2017 – Siva’s Capsicum Test Suite Project
As a co-op student at the FreeBSD Foundation, I have the unique opportunity of being encouraged to contribute to other open source projects that help make progress on FreeBSD and its components. One such project that I worked on in July is an analysis of the Capsicum test suite. This test suite targets the Capsicum capability and sandbox framework, which is included in FreeBSD since version 10.0. As described on the University of Cambridge Computer Laboratory website, “Capsicum extends the POSIX API, providing several new OS primitives to support object-capability security on UNIX-like operating systems”. Furthermore, the test suite was initially created by David Drysdale at Google while porting FreeBSD’s reference implementation of the Capsicum framework to Linux.
For this project, I was first assigned to investigate a test case for pdfork(2)
that had been failing for some time. However, upon running the test suite on a FreeBSD 12 CURRENT machine, I noticed that there were several test cases failing with non-trivial error messages and status codes. I discussed these results with Ed Maste, my supervisor, and we determined that the following test results were of interest:
-
OpenatTest.WithCapability
: Open files using pathnames that are relative to a directory with restricted capabilities and contain “..”. The test was failing due to an assertion that every call toopenat()
with a pathname containing “..” is invalid. Based on changes made to FreeBSD after the test was written, the assertion should instead be that callingopenat(base_fd, path, ...)
with apath
containing “..” should be forbidden only ifpath
points to a file outside of the base directory represented bybase_fd
. -
WithFiles.DisallowedFileSyscalls
: Execute themknod(2)
syscall in capability mode with invalid arguments. This test case expected the syscall to return withECAPMODE
; however, the FreeBSD implementation of the syscall first ran validations against the given arguments before checking for capability. Since the arguments were invalid, it returned withEINVAL
. The POSIX specification confirms that this behavior is permissible, so we decided that the test case must be changed[1]. -
Pdfork.OtherUser
: Kill a process withpdkill(2)
after changing the current process’s user identifier (UID). This test is currently failing because the kernel disallows sending signals to processes that are not of the same UID as the current process. After a short discussion, we determined that this behavior is desired, and we decided that the test case should be modified to remove the call topdkill()
after changing the current process’s UID. -
Pdfork.Simple
(related tests omitted): Test basic operations using process descriptors on processes created with thepdfork(2)
syscall. These tests were failing because of checks to determine if a certain process is a zombie. These tests used theps(1)
tool, but upon further inspection, I noticed thatps -p <zombie-pid>
does not report zombie processes. The call tops(1)
was modified in the test suite to ensure that thePdfork.*
test cases pass, but the kernel’s behavior, with respect to reporting zombie processes, remains the same until further discussion. -
PosixMqueue.CapMode
: Test basic operations usingkmq_*()
syscalls on POSIX message queues in capability mode. In order to run this test case, I needed to dynamically load themqueuefs(5)
kernel module. After doing this, I noticed that the newly-loaded syscalls returnedECAPMODE
while in capability mode. Remote debugging these syscalls with GDB showed that their respective syscall entries (sysent
s) were not being initialized with the correct flags, so I submitted a kernel patch (which has now been committed to FreeBSD) and the tests now pass. -
PipePdfork.Close
: Test the behavior of a closed process descriptor. This test is currently failing because of awaitpid(2)
call to a process that had its last process descriptor closed. I noticed that the kernel reparents a process to theinit
process after the lastclose(2)
on its process descriptor. Ed and I decided that this behavior should be further discussed at the biweekly Capsicum conference call, and the verdict was that the kernel’s behavior is appropriate. The test case must be changed to reflect this behavior.
To run the Capsicum test suite, follow these steps on a FreeBSD machine:
-
Clone the Capsicum test suite git repository and navigate into the directory
$ git clone https://github.com/google/capsicum-test.git && cd capsicum-test
-
Build the test suite
$ make
-
Run all tests that do not require you to be root
$ ./capsicum-test
-
Run all tests that require root
$ sudo ./capsicum-test
-
Run a specific test case with verbose log messages
$ ./capsicum-test -v --gtest_filter="Pdfork.Simple"
For more help on how to use the test suite, run $ ./capsicum-test --help
.
[1] Full discussion can be found here
– Contributed by Siva Mahadevan