> The state of userspace sandboxing across all operating systems I'm aware of is dismal. As a developer it should be trivial to spawn a process with a subset of the privileges of the parent process.
It's a breeze on OpenBSD, at least as an application developer. The key is realizing that you can't effectively sandbox a process without the process cooperating. That often means refactoring the source code to reorganize how and when it acquires resources. If you're refactoring the source code, then in many cases it's easier and most effective for the process to sandbox itself, thus pledge(2) (https://man.openbsd.org/pledge.2) and unveil(2) (https://man.openbsd.org/unveil.2). Afterall, the process and its authors are the final and best arbiters of the resources it will need to initialize and acquire during runtime.
All the pain on Linux comes from people struggling to sandbox uncooperative processes (i.e. processes you can't modify and refactor) by trying to construct a fake environment. That's ultimately a losing battle. And quite ironic that people instinctively seek that route even in the context of open source applications where source code is readily available and upstreaming patches and improvements extremely common. OpenBSD has managed to sandbox to some extent almost every program, including command-line utilities, that ship with the OS. And they continue to incrementally improve the those sandboxes over time--IOW, pledge and unveil are amenable to iterative, steady development of capability management, rather than requiring herculean effort up front, potentially resulting brittle architectures that make feature additions excessively difficult.
While there's nothing quite as simple as pledge on Linux (seccomp is close but has several problematic caveats), something very similar to unveil was upstreamed into Linux last year: Landlock. See https://docs.kernel.org/security/landlock.html Unfortunately, AFAICT, Landlock, like seccomp, is mandatorily inherited on fork (no option to disable), which means it can be difficult to integrate into existing applications that might fork or exec other processes--they might be completely unrelated and require a privilege set that isn't a subset of the invoker. Reordering the sequence of process spawning to before the privilege drop can be impractical--effectively impossible if it means basically rewriting the entire program, for example with a read-eval loop (e.g. procmailrc). Spawning processes indirectly through, e.g., systemd or pkgexec, simply shifts the problem and can even increase exposure and bug risk. But for daemon services which are only leaves on the process tree, that's not a concern; Landlock and to a lesser extent seccomp can better approximate unveil and pledge, respectively.
I'm totally fine changing the way I write my applications to make them more secure. I just don't feel like the APIs are there.
Personally I think capability-based security models is the best idea I've seen so far. Set up the file descriptors and network sockets your program needs at startup, then drop any other privileges. The problem is file descriptors don't cover things like directory trees AFAIK.
If performance isn't critical, what are your thoughts on using QEMU to wrap an application for security purposes? That might even work on Windows.
It's a breeze on OpenBSD, at least as an application developer. The key is realizing that you can't effectively sandbox a process without the process cooperating. That often means refactoring the source code to reorganize how and when it acquires resources. If you're refactoring the source code, then in many cases it's easier and most effective for the process to sandbox itself, thus pledge(2) (https://man.openbsd.org/pledge.2) and unveil(2) (https://man.openbsd.org/unveil.2). Afterall, the process and its authors are the final and best arbiters of the resources it will need to initialize and acquire during runtime.
All the pain on Linux comes from people struggling to sandbox uncooperative processes (i.e. processes you can't modify and refactor) by trying to construct a fake environment. That's ultimately a losing battle. And quite ironic that people instinctively seek that route even in the context of open source applications where source code is readily available and upstreaming patches and improvements extremely common. OpenBSD has managed to sandbox to some extent almost every program, including command-line utilities, that ship with the OS. And they continue to incrementally improve the those sandboxes over time--IOW, pledge and unveil are amenable to iterative, steady development of capability management, rather than requiring herculean effort up front, potentially resulting brittle architectures that make feature additions excessively difficult.
While there's nothing quite as simple as pledge on Linux (seccomp is close but has several problematic caveats), something very similar to unveil was upstreamed into Linux last year: Landlock. See https://docs.kernel.org/security/landlock.html Unfortunately, AFAICT, Landlock, like seccomp, is mandatorily inherited on fork (no option to disable), which means it can be difficult to integrate into existing applications that might fork or exec other processes--they might be completely unrelated and require a privilege set that isn't a subset of the invoker. Reordering the sequence of process spawning to before the privilege drop can be impractical--effectively impossible if it means basically rewriting the entire program, for example with a read-eval loop (e.g. procmailrc). Spawning processes indirectly through, e.g., systemd or pkgexec, simply shifts the problem and can even increase exposure and bug risk. But for daemon services which are only leaves on the process tree, that's not a concern; Landlock and to a lesser extent seccomp can better approximate unveil and pledge, respectively.