-- why this system may seem odd -- I have noticed that the UID 0 hack in the kernel is very gross. The kernel pretends that the file had fI and fE set. Ugh. Then consider the bits set in a normal user process. You can see them in /proc/*/status. Odd, isn't it? Now look at the pP etc. calculation. The _only_ capability sets that provide influence are pI and the file-based sets. This means that fI and fP are essentially the same thing! You can set a bit in either one, and the effect will be the same. Clearly this is not the intent. It seems that the pI bits were intended to be _unset_ for normal processes. This would make fP provide setuid-like effects and make ~fI be a mask used to make sure admins use authorized tools for their admin work. If I am right about this, then we should make pI unset for normal processes and assume that unmarked executables have a full fI. (only assume fI is full when running a somewhat normal system) With such a change, plain setuid root executables would get pI filled; this lets the full fI take effect. If you do the above but don't assume fI is full, then admins can only exercise their powers when running specially marked executables. This is nicely secure, but would make a terrible default. -- bit allocation -- Some of the undefined bits in pI should be _set_ and reserved for a time when Linux makes "normal" user rights be capabilities. Let's say that bits 32..63 are for network _client_ use, plain chmod, the fork() and exec() system calls, etc. Some of the undefined bits could be reserved for userspace. For example, there could be an X admin capability. The kernel would handle the inheritance of this bit, but would not use it. The X server could check the bit on local connections. -- new bitmap proposal -- I propose min and max data as follows: pm Always set these. pM If ~pM would be in pP' after the exec, then return -EPERM. fm If these bits would not be in pP' after the exec, then return -EPERM. fM Remove unset bits from pm. (?) Calculation becomes something like this: new_pP = fP | (fI & old_pI) | old_pm; if(new_pP & ~old_pM) return -EPERM; /* getting prohibited caps? */ if((new_pP & fm) != fm) return -EPERM; /* not enough? */ (the rest inherits in the obvious or documented way)