4 ms·
My opinion, as the designer of Sandstorm, a capability-based server OS: Capabilities are not the way developers are used to thinking. It may be that if people
by kentonv 9y ago
My opinion, as the designer of Sandstorm, a capability-based server OS:
Capabilities are not the way developers are used to thinking. It may be that if people got used to it, it would make sense -- or it may be that it's simply too complicated and most developers will never wrap their heads around it. I honestly don't really know which it is. In this respect, it feels a lot like functional programming (FP and capabilities are very different concepts, but are similar in that it takes a while to fully understand how to use them effectively).
We do see capability systems appearing by accident all over the place. Unix file descriptors, for example, behave very much like capabilities. Once open() finishes successfully, all access checks are done -- they aren't repeated for every read() or write(). You now have a capability, and you can even send that capability to other processes (even running under different UIDs that wouldn't have permission to open the file directly) via Unix domain sockets.
People who really get how to exchange file descriptors build some amazing systems with them (without ever realizing they're building capability systems). But, for some reason, most systems do not really try to take advantage of FD passing, and instead opt to do things like listen on a globally-accessible port and perform an authentication handshake on incoming connections. I guess this kind of design just seems more obvious to people?
But often, as systems get more complex and involve more parties, they end up forced to use capability-ish designs, because ACL-based designs get intractable. OAuth's use of bearer tokens, for example, is very capability-ish, albeit not acknowledged as such, and a fairly primitive form of capabilities. This sort of design turns out to be necessary in large-scale systems. If people would learn capability theory before designing such systems, they'd probably be more secure and powerful.
- im_down_w_otp 9y agoWell... Kenton, now you've now got my brain stirring on whether or not the perceived complexity & opacity of ocap is an artifact of how tightly it has bound itself to the concepts of OOP (as something of a personal character flaw I find OOP to be fairly obfuscating beyond trivial domains for whatever reason), and whether or not FP concepts applied to a similar domain as ocap might provide me with clarity in security design/implementation the same way FP gave me clarity in program design/implementation eventually. None of which I really have excess time to noodle about, but is now unavoidable. Thank you, sir.
- abecedarius 9y agoYou might find http://www.erights.org/elib/capability/ode/index.html http://www.erights.org/elib/capability/ode/index.html stimulating if you haven't seen it before. It showed me that OO could be more elegant than I'd thought.
- kentonv 9y agoYes! Too many people think OOP means deep class heirarchies, implementation inheritance, AbstractSingletonProxyFactoryBean, and other things you might see in Java. I think this turns a lot of people off. Good OOP is none of that. It's simply associating data with code that operates on it, in order to get two good things: abstraction and encapsulation. Abstraction is by defining virtual tables, encapsulation is by hiding implementation details as private members. Object-capability discipline leverages encapsulation as a security primitive (you can only perform the operations allowed by the public interface), and leverages abstraction to implement attenuation via wrappers (e.g. a wrapper that blocks certain methods, or a wrapper that can be revoked later). It has zero use for class hierarchies with implementation inheritance. So yeah, I think studying ocaps does help one understand how to do OOP right. And yeah, I think learning FP can indeed help you gain clarity over a different aspect of programming -- something basic about organizing computation and data structures, which complements OOP and ocaps. (I seem to be one of few people that don't see any inherent conflict between OOP and FP... they are orthogonal and can be used together.)
- kybernetikos 9y ago> I seem to be one of few people that don't see any inherent conflict between OOP and FP It really depends on which aspects you see as essential to the paradigms. If you define functional programming as programming that makes use of HOFs, or that encourages referential transparency, then you can combine those learnings with OOP nicely. It's also possible to characterise them as in opposition. For example, you say > Good OOP is none of that. It's simply associating data with code that operates on it If I wanted to characterise FP in opposition to that, I would say that Good FP is keeping the state (i.e. the data) dissociated from the code in order to gain the benefits of referential transparency, composability, reusability and abstraction (attaching code to state massively reduces your ability to abstract). FP tends to encourage the reuse of generic datastructures and vocabularies much more, while OOP likes to encourage you to create your own datatypes with their own vocabularies. Personally these days I like coding in an OO style with lots of learnings taken from FP, but the worldview that sees these as different poles on a continuum is not difficult for me to appreciate.
- jonahx 9y agoGreat explanations. What would you recommend reading to better understand capability theory?
- abecedarius 9y agoI'm not Kenton, but my favorite deeper look is Mark Miller's thesis, linked to at the top of the OP. As a shorter and less formal intro, there's http://www.erights.org/elib/capability/ode/index.html http://www.erights.org/elib/capability/ode/index.html
- kentonv 9y agoI am Kenton and that's pretty much what I would have said... :)
- solipsism 9y agoDo you have any examples of systems using such a technique? I'm interested in seeing something concrete.
- spc476 9y agoI did a proof-of-concept [1] of such a system several years ago in C/Lua to allow non-root users to bind to privileged ports [2]. The things I got from this were: 1) Odd that something like this hadn't been written for Unix years before as a way to avoid "set uid" programs and 2) passing FDs in Unix is a pain. 3) only Linux supports passing a PID along with the FD request (and Linux may be the only one to pass UID/GID as well, which may explain why 1 wasn't done). I don't really use that program as it's utility is limited. Shame, as I think it's a good idea but way too late to be of any use these days. [1] https://github.com/spc476/ipacld https://github.com/spc476/ipacld [2] You can see a set of "rules" in this file: https://github.com/spc476/ipacld/blob/master/ipacl.lua https://github.com/spc476/ipacld/blob/master/ipacl.lua