Implementing POSIX 1003.1e capabilities under Linux.


Due to the lack of support for capabilities in current Linux filesystems, capabilities have been disabled in kernels released after 2.2.14.

Under these kernels, privileges work in suser() emulation mode: any process whose uid is zero has a complete set of capabilities, while all others have the empty set.

Unfortunately, this prevents one from running proccesses with partial capability sets.

Until Linus returns the kernel to it's documented behavior, one must perform a bit of system tweaking if they wish to use capabilities as intended.


Raising the inital inheritable set:

Firstly, you must alter the initial inheritable set. This set will become the permitted and effective sets of those processes spawned by init.

This is most easily done by installing a patched init(8). I have provided an i386 and a src RPM for those who use RedHat-like distributions; however, for everyone else there is also a patch to apply to sysvinit-2.83.

Alternately, you may modify the following line in <linux/capability.h>

#define CAP_INIT_INH_SET to_cap_t(0)

to look like this:

#define CAP_INIT_INH_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))

and recompile your kernel. Both methods require a reboot to take effect.

Setting up /proc/sys/kernel/cap-bound:

/proc/sys/kernel/cap-bound is effectively a mask that the kernel uses to determine which individual capabilities work in suser() emulation mode. Each capability, enumerated in <linux/capability.h>, is a bit that if set, forces the capability to follow the legacy behavior.

Warning: Attempting this without first raising init(8)'s inheritable set, as above, will lower ALL capabilities for all uids, rendering the machine nearly useless.

To turn all bits in the mask off, returning the kernel to 1003.1e behavior, do the following:

# echo 0 >/proc/sys/kernel/cap-bound

Now you can use capabilities as they were intended.

The impetus to downgrade the kernel to the suser() behavior followed the discovery of this setuid() problem. While I have not been able to reproduce the bug in recent kernels, one would be safer keeping CAP_SETUID's bit on in the bounding set.

CAP_SETUID is currently bit seven; therefore

# echo $((1 << 7)) >/proc/sys/kernel/cap-bound

will leave setuid() calls in suser() emulation mode, while promoting the rest to POSIX 1003.1e behavior

Having corrected both the initial inheritable set and the bounding set, capabilites should now work as advertised in the supporting documentation.