17 ms·
Unveil(2) – Unveil parts of a restricted filesystem view
- gshrikant 8y agoNot a very insightful comment but I really like the way OpenBSD names system calls - both `unveil` and `pledge` are great, descriptive Unix-y names for what these system calls do.
- rurban 8y agoReminds me more on Perl naming conventions. Take an arbitrary non technical expression, where established names already do exist, but clash with the semantics. Also the usage of strings for flags and not int bits just let me cry out. This is pure nonsense.
- gshrikant 8y agoPledge (previously `tame`) did use bitmasks in its earlier iterations. See Ted Unangst's post about it: https://www.tedunangst.com/flak/post/string-interfaces https://www.tedunangst.com/flak/post/string-interfaces
- rjvbk 8y agoI don't like it, it's un-C-like.
- arcticbull 8y agoToo many vowels? Would you prefer 'pldg' ? ;) Unless you meant the stringly-typed arguments in which case I'm 100% with you, they're asking for trouble.
- rurban 8y agoI know this change, that's why I bothered. He can do this in his private app as he likes, but not in the libc which is the most widely copied libc. It's about security, consistency and being a positive role model.
- anilakar 8y agoMaybe Theo wanted fopen-like semantics?
- bonzini 8y agofopen is not a system call, it is a library call. The system call is open, and it uses bits for flags.
- int_19h 8y agoWhich makes it that much harder to extend. There's nothing wrong with the use of strings here. It's very readable, easily understandable to anyone who knows C, can be checked by automated tools (or at runtime) for invalid values, and is easily extensible in the future. It's also not on a hot path (I mean, you shouldn't have to do this at any point other than process creation).
- therein 8y agoRight but is there really any reason why the implementation should call strncmp or anything that would be costlier than a bitwise AND? It's not like "r" reads better than O_RDONLY.
- codetrotter 8y agoPledge happens on process startup only, so since it’s not like it is called over and over again during the life of the process, the overhead is certainly negligible for all modern servers, desktops and laptops.
- tedunangst 8y agoIt's like everything else in openbsd. The people who don't use it don't like it; the people who live with it every day for years realize benefits the haters don't perceive.
- setzer22 8y agoI'm curious. To me, unveil means reveal information, while the intended purpose for this tool is to hide it. Why do you think it's such a descriptive name?
- danielparks 8y agoYeah, that was my thought too. This is more like “veil_except”. That said, “unveil” is good enough.
- amelius 8y agoWhy not "restrict"?
- MaxBarraclough 8y agoHere be dragons! "restrict" is a keyword in C.
- makecheck 8y agoIt is stated in the 2nd line of the Description in the manual that this will reveal things with subsequent calls. It’s just the initial call that hides everything.
- jakobegger 8y agoWhile it implicitely hides everything on the first call, it unveils the arguments. Reads really natural. I imagine typical usage would be: fork(); unveil("/home/jakob/", "w"); unveil("/etc/some_config_file", "r"); unveil(0,0); exec();
- matheusmoreira 8y agoI agree. Naming things is so hard. It's always nice when people do manage to come up with terse names.
- shawn 8y agoThis design is so thoughtful. Thanks to fork, you can easily sandbox a child process to a specific subtree of the filesystem: fork, unveil(0, 0), run untrusted user code. I wish OS X and windows had this.
- malkia 8y agoBuild systems can use such feature, without going through heavy duty isolation (sandboxing) like Bazel. It's done there, such that "accidental" dependencies are not followed, e.g. if your a.cpp source included b.h it better be that the rule compiling a.cpp explicitly stated that is dependent on a rule "exporting" b.h And possibly for other uses too :)
- saagarjha 8y agoIs sandboxing on macOS not exactly this (albeit with a different API)?
- floatboth 8y agoIt is. You have to write the rules as a Lisp script, and there's a scary "this is sort of deprecated, use the new Mac App Store stuff" paragraph in the manpage, but yes, it does allow exactly that.
- geocar 8y agoCan you? I haven't used OpenBSD in around fifteen years. Is the dynamic linker somehow exempt from unveil? Or does it somehow know what's going on?
- patrec 8y agoI wish instead of a patchwork of hacks like this we had a nice fundamental mechanism, e.g. capabilities exposed via a union file system (i.e. you make everything your process might want to access available via a file handle and run it in some chroot where you "mounted in" the things you want it to be able to touch; e.g. /bin has all the programs it can run, network, window manager and process tree access is mapped to /net /x and /proc etc).
- appslure 8y agoHi, all we are doing app development and web development services http://www.appslure.com/web-development/ http://www.appslure.com/web-development/
- shaggyfrog 8y agoHere's a presentation from Bob Beck entitled Pledge, and Unveil, in OpenBSD: https://www.openbsd.org/papers/BeckPledgeUnveilBSDCan2018.pdf https://www.openbsd.org/papers/BeckPledgeUnveilBSDCan2018.pd...
- avar 8y agoThis seems like a pretty major limitation of the interface: QUOTE It is important to consider that directory results are remembered at the time of a call to unveil(). This means that a directory that is removed and recreated after a call to unveil() will appear to not exist. Non directories are remembered by name within their containing directory, and so may be created, removed, or re-created after a call to unveil() and still appear to exist. ENDQUOTE So it's not really path-based, but rather translates a path at the the time of the call to some UUID (or just an inode? But then how is inode re-use handled?) for that particular directory. So if you unveil("~/myapp", ...) and the user does something like `mv ~/myapp ~/myapp.back && mkdir ~/myapp` the program won't see anything under ~/myapp anymore, since it's not the same directory, even thought it's at the same path.
- vesak 8y agoWhy would the user do that? You don't move away a program's data dir while it's running and expect everything to just work, right?
- avar 8y agoThere are programs that rely on this working, which would continue to work with unveil(2) if it wasn't for this artificial limitation. 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.
- vesak 8y agoEven though the function's name is unveil, I'm thinking that this feature is for denying access rather than allowing. In that sense, I think it's a useful protection measure that the new directory doesn't suddenly become visible in your example -- smells like an attack vector. Also, I would guess that doing these checks via pathname every time files are accessed would have to be pretty bad for performance. If such a feature is wanted, I would think that the daemon can just call unveil again when it's doing an automatic recovery.
- stevesimmons 8y agoThis discussion from 39 days ago has some good links plus whether there is a Linux equivalent: https://news.ycombinator.com/item?id=17277067 https://news.ycombinator.com/item?id=17277067
- specialist 8y agoI want a "merge" or "link" posts UX feature. Conceptually like merging bug reports.
- sctb 8y agoWe do merge posts while the discussion is still happening, but afterwards we aim to preserve context as much as possible.
- rphlx 8y agoThis is neat but I am still partial to slower but fully generic approaches for syscall filtering, such as BPF. Sooner or later you run out of clever English verbs for the plethora of fixed-function ones.
- floatboth 8y ago> fully generic approaches for syscall filtering, such as BPF How do you constrain filesystem access to be under a list of allowed directories using BPF? I briefly looked at it, and there doesn't seem to be a good way to manipulate strings. Everyone seems to be using chroot / bind mounts for that on Linux, which adds crap lines to `mount` output.
- Panino 8y ago> unveil can be locked, preventing further filesytem exposure by calling unveil with two NULL arguments. This is nice and I bet it will be preferable to blocking further unveil calls via pledge. Doing it with pledge would depend on the code path. Just as an example, are you connecting to an IP address or a hostname (requiring a "dns" pledge)? Are you reading from stdin or opening a file directly (requiring an "rpath" pledge)? The current pledge state wouldn't matter when removing unveil access via unveil itself, much simpler. Pledge is already outstanding but combined with unveil I feel like a kid in a candy store.
- aomix 8y agoI don't think the unveil(0,0) call to disable/ignore further calls is intuitive. But I'm not sure how you would improve on it beyond creating an unveil_disable() call.
- deleted 8y ago[deleted]
- imtringued 8y agoThe hardcoded zero literal for the flags could be replaced by a named constant. unveil(0, UNV_LOCK)