Improving capabilities support: need your opinion

Pietro Iglio (iglio@fub.it)
Fri, 11 Jun 1999 15:03:52 +0200


Sorry for the long message, but I'm working on an extension of the linux
capabilities to support fine-grained capabilities to access specified files
and I need your opinion.

Using the current implementation, if a program is setuid root only because
it needs to override some file permission problems, we give it
CAP_DAC_OVERRIDE instead of giving it ALL roots capabilities
(eventually, only for a short period of time).

That's good, but if we run unmodified setuid0 applications, most of them
need CAP_DAC_OVERRIDE (eg. to write on /var/utmp, /etc/shadow, etc.).
However, a setuid0 application with CAP_DAC_OVERRIDE is still very dangerous,
because an attacker that breaks such an application can become root, for
example adding a new entry in /etc/passwd, even if the setuid0 application
is running with euid = nobody.
One solution is to add a 'sandbox user' for the application instead of using
CAP_DAC_OVERRIDE, but this can probably work well only if we have ACLs and
it is still hard to track what a setuid0 application can do.

PROPOSED SOLUTION: to enforce least privilege explicitly specifying files
for which the standard access control should be overriden, along with the
required access mask.

I can explain with an example. Suppose that you have an application myapp
that needs write permission on a file owned by root with access mask 000,
eg. /etc/myapp.conf. You want to create a "safe setuid0", so that every user
can run myapp.
I have modified Pavel Machek's elf capabilities hack
(http://atrey.karlin.mff.cuni.cz/~pavel/elfcap.html) so that you can write
(as root):

#> chmod u+s myapp
#> setcap -u nobody -c FILE_ACCESS:/etc/myapp.conf:w myapp

that means: myapp is a setuid that will run with euid = nobody and that
has write access to /etc/myapp.conf.

IMPLEMENTATION DETAILS:

The list of files corresponding to the CAP_FILE_ACCESS (new) capability is
stored in the elf header. When myapp is executed, the kernel associates
a list of entries (inode_number, rdev, mask) to the corresponding process.
For this reason, I have extended task_struct. (inode_number, rdev) are
used to identify the file and are determined using the paths stored in
the elf header.

The file access control is performed as follows:

permission(inode, mask):

- if inode can be accessed with normal UNIX access control, then it's OK;
- otherwise, go through the list of file capabilities of the current process
and find an entry corresponding to inode, and check access according to
the corresponding mask;

Thanks in advance for your comments.

-- Pietro Iglio (iglio@fub.it)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/