This Article IsCreated at 2023-11-19Last Modified at 2024-05-06Referenced as ia.www.b24

Writting Secure Programs with Capsicum on FreeBSD

Note: this article is very simple. I’ll add more to this article when I try more stuff with Capsicum.

Update: Someone wrote an article about using openat in Capsicum. It has more words than this one.


Recently I heard this capability subsystem that I kept spelling as “Capsium” is supposed to easy to add to existing UNIX programs. The good news is, it is on FreeBSD right now, and I can use it! (You too!) The bad news is that it’s not on Linux, and probably never will be.

Reminder: Please apply the newest security patches on your FreeBSD installation before using Capsicum.

After installing FreeBSD, here’s the singular C program that I wrote to try out Capsicum.

#include <stdio.h> 
#include <sys/capsicum.h> 
 
int main() { 
    int cwd_fd = open(".", O_RDONLY|O_DIRECTORY); 
    cap_enter(); 
    puts("hello"); // write to stdout 
    int hello_c_fd = openat(cwd_fd, "hello.c", O_RDONLY); 
    int parent_fd = openat(cwd_fd, "..", O_RDONLY); 
    printf("%d %d %d\n", cwd_fd, hello_c_fd, parent_fd); 
}

Then, I ran it with root (cc hello.c && ./a.out) and it gave me this output.

hello
3 4 -1

It works! Capsicum seems super easy to use!

For more usage of Capsicum, see my experimentation repo.

That’s it for now bye~

How Does This Works Exactly

This is best explained by rights(4). Basically, you can limit the set of syscalls that can be used with a file descriptor. When in doubt, CAP_READ|CAP_WRITE|CAP_SHUTDOWN.

.. is not allowed in openat(2).

The complete list of “file” types can be found in FreeBSD’s source code.

Musing: proc fd cannot refer to the current process. To send signal to current process, use getpid+kill(2 syscalls!), which capsicum allows.