Re: [patch 2.1.97] more capabilities support

Alexander Kjeldaas (astor@guardian.no)
Mon, 20 Apr 1998 11:18:51 +0200


On Sun, Apr 19, 1998 at 03:50:59PM -0700, Andrew Morgan wrote:
>
> They decide on a need for file attributes to specify the capabilities
> that a program can acquire as this is the most straightforward way for
> the sysadmin(s) to keep control of the system: in general, the model
> assumes that the security/reliability of "trusted" filesystems is
> guaranteed.
>
> My problem with things like CAP_SETPCAP is that it is ill defined: it
> places a large hole in the security model of the kernel and leaves it
> up to a user application to fill. I can see that in your language,
> this can also be read as "open to a world of possibility..." :^)
>
> Currently, the software security perimeter of the Linux kernel is the
> system call API. Adding CAP_SETPCAP for the express purpose of giving
> arbitrary capability control to a user space daemon seems like a
> really dramatic change.
>
> Perhaps it is just semantics, but this sort of ability seems to be
> much more appropriate to a "security module" than a user-space daemon.
>

CAP_SETPCAP is needed to implement file system support in user
space. There are other ways this could be done, but CAP_SETPCAP is
easy and straight forward.

IMO, CAP_SETPCAP isn't a security hole. It is more powerful than
CAP_SETFCAP, but only somewhat. CAP_SETFCAP is also something you
don't want to give to everybody. We don't currently _have_ CAP_SETFCAP
since we don't have file system support, so we use CAP_SETPCAP
instead. CAP_SETPCAP is what makes it possible to implement
CAP_SETFCAP in user space. POSIX doesn't deal with this issue.

Capabilities should be able to do what we previously used securelevel
for, so a system call which sets capabilities on all processes to
emulate the effect of a securelevel change can be designed. I imagine
something like the following system call interface:

setcap(int version, int pid, cap *inh, cap *perm, cap *eff);

where version gives both the size of the capabilities and possible
mappings needed. User space should do the necessary mapping, but it is
important to be able to catch old programs. pid 0 means current
process, -1 means all processes except current, and >0 means specific
process.

> > As such, we should _allow_ the capability to raise other capabilities. If
> > you don't like that capability, you can just make sure that it is cleared
> > at boot for everybody, and then nobody can inherit it and nobody can ever
> > get it any other way either (as nobody has the capability to raise the
> > capability).
>
> By definition, your opinion is the one that counts.
>
> I guess if I have to concede on this can I suggest that, at the very
> least, this should be a global is_secure(ALLOW_SETPCAP) condition?
> Otherwise, the "nobody can inherit it" part is only good as long as
> there is no executable sitting on a trusted filesystem that has this
> Permitted (Forced) bit raised. (Some protection against the equivalent
> of the current "setuid-root shell" that people like to have lying
> around... :^)

Why do we have to protect ourselves against the file system? I want to
protect my system against a non-trusted filesystem, but not a
_trusted_ filesystem with capabilities support.

How do you get this "setuid-root shell" with the CAP_SETPCAP bit
raised? On a capability-fs system you have to have the CAP_SETFCAP
capability to do this. CAP_SETFCAP is ultimate power and available to
the few selected ones so it shouldn't be trivial. This is an essential
difference between the "suid" system and the capability system. Anyone
can make a binary suid themselves, but you need the CAP_SETFCAP
capability to set forced capabilities. I guess one could say that on a
capability system you protect the file system from the user so you
don't have to do the reverse :-). When you can't protect the file
system from the user (normal file systems) you have to protect the
system from the file system by reading all capabilities as { 0 }.

If we do want to protect ourselves against the file system, I suggest
a global "securelevel" kind of capability set which all
read-file-capability operations are filtered through.

I aggree that having CAP_SETPCAP available to all uid=0 processes _by
default_ is a bad thing. This can be fixed by removing the CAP_SETPCAP
bit from the inheritable (and possibly effective) set of init_task. A
capability-aware init could then raise the bit when needed. This also
applies to the CAP_SETFCAP capability when implemented.

astor

-- 
 Alexander Kjeldaas, Guardian Networks AS, Trondheim, Norway
 http://www.guardian.no/

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu