Think e.g. a daemon that processes data in /var/run/something and uploads it somewhere else, and gracefully handles failure if the directory disappears (e.g. an admin had to remove all existing data). Due to the unveil(2) interface such an action would require a full restart of the daemon, but that's not a normal limitation on *nix systems.
I can't think of any reason for it to work this way except that it's exposing the underlying limits of the implementation, or if they're making the trade-off of tying it to the inode so `mv ~/myapp ~/myapp.back` will continue to allow access to files under ~/myapp.back, but they don't document that.
If such a feature is wanted, I would think that the daemon can just call unveil again when it's doing an automatic recovery.
> [...]the daemon can just call unveil again[...]
Not if it previously called unveil(NULL, NULL), which is a significant part of the security selling point of this feature. If so it'll need a full restart.You also won't be able to tell if the directory can't be accessed or if it truly doesn't exist, since syscalls will return ENOENT instead of EACCES in this case. So the state machine to recover from this becomes complex. You might do a full restart just to find that no, the directory really doesn't exist anymore, rather than getting replaced.
On the other hand this is consistent with how chroot(8) works, but in that case you're cd'd to the directory in question, which you'll loose access to if it gets replaced (standard nix semantics, nothing to do with chroot per-se).
Overall I really like these simple security restriction mechanisms OpenBSD is adding, and wish these sorts of APIs were available on more popular OSs, but if say Linux cloned this I hope they don't carry over this caveat, since it's not consistent with how path access works in general.
unprivileged user namespace + mount namespace -> mount some tmpfs, bind-mount (optionally read-only or noexec), pivot_root and you got an isolated view of the filesystem. You could write a wrapper around that which provides a streamlined API in the fashion of unveil.
It's what sandboxes and containers runtimes do. Instead it could also be made into a security library which processes could use as part of their startup sequence.
Basically, the linux building-blocks (seccomp, namespaces, privileges) are more low-level and you need to assemble pledge/unveil-like abstractions from them. But I am not aware of any established library that does that in a convenient fashion.
probably better, as such code is likely to be very unportable. even if you standardise the calls in a library, on linux the right paths will probably vary between distributions and architectures
That's not possible with an external container/sandbox launcher, you need to interleave it with the control flow.
Seccomp&co are too low-level. Jail launchers are too coarse.
Intuitively you would think that makes them less secure. But inheritance means that it becomes impossible to use system utilities. On OpenBSD /bin/sh is pledge'd; you could never do the same thing using seccomp because it would make the shell useless. At best you'd dynamically seccomp a single shell session according to a particular task, and you'd have to do it from the invoking process. Unsurprisingly, nobody bothers doing this.
So it's impossible to emulate pledge, and impractical to emulate unveil, on Linux. At this point, almost every program on OpenBSD uses pledge. No configuration. No option switches. It's done. Everything works like before, except now the security risk of bugs in all that code are substantially mitigated.
All the criticisms of pledge and unveil miss the basic point of these interfaces--to be easily useable by developers and easily used in all programs, not as low-level primitives to be used to write libraries to be used to write tools to be used by sysadmins for sandboxing services.
This way bugs/exploits of the server can't suddenly go read/write to i.e. /etc/passwd.