Sandboxing applications using capsicum can sometimes lead to repeating some common patterns and duplicating large amounts of code. Fortunately there is an easy solution.
Most software that is capsicumised require limiting stdin/out/err descriptors and probably also caching timezone and locale data. The procedure to limit streams is to:
- limit rights on descriptor to CAP_READ/CAP_WRITE, CAP_FCNTL, CAP_FSTAT and CAP_IOCTL
- limit ioctl(2) to TIOCGETA, TIOCGWINSZ
- allow CAP_FCNTL_GETFL in fstat(2)
That usually require duplicating some code for all 3 standard io descriptors, possibly also for some additional for log files etc.
We can simplify the whole process by using
capsicum_helpers(3), part of the
libcapsicum available in base system.
[…] #include <capsicum_helpers.h> #include <err.h> […] // standard io if (caph_limit_stdin() == -1) err(1, “capsicum”); if (caph_limit_stdout() == -1) err(1, “capsicum”); if (caph_limit_stderr() == -1) err(1, “capsicum”); // additional descriptors if (caph_limit_stream(myfd, CAPH_WRITE) == -1) err(1, “capsicum”); […]
For standard io there is also simple functions that takes care of all of them:
if (caph_limit_stdio() == -1) err(1, “capsicum”);
To cache timezone and locales data use:
There is no need of error handling for these two functions.