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:

  1. limit rights on descriptor to CAP_READ/CAP_WRITE, CAP_FCNTL, CAP_FSTAT and CAP_IOCTL
  2. limit ioctl(2) to TIOCGETA, TIOCGWINSZ
  3. 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:

caph_cache_tzdata();
caph_cache_catpages();

There is no need of error handling for these two functions.

Was this post helpful to you? Yes!


Leave a comment