7 ms·
I'm working on a problem where I have a single executable that is run as a dynamic number of long-running processes where I'd like to restrict each process to a
by dmm 8y ago
I'm working on a problem where I have a single executable that is run as a dynamic number of long-running processes where I'd like to restrict each process to a separate directory.
For example, process 1 could only r/w files in "/some/path/1" and process 2 could access "/some/path/2". But the number of processes is dynamic. I might have two or I might have 100. So I need to be able to specify new directories at runtime.
I've been looking at the linux hardening mechanisms but I couldn't find a way to do this with, for example, selinux. With selinux it seems you are mostly able to create system level policies that applied to whole programs. I haven't found a way to provide something like a parameter to change the policy for a given process.
But it looks like this would be very easy to accomplish with unveil(2). This is very interesting work!
- masklinn 8y agoYup, sadly unlike pledge(2) there doesn't seem to be an execveil so you'd have to fork(); unveil(path, perms); unveil(null, null); pledge(...); exec();
- the_duke 8y agoOut of curiosity, what would be the point of restricting child processes to specific directories? If I trust a binary to read a directory, what's the point of constraining specific processes further? The only use case I could think of is where the binary itself runs untrusted code from a third party. (e.g. plugins).
- Someone 8y agounveil also protects you against untrusted code you wrote yourself (and yes, you shouldn’t trust code you wrote yourself. You may know it doesn’t do anything wrong on purpose, but it might be buggy and do something wrong by accident) Also, if you didn’t write the OS, your untrusted code will call third party code, if it is worth running it at all (it has to communicate results back to the caller. That requires some OS calls, even if only to trigger some semaphore)
- mikeash 8y agoIf you ever read untrusted data, you should consider the possibility that you’ll be exploited and end up running untrusted code even though you never intended to.
- masklinn 8y agoThe point of pledge(2) (and unveil which builds on and complements pledge(2)) is to protect against the consequences of human failing: if the software has an accessible exploit, limiting its ability to see the system means the attacker has a much harder time pivoting into something useful. That's why pledge(2) and unveil(2) are useful despite literally being part of the software it restricts.
- proaralyst 8y agoYou might be interested in bwrap.[0] [0]: https://github.com/projectatomic/bubblewrap https://github.com/projectatomic/bubblewrap
- noselasd 8y agoIf your program copes with all the implications it entails, you could chroot() to the relevant directory.
- justinsaccount 8y agoI don't know about selinux, but systemd can easily do this: https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ReadWritePaths= https://www.freedesktop.org/software/systemd/man/systemd.exe...
- throwaway2048 8y agoThis has the same problem, you have to define a systemd unit/service/whatever beforehand, the program can not change these parameters, then signal it wishes to be locked down and prevented from changing them again. That's the real beauty of how the OpenBSD approach works, it lets you incrementally ratchet up the restrictions as various stages of the startup/run loop of a program progress, so you don't have to specify everything a program might ever try to do ahead of time, and have that huge pool of permissions persist throughout the entire life of the program.
- justinsaccount 8y agoBetween templated unit files and systemd-run things can be a bit more dynamic, but yeah, not at runtime. As I understand it, seccomp can do what unveil and pledge can do, just with a much more complicated API. I wonder if anyone is working on a pledge/unveil compatible wrapper API for seccomp...
- brynet 8y agoNot at all, for example you can't implement the ratchet down semantics of pledge() using seccomp. For instance having initial broader promise set "stdio rpath recvfd", and then irrevocably dropping to a runtime promise of "stdio" after init. This is a very paradigmatic use of pledge(2), which a large portion of the 85% of OpenBSD's base system pledged will demonstrate. unveil(2) would be very challenging, if not impossible. Both would require proper Linux integration and kernel implementation.
- deleted 8y ago[deleted]
- deleted 8y ago[deleted]
- zimbatm 8y agoOn Linux it's a bit more DYI. Look at `unshare()` and cgroups to limit resources. For example your process scheduler could fork, create a new mount namespace with unshare() , bind-mount the temporary workdir to a known location, drop privileges and the exec the target program.
- le-mark 8y agoIsn't this essentially the same problem as securing container (ie docker) access to the host file system? Also similar if you just want to give every user their own process. Are docker's tools sufficient for this, for example? If you aren't executing third party code, don't worry about it? And if you are; provide an api third parties must use that validates paths before r/w files? Disallow '..' './' '~/' etc?
- xorcist 8y agoAre you not describing plain old chroot?