Re: updated proposal for cap in elf

Albert D. Cahalan (acahalan@cs.uml.edu)
Mon, 19 Apr 1999 01:59:00 -0400 (EDT)


Y2K writes:
> On Sat, 17 Apr 1999, Albert D. Cahalan wrote:

>>> pI' = pI
>>> pP' = fP | ( fI & pI & pP)
>>> pE' = fE & pP'
>>
>> No, this is bad. Consider an admin with the bits below. Normal users
>> on this system don't get any bits set, unlike the current default.
>> pI == 00000000fffffeff
>> pP == 0000000000000000
> I would think pP should be pP == 00000000fffffeff

Nope, this is for a highly secure system.

>> pE == 0000000000000000
> pE should maybe be a little higher so that some of the shell builtins work
> like echo 'foo' >> /etc/passwd still work ;->

Nope, shell builtins are not supposed to have such power.
Admins are expected to use a tool with proper logging and locking
when they modify the password file.

>> The admin is only allowed to do his work via tools that leave an
>> audit trail, so his shell only has the above. The shell can't do
>> anything at all.
> Auditing would be more reliable on a per sys-call basis IMHO.
> Especially since for legacy situations mv does no inherent logging.
> Also I think that shell builtins should work if they still need some caps.

Both high-level and low-level auditing may be done. There was once a
Linux distribution that added auditing support to /bin/mv and all other
normal tools.

>> The /bin/mv executable has bits set in fI. Normal users should not
>> get any special rights when they run /bin/mv, but the admin should
>> gets a few capability bits in pP when running it.
>
> Yes in the old formula it would be 00fffffeff using old formula and your
> numbers -- I consider that a bug you a feature. Under my system normals
> don't get special rights, but enhanced users would be able to use caps
> even in his shell builtins or legacy programs.

Well, this is bad. I think the draft was poorly done, but I think that we
should be able to turn off Linux extensions. I'd like to see

1. traditional UNIX
2. pure draft standard
3. something that isn't so extreme

This works:
/* pP_control_config is a global kernel setting */
new_pP = fP | (fI & old_pI) | (old_pP & pP_control_config);

This works:
/* old_pm is full for a backwards-compatible root user */
new_pP = fP | (fI & old_pI) | old_pm;

This works:
/* You can have it all! */
new_pP = fP | (fI & old_pI) | (old_pP & pP_control_config) | old_pm;

> Under my system he would get his powers in pP' because his old pP had the
> power and it didn't get masked out. Normals would not have had the cap in
> their pP.

The problem: on high-security systems, an admin's shell has an empty pP.

>> For /bin/mv, the bits are:
>>
>> fI == 00000000fffffeff
>> fP == 0000000000000000
>> fE == 0000000000000000
> For backwards compatibility fE would have to be non-zero.
> Since mv doesn't do many network stuff or change uid, etc it should set
> its fI much lower hypothetically 0e4a .
> fP should be zero.

Sure, fI should be something less and fE would need to match if the
/bin/mv command does not support the new security system.

The important point is that fI should contain some bits.

>> Your system would not give /bin/mv the capabilities it needs to have.
>> I think you were expecting that pP would contain something, and that
>> a normal user would have bits set in pI. These are bad assumptions.
>
> Yes pP should be what that process and what its children might need
> inherite. Normals may or may not have a non zero pI I'd think it would
> start out to be somewhat high.

Well, this is just broken. It means the admin's shell can do anything.
I'd like to support that behavior as an option, not as the only way.

>> In the "pP' = fP | (fI & pI)" expression you can see that the admin
>> gets power from the "(fI & pI)" part, while normal users can only get
>> power from the "fP" part. All of the admin's special rights are stored
>> in the pI value, since the other values do not even influence an exec().
>
> What about the situation where a user calls a legacy program that was suid
> root but now gains stuff from fP but it does some of its work by calling
> other programs that still need those privledges?

There are several options.

1. The pP_control_config hack above could fix this.
2. Most programs like that are security holes already.
3. Perhaps fE should influence the new pI... (must be an option)

Considering option 3, one could have this:
new_pI = old_pI | (fE & fE_control_config);

> I don't think anybody should gain power from fI only from pP(heavily
> masked by inheritance flags) or fP. It sounds like your pI is a
> quazi-permitted bit. I can't do it but this indicates that maybe one of my
> children will say I can whereas if not then I could not use it.

It is strange indeed. For compatibility, you may wish to assume that
unmarked executables have a full fI set.

>> No, we need a set of bits (I'll call it "pm") that are always added to pP.
>> The set would be 0 for maximum security or normal users, and ~0 for an
>> admin on a more normal system. This might be help kill off the ugly hack
>> in exec.c that pretends an executable has fI and fE full if UID 0 runs it.
>
> What you call pm I call pI & pP which then gets further masked by fI.
> What would you have for defaults on trusted marked binaries? untrusted
> marked ones?

Trusted marked binaries get exactly what they specify.

Untrusted binaries (marked or not) get a full fI at boot,
but this may be reduced system-wide by writing to a file in /proc.

>> new_pP = fP | (fI & old_pI) | old_pm;
>> if(new_pP & ~old_pM) return -EPERM; /* getting prohibited caps? */
> Why are you getting prohibited caps thats why there is fI?

They come from old_pm, the substitute for the UID 0 hack in exec.c.
It may be better to reduce old_pm before calculating new_pP instead.

>> if((new_pP & fm) != fm) return -EPERM; /* not enough? */
> That I can see as being potentialy useful.

It helps avoid crashing privileged processes. At the very least,
users and tech support will prefer "permission denied" over crashes.
It will most likely stop some DoS attacks and maybe worse.

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