[cap-talk] ... enforcement - hope? Capabilities as clumsy, not

David Wagner daw at cs.berkeley.edu
Mon Sep 27 23:57:49 EDT 2004


Jed Donnelley writes:
>Can you describe more specifically how the standard C prototype
>for main() fails to follow a 'capability discipline'?

Sure.  The prototype for main() says that the caller must pass in a list
of strings.  If the caller wants to pass a file to the program, the caller
does so by passing a string that holds the file's name.  That violates
capability discipline.  There is no way to arrange that argv[1] holds
a capability to the file, instead of a filename represented as a string.

By the way, you can think of this lack of capability discipline as the
source of a large number of filesystem races (TOCTTOU bugs) in code.

Check out this buggy C code:
    int open_if_not_link(char *pathname) {
        stat(pathname, &statbuf);
        if (statbuf.st_nlink != 1)
            return -1;
        return open(pathname, O_RDONLY);
    }
If it had been written using capability discipline in some Java-like
language, we might instead have ended up with some code like the following
(which I believe can be secure if used with an appropriately designed
File object):
    File open_if_not_link(String pathname) {
        File f = new File(pathname);
        if (f.getNlinks() != 1)
            return null;
        return f;
    }
except that of course the very concept of passing in a pathname string
is a bad idea, and it should have been converted to a File object further
up in the code.  In C, we might try code something like this:
    int open_if_not_link(char *pathname) {
        int fd = open(pathname, O_RDONLY);
        fstat(fd, &statbuf);
        if (statbuf.st_nlink != 1) {
            close(fd);
            return -1;
        }
        return fd;
    }
except that this isn't actually safe, since open() can have side effects
in some rare cases.  The Unix OS does not provide the full set of operations
on file descriptors needed to replace all uses of pathnames with uses of
fds-as-capabilities.  If it did, I suspect the capability programming style
could be used to eliminate many TOCTTOU bugs pretty cleanly.

>We also
>went pretty far in an analysis of Unix circa 1985 and believed that
>we could have done a similar thing for the Unix API.

Can you elaborate on how you were planning to do this?

Suppose I run the following in a Unix shell:
  $ ./foo bar
Similarly, suppose a program executes:
  execv("./foo", {"./foo", "bar", NULL});
Should argv[1] ("bar") be interpreted as the name of a file,
or as a string containing ASCII text?  For instance, how do you
programmatically distinguish between the following two cases in
a way that respects capability discipline?
  $ echo Hello world
  $ cp notes notes.bak
Likewise, you can think of what you'll do if you see the
corresponding calls to execv().

I seem to recall there has been some prior discussion on this list of
things you might be able to do about this, and some of those ideas seemed
intriguing -- but I'm curious to hear more about what you came up with
at the time.  (Or did you already mention what you had come up with in
that prior thread?  I'm afraid that I've forgotten the source of the ideas
previously posted on this mailing list; if that was you, I apologize for
my poor memory.)


More information about the cap-talk mailing list