3 ms·
I'm... conflicted. On one hand, a simple opt-in way for applications to give away the ability to do operations is something I've wanted for sandboxing for a lo
by bodyfour 11y ago
I'm... conflicted.
On one hand, a simple opt-in way for applications to give away the ability to do operations is something I've wanted for sandboxing for a long time. From an API perspective, tame() looks great.
However, the kernel-side implementation is way too ugly. Hardcoding pathnames needed to use things like DNS, NIS, etc is just way too inflexible and fragile.
I think the kernel should just support a set of fs/network/etc restrictions that can be grown but not shrunk by the process. i.e. basically what seccomp-bpf gives you on linux. What we really need is user-friendly libraries to make using seccomp-bpf as easy as using tame()!
- batou 11y agoI think it's quite simple really. Sure it's a bit ugly but most APIs are behind the scenes. As long as the API itself is clean, that's not necessarily a problem. In this case though, the problem with growing the permission set is you then need rules to define the sandbox "size" outside the process, then tools to administer it, then the policies to be deployed with the program. If you're using tame which is restrictive, based on how they do privsep in OpenBSD, you're forking tasks off from a control process and then removing privileges. So the program defines the policy internally, very granularly and correctly. How you'd do that with seccomp-bpf with forked child processes etc would be vastly more complex. Consider OpenSMTPd for example which consists (I can't remember the exact separations): master process, smtp listener, queue, writer. These are all forked from the master process and talk to each other with pipes. How would you mandate the call limitations efficiently if this was externalised? Also how would you assure that a misapplied external policy doesn't compromise your system.
- bodyfour 11y agoThe problem isn't that it's behind the scenes, it's what part of it is in kernel space. The user of tame() quite sensibly wants to specify a simple filter based on what things they might need to do in the future. i.e. "I need to be able to loop up details about local users". At the system-call level this implies a number of things should be allowed i.e. "can open /etc/group for read-only access, can read NIS configuration files, ..." In the OpenBSD implementation of tame() all of these rules are hardcoded into the kernel. Using LDAP instead of NIS? Well, you'll have to patch and recompile I guess. Since ultimately the userland process is opting-in to the restrictions there's no security reason that it can't specify the rules to the kernel. (Assuming here that care is taken so it can't DoS the kernel by pushing down a billion-entry list or something) Again, what OpenBSD gets right here is the API -- it should be as simple as possible for a process to say "I need to look up users, use DNS, and read files; block all else" Making that a simple call like tame() is a great step forward. I hope the seccomp-bpf people do something similar. However, tame() should be a library function, not a syscall. The kernel shouldn't know or care what "I need to use DNS" means, it should just be told what files I can open and what sockets ops I'm allowed to do. The OpenBSD implementation is simultaneously too rigid for some things (since things like plugable nsswitch.conf modules can't work at all) and too loose to support other useful ones (per-application policies like "block any attempt to open a file for writing unless it's an append to $HOME/.ssh/known_hosts") In UNIX there is a very long tradition of not baking policies like this into the kernel, and for good reason.
- batou 11y agoI conceed. Some good points there.
- angersock 11y agoThe kernel shouldn't know or care what "I need to use DNS" means, it should just be told what files I can open and what sockets ops I'm allowed to do. Is this perhaps an artifact of the OpenBSD development model, where programs are assumed to work tightly coupled to the kernel?
- Canada 11y agoOf the pathnames contained in tame_namei(), how many are really going to change? I'm trying to think of a case where alternate names or paths are needed, yet nothing comes to mind.
- bodyfour 11y agoCertainly on other UNIXes getpwnam() can need a bunch of different files and sockets depending on what nsswitch.conf backend is in use. I guess OpenBSD doesn't support nsswitch at all (it looks like it just uses a pseudo-NIS damon "ypldap" if you want to use LDAP auth) but on most other UNIXes it doesn't work that way. Similar arguments apply to host resolution, but these days it's almost always just /etc/hosts and DNS so less of an issue.