On Tue, Jul 10, 2018 at 1:30 AM Bakul Shah <bakul@bitblocks.com> wrote:
On Sun, 08 Jul 2018 22:44:23 -0400 Dan Cross <crossd@gmail.com> wrote:
Dan Cross writes:
> On Sun, Jul 8, 2018 at 4:31 PM Perry E. Metzger <perry@piermont.com> wrote:
>
> > [snip]
> > On Wed, 4 Jul 2018 23:40:36 -0700 Bakul Shah <bakul@bitblocks.com>
> > wrote:
> > > - Capabilities (a number of OSes implemented them -- See Hank
> > > Levy's book: https://homes.cs.washington.edu/~levy/capabook/
> >
> > A fascinating resurrection of capabilities in a kind of pleasant
> > Unixy-way can be found in Robert Watson's "Capsicum" add-ons for
> > FreeBSD and Linux. I wish it was more widely known about and adopted.
> >
> > > - Namespaces (plan9)
> >
> > A good choice I think.
>
> Interestingly, it was in talking with Ben Laurie about a potential security
> model for Akaros that I realized the correspondence between Plan9-style
> namespaces and capabilities.

I tend to think they are orthogonal.  Namspaces map names to
objects -- they control what objects you can see.

In many ways, capabilities do the same thing: by not being able to name a resource, I cannot access it.

_A_ way to think of plan9 style namespaces are as objects, with the names of files exposed by a particular filesystem being operations on those objects (I'm paraphrasing Russ Cox here, I think). In the plan9 world, most useful resources are implemented as filesystems. In that sense, not only does a particular namespace present a program with the set of resources it can access, but it also defines what I can do with those resources.

Capabilities control what you can do with such an object. Cap
operations such as revoke, grant, attenunating rights
(subsetting the allowed ops) don't translate to namespaces.

I disagree. By way of example, I again reiterate the question I've asked several times now: there's a capability in e.g. Capsicum to allow a program to invoke the connect(2) system call: how does the capability system allow me to control the 5 tuple one might connect(2) to? I gave an example where, in the namespace world, I can interpose a proxy namespace that emulates the networking filesystem and restrict what I can do with the network.

A cap is much like a file descriptor but it doesn't have to be
limited to just open files or directories.

As an example, a client make invoke "read(fd, buffer, count)"
or "write(fd, buffer, count)". This call may be serviced by a
remote file server. Here "buffer" would be a cap on a memory
range within the client process -- we don't want the server to
have any more access to client's memory. When the fileserver
is ready to read or write, it has to securely arrange data
transfer to/from this memory range[1].

So in other words, "buffer" is a name of an object and by being able to name that object, I can do something useful with it, subject to the limitations imposed by the object itself (e.g., `read(fd, buffer, count);` will fault if `buffer` points to read-only memory).

You can even think of a cap as a "promise" -- you can perform
certain operations in future as opposed to right now. [Rather
than read from memory and send the data along with the write()
call, the server can use the buffer cap in future. The file
server in turn can pass on the buffer cap to a storage server,
there by reducing latency and saving a copy or two]

Similarly to the way that the existence of a file name in a process's namespace is in some ways a promise to be able to access some resource in the future.

>                              Since Akaros had imported a lot of plan9
> namespace code, we concluded that we already had the building blocks for a
> capability-style security model with minimal additional work. I
> subsequently concluded that Capsicum wasn't strong enough to be complete.

The point of my original comment was that if capabilities were
integral to a system (as opposed to being an add-on like
Capsicum) a much simpler Unix might've emerged.

[1] In the old days we used copyin/copyout for this sort of
data transfer between a user process address space and the
kernel. This is analogous.

It's an aside, but it's astonishing to see how that's been bastardized by the use of ioctl() for such things in the Linux world.

        - Dan C.