Sandboxing on Linux - it needn't be complicated

... because what's the fun when the BSDs are the only kids in the sandbox?

Initial writeup: 2024-12-13

Sandboxing and POSIX

Imagine: you setup a fancy new service that is connected to the interwebs. How scary! What if that new butt that you have exposed to the www is - in fact - naked? Even worse, what if it is programmed in C and because of that, probably breakable in ways that you cannot imagine?

Then, you'd better be of patching that software!

If that is a possibility. Of course, depending on the OS you are on, you have nice options that are (relatively) intuitive and easy to use. Of course, I cannot miss to mention OpenBSD's unveil(2) and pledge(2). They are, in my opinion, the most ergonomic API for C programmers to call when it comes to sandboxing a program.

Ironically though, these symbols are included with <unistd.h>, which is the system's POSIX header. (Right?) But unveil and pledge are... Not POSIX? (What??) So you won't find them in your common linux.

The common linux that I am talking about, becomes uncommon, as soon as you start to use something like

cosmopolitan libc

which is in fact cross platform (even onto windows!) and provides an implementation for pledge! This is truely an amazing feat of the person behind cosmopolitan.

But I am not that much into custom libc implementations - I have tried voidlinux with musl once and found it weird. I am not sure though if in the end that weirdness was coming from void or musl. Whatever.

Now, given that most people are stuck with GNU libc, the options are (used to be) limited. Günther Noak attempted to port pledge to linux, and he describes his failed efforts in his blog post:

The feasibility of pledge() on Linux

To cite and summarize:

You can't predict the syscalls a program will do.

Because restricting a process' privileges is after all effective through limiting the syscalls it is allowed to issue, and GNU libc doesn't guarantee stability of syscalls that are in use under the hood. I am extrapolating here, but BSDs apparently have less of a struggle here because there, userspace and kernelspace aren't kept seperate to the same degree as they are under Linux.

Landlocked processes improve the sleep of admins

This is a known fact, and certified by the Linux admin health society (c) \s.

Now of course, Linux just can't admit to (Open)BSD folk that their ideas on sandboxing are truly user friendly. That's why they have their own stuff!

Seccomp BPF, etc. Does anybody here know seccomp? Yikes!

But there is actually one upcoming and partially already implemented ABI that is landlock(7). As far as usability goes, I do not consider for it to be as ergonomic as the stuff in OpenBSD's <unistd.h> (again, why is non-POSIX-stuff in a POSIX header??): pledge and unveil. But it does make sense if you stare at it for long enough.

At the time of writing this post, landlock enables unprivileged processes to restrict themselves, in:

capabilities. There is some upcoming functionality on restricting IPC as well, such as signals and abstract unix sockets.

Available filesystem restrictions make it possible to precisely define files or filesystem-hierarchies that can only be readable, and so on. With this, I consider unveil() to be "implemented" in a sense that it can be emulated, because landlock's rules on filesystem restrictions actually make it possible to have more fine-grained control on the set restrictions.

Networking restrictions are a little less spectacular as of right now, but they are interesting as it is possible to either make it impossible for the process to connect or bind to any TCP socket, or to restrict these capabilities to certain ports only.

Still, pledge() covers more process capabilities. It remains to be seen where Torvalds et. al. head with landlock.

But it is totally usable! In fact, the magnificent comment system that I use for my blog here is landlocked - after all, I want to be able to sleep well at night. Commits on main integrate a header that I have come up with to make using landlock a little less boilerplaty and cumbersome:

landloc.h

which really is just some accumulation of ridiculous macros. But hey! It should make it easier for anyone that knows a little C to write landlocking code. And after all, it is free (as in 0-Clause-BSD) software!

Cheers!

View comments

Home