
What Are Capabilities? - abecedarius
http://habitatchronicles.com/2017/05/what-are-capabilities/
======
loeg
One interesting application of the idea of capabilities to an existing POSIX
system is FreeBSD's Capsicum. (There is also a Linux port of Capsicum, but it
has not been integrated into Torvalds' tree.)

In Capsicum, capabilities are tracked on a per file descriptor basis. A
typical program opens any input paths, restricts capabilities on open fds
(including stdio), and then enters sandbox mode.

Once the capability mode sandbox is entered, no additional capabilities can be
granted, and filesystem access via absolute paths is revoked. (Sandbox mode
programs are expected to access files they already have open, or to use
relative accesses to walk file trees.)

Erroneous system calls generate ECAPMODE or ENOTCAPABLE errors if they attempt
to perform actions they do not have permission to do.

~~~
Majora320
What prevents a Sandbox mode program from just using a chain of `··`s to
access the root?

~~~
loeg
Access to ".." above the "root" of a given dirfd are disallowed in the
sandbox.

So for example, if you have an open dirfd with the LOOKUP capability when you
enter the sandbox, you can access the following relative paths:

".", "./foo/bar", "./foo/.."

But you cannot access these relative paths:

"..", "./foo/../..", etc.

------
hierophantos
I have also made bulleted notes of this article a few months back:
[https://github.com/hierophantos/capable](https://github.com/hierophantos/capable)

Talking to one of the "O-Cap Gang", Norm Hardy ([http://www.cap-
lore.com/CapTheory/](http://www.cap-lore.com/CapTheory/)) a few weeks ago, he
said, to the point of creating secure distributed computing architectures:
"Object capabilities are not easy, but they're the only way I see forward."

I'm biased to agree.

------
tzahola
What prevents capability based security models from widespread adoption? Is it
again the fault of UNIX being “not bad enough”?

~~~
kentonv
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
Well... 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.

~~~
kentonv
Yes!

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
> 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.

------
eadmund
My own favourite metaphor for capabilities is that they are like physical
keys. If I have a key, I can easily go to a shop and make a copy of that key,
and give it to someone else. That other person will have all the access to the
things behind the lock that I have.

~~~
kentonv
Yes, but note more advanced capability systems go beyond that. You should not
only be able to give a friend a copy of your key, but also be able to _revoke_
their copy at any time, without also revoking your own copy or any other
copies you gave out. You should also be able to set things up so that your
friends' usage of the key is logged where you can see it. Your friend, OTOH,
cannot see the logs of _your_ use. But if your friend makes another copy to
give to a third party, both you and your friend can see the logs of that third
party's access. And if you revoke your friend's access, the third party is
transitively revoked as well. That is to say, it's a tree.

~~~
AgentME
Also, depending on the system, you could mint a copy of your key that can only
access part of your locker.

If your friend is really good at fooing widgets, you don't want to do it
yourself, and you don't want to continually bring all of your heavy widgets to
them, then you can make a copy of your key that can only access the part of
your locker holding your widgets and give that to them so they can come by and
foo your widgets for you.

With this system, you don't have to trust your friend to not mess with the
other contents of your locker. You don't have to trust them to not take the
money or personal documents you have in the other part of your locker. Maybe
you believe you fully trust this friend, but maybe you don't fully trust their
key-handling. If you gave them a restricted key, and you think one of your
personal documents is missing from your locker one day, then you can skip
worrying about whether it was your friend that's responsible. If your friend
loses their key one day (they misplaced it, or someone stole it from them),
then you don't need to freak out and worry about your personal documents; it's
only your widgets that are in danger. If someone knows that your friend is
given a lot of unrestricted keys to people's lockers, they might be
incentivized to try to steal/blackmail/threaten the friend for their keys so
they can get to people's important documents; if it's known that the friend
always requests restricted keys from people to foo their widgets, then an
attacker who doesn't care about widgets isn't incentivized to try to attack
the friend.

------
CMCDragonkai
Without the support of the OS, what are some examples of regular software
(multiuser webapps... etc) using the capability design. And does this imply
that the capability design only works internally and you cannot pass caps to
other applications?

~~~
kentonv
Lots and lots of software uses aspects of capability design internally,
sometimes intentionally, sometimes by accident.

In particular, many IPC mechanisms that involve more than a few parties
interacting -- especially when some or all parties are intended to be
sandboxed -- become capability systems.

Examples of real-world capability systems include:

\- Android's Binder

\- Chrome's Mojo

\- FreeBSD's Capsicum

\- Linux's Bus1 (not yet merged into mainline)

\- Classical Unix domain sockets (in that you can pass a file descriptor over
a socket).

\- Cap'n Proto RPC, especially as used in Sandstorm.io (disclosure: these are
my creations)

\- The Google Docs "anyone with the link can access" mode and e-mail
invitations to non-Google accounts (this is a relatively weak and
unintentional capability system).

\- OAuth 2's use of bearer tokens (also relatively weak).

> does this imply that the capability design only works internally and you
> cannot pass caps to other applications?

It's best if the applications agree on a capability protocol, but in some
cases you can trick applications into behaving in a capability-based way
without explicit support. For example, using secret, unguessable URLs can
allow for capability-like design patterns -- although at the risk that secret
URLs are relatively easy to leak (stronger capability systems can protect
against accidental leakage).

~~~
b1daly
Struggling to get my mind around this. One system I’m familiar with that comes
to mind is the Drupal CMS “permissions” system. You can set content types, and
along with associated fields.

There are things you can do: view a resource (in practice a page or a
particular field of a page), edit a resource, or create/delete a resource.

Users are assigned “roles” which are then given permission to do certain
things on various resources. It looks like a big grid, with all possible
actions as rows, and the various roles along the top as columns.

Users are assigned a role, which then limits what they can see/do on a
website.

This seems sort of akin to capabilities, but not quite. For one thing, there
is no easy way to set up the permissions for a single object, which you could
then assign to a given user.

To get that level of granularity you would have to create a new “role” and a
new object type.

~~~
kpreid
A capability system is sort of like having lots and lots of those roles. But a
key element is that within the system you don't have to be an administrator or
have any kind of privileged-operation access to create a new capability, you
just do it, and then you can pass it around (loosely equivalent to giving the
role to others).

Capability systems include a way to _pass_ capabilities as part of the basic
routine operations.

------
snvzz
For a very simple explanation, look at the Genode Foundations book (free,
available on their website)

------
EGreg
Capabilities have the following downside vs ACLs:

Someone can share them with someone else.

ACLs can be thought of as server-side mechanisms to increase the "specificity"
of capabilities. The typical capability that ACLs work with is "identity", ie
"I have access to this account."

The idea is that people won't be able to delegate fine grained capabilities to
someone else without giving the broad capability (access to their whole
netflix account etc.)

Now, the downside of ACLs is that they're much harder to do in a distributed
computing fashion. So instead of blockchains etc. you have to trust a certain
backend, and that backend can lock you out or become compromised.

Think of capabilities as client-side controlled access tokens and ACLs as
server side controlled ones.

~~~
kentonv
> Someone can share them with someone else.

Delegation is a feature, not a bug, because:

> the downside of ACLs is that they're much harder to do in a distributed
> computing fashion.

That's because large-scale work almost always requires delegation. So using a
system that tries to prevent delegation is really shooting yourself in the
foot -- but it seems fine at first, as long as the system stays simple. You
only run into trouble when things get complex, and the ACLs become completely
impossible to manage, but by then it's too late to make a fundamental design
change.

Now, you might insist that in some cases, you really do need to prevent
delegation. But it turns out ACLs don't really enforce this: I can always set
up a proxy server that has my credentials and provides some API to another
user, hence delegating my authority with whatever granularity I wish. No ACL
system prevents that, hence no ACL system prevents delegation!

Usually, what you really want is not to prevent delegation entirely, but
rather to prevent accidental policy breaches. That is, you trust that people
aren't _maliciously_ trying to circumvent the rules, but you aren't sure that
your users fully understand what the rules are or why they are in place. This
especially comes up in compliance scenarios: HIPAA or ITAR restrictions might
legally prohibit delegating some data, but the rules are so complicated that
not every employee in your company understands them. So, you want to enforce
some basic policy rules that prevent them from doing so.

It turns out this is a UI problem, not a security problem. In either an ACL
system _or_ a capability system, it's easy to design a UI that prevents such
user error, without the need to fundamentally change the underlying security
architecture.

But, we're too used to thinking of these compliance problems as something the
basic security architecture should enforce, rather than as a UI problem. So we
keep shooting ourselves in the feet.

~~~
noblethrasher
Indeed, one of the maxims of capability-based security is "don't try to
prohibit what you can't prevent".

~~~
EGreg
So when you have a sensitive document or a photo you only want to share with
20 friends, you should make it easy for it to get out?

In other words the capabilities maxim implies that privacy and DRM should not
exist.

~~~
kentonv
In every real-world security system I know of, if you share a sensitive
document or photo to a friend, it is trivial for them to make a copy and share
it widely. For example, if nothing else, they can copy/paste or take a
screenshot. You rely on your friend to respect your wishes in not doing this;
if you can't trust them, then you shouldn't share with them in the first
place.

~~~
EGreg
Right, but in practice when you build some social app you may want to
implement "banning someone from a chatroom" or "removing someone from your
friends list" or "repudiating a stole device" and so on.

So how do you do this? Let each friend have a unique capability such as
"friend"? And then revoke them on the server side when someone is taken out of
the group?

In that case you again have a list of which friend is allowed to access a
resource, aka an ACL. Which is what I was saying.

Now you may say this is totally ineffective since that friend could ask
another friend to be a proxy. But that's not very convenient usually, and
involves violating various trust, which is auditable btw since we know whose
capability was used. And also in a chatroom they won't be able anymore to
speak in their own name, but only the proxy friend's name.

Of course it's theoretically _possible_ to still do stuff, but according to
the capabilities motto, no one can be banned from a chatroom or from editing a
document as long as SOMEONE can edit it.

~~~
EtDybNuvCu
Capabilities support revocation:
[http://srl.cs.jhu.edu/pubs/SRL2003-02.pdf](http://srl.cs.jhu.edu/pubs/SRL2003-02.pdf)

Capabilities support audit trails:
[http://www.erights.org/download/horton/document.pdf](http://www.erights.org/download/horton/document.pdf)

I highly recommend that you read at least the first of these papers,
"Demolishing Capability Myths", which directly addresses your point.

~~~
EGreg
I remember reading that paper, and also about CapROS and KeyKOS when it came
out. I think there was also EROS back then.

Whatever happened to them?

