The idea of capabilities is to break the power of root (user ID 0) into independently assigned pieces governing specific privileged operations. Implicit in that model is that the set of privileged operations governed by each capability should be small (otherwise, why break the power of root into pieces at all?). However, that implication hasn't turned out to be true in practice.
Table 1 shows some statistics on the use of the 36 currently existing capabilities in the C files of the Linux 3.2 kernel source code. The "#uses" column is the number of uses of the capability across all source files; the "#files" column is the number of distinct source files where the capability is used.
Table 1: Breakdown of Linux capability uses in Linux 3.2
Capability | #uses | #files |
CAP_AUDIT_CONTROL | 2 | 2 |
CAP_AUDIT_WRITE | 1 | 1 |
CAP_CHOWN | 4 | 2 |
CAP_DAC_OVERRIDE | 2 | 1 |
CAP_DAC_READ_SEARCH | 4 | 2 |
CAP_FOWNER | 9 | 8 |
CAP_FSETID | 8 | 6 |
CAP_IPC_LOCK | 13 | 8 |
CAP_IPC_OWNER | 1 | 1 |
CAP_KILL | 2 | 2 |
CAP_LEASE | 1 | 1 |
CAP_LINUX_IMMUTABLE | 13 | 13 |
CAP_MAC_ADMIN | 25 | 5 |
CAP_MAC_OVERRIDE | 6 | 2 |
CAP_MKNOD | 3 | 3 |
CAP_NET_ADMIN | 395 | 182 |
CAP_NET_BIND_SERVICE | 13 | 10 |
CAP_NET_BROADCAST | 0 | 0 |
CAP_NET_RAW | 18 | 11 |
CAP_SETFCAP | 3 | 2 |
CAP_SETGID | 10 | 6 |
CAP_SETPCAP | 2 | 2 |
CAP_SETUID | 8 | 4 |
CAP_SYS_ADMIN | 451 | 229 |
CAP_SYS_BOOT | 2 | 2 |
CAP_SYS_CHROOT | 1 | 1 |
CAP_SYSLOG | 2 | 2 |
CAP_SYS_MODULE | 4 | 3 |
CAP_SYS_NICE | 14 | 8 |
CAP_SYS_PACCT | 1 | 1 |
CAP_SYS_PTRACE | 11 | 6 |
CAP_SYS_RAWIO | 67 | 42 |
CAP_SYS_RESOURCE | 36 | 24 |
CAP_SYS_TIME | 22 | 13 |
CAP_SYS_TTY_CONFIG | 11 | 4 |
CAP_WAKE_ALARM | 2 | 1 |
Total | 1167 | 610 |
What is of course notable is the extremely heavy use of two capabilities: CAP_SYS_ADMIN and CAP_NET_ADMIN. Together, these two capabilities account for more than 70% of all uses of capabilities! The uses of CAP_NET_ADMIN are limited to the drivers/ (mainly drivers/net/) and net/ directories. On the other hand, the uses of CAP_SYS_ADMIN, which accounts for nearly 39% of all capability uses, are spread widely across the kernel source tree.
One might wonder whether either of these two capabilities is overrepresented because of duplications in the drivers/ or the arch/ trees. (In particular, CAP_SYS_ADMIN is used for similar administrative functions on a lot of device drivers.) However, even if we strip drivers/ and architectures other than x86 from the measurements, the overall picture doesn't change greatly, as shown in Table 2.
Table 2: Breakdown of Linux capability uses in Linux 3.2, excluding drivers and architectures other than x86
Capability | #uses | #files |
CAP_AUDIT_CONTROL | 2 | 2 |
CAP_AUDIT_WRITE | 1 | 1 |
CAP_CHOWN | 4 | 2 |
CAP_DAC_OVERRIDE | 2 | 1 |
CAP_DAC_READ_SEARCH | 4 | 2 |
CAP_FOWNER | 9 | 8 |
CAP_FSETID | 8 | 6 |
CAP_IPC_LOCK | 11 | 6 |
CAP_IPC_OWNER | 1 | 1 |
CAP_KILL | 1 | 1 |
CAP_LEASE | 1 | 1 |
CAP_LINUX_IMMUTABLE | 13 | 13 |
CAP_MAC_ADMIN | 25 | 5 |
CAP_MAC_OVERRIDE | 6 | 2 |
CAP_MKNOD | 3 | 3 |
CAP_NET_ADMIN | 167 | 73 |
CAP_NET_BIND_SERVICE | 12 | 9 |
CAP_NET_BROADCAST | 0 | 0 |
CAP_NET_RAW | 18 | 11 |
CAP_SETFCAP | 3 | 2 |
CAP_SETGID | 9 | 5 |
CAP_SETPCAP | 2 | 2 |
CAP_SETUID | 8 | 4 |
CAP_SYS_ADMIN | 167 | 80 |
CAP_SYS_BOOT | 2 | 2 |
CAP_SYS_CHROOT | 1 | 1 |
CAP_SYSLOG | 2 | 2 |
CAP_SYS_MODULE | 4 | 3 |
CAP_SYS_NICE | 12 | 6 |
CAP_SYS_PACCT | 1 | 1 |
CAP_SYS_PTRACE | 10 | 5 |
CAP_SYS_RAWIO | 10 | 9 |
CAP_SYS_RESOURCE | 26 | 18 |
CAP_SYS_TIME | 4 | 2 |
CAP_SYS_TTY_CONFIG | 1 | 1 |
CAP_WAKE_ALARM | 2 | 1 |
Total | 552 | 291 |
CAP_SYS_ADMIN still accounts for 167 of 552 uses of capabilities--about 30%, and, by chance, usage of CAP_NET_ADMIN is the same.
It turns out that the overall picture hasn't changed that much since capabilities were first introduced with Linux 2.2 (Jan 1999). Then, there were 27 capabilities, broken down as shown in Table 3.
Table 3: Breakdown of Linux capability uses in Linux 2.2
Capability | #uses | #files |
CAP_CHOWN | 2 | 1 |
CAP_DAC_OVERRIDE | 5 | 5 |
CAP_DAC_READ_SEARCH | 4 | 4 |
CAP_FOWNER | 7 | 5 |
CAP_FSETID | 3 | 2 |
CAP_IPC_LOCK | 4 | 2 |
CAP_IPC_OWNER | 1 | 1 |
CAP_KILL | 0 | 0 |
CAP_LINUX_IMMUTABLE | 2 | 2 |
CAP_NET_ADMIN | 75 | 32 |
CAP_NET_BIND_SERVICE | 3 | 3 |
CAP_NET_BROADCAST | 0 | 0 |
CAP_NET_RAW | 8 | 6 |
CAP_SETGID | 7 | 2 |
CAP_SETPCAP | 2 | 2 |
CAP_SETUID | 7 | 3 |
CAP_SYS_ADMIN | 127 | 69 |
CAP_SYS_BOOT | 1 | 1 |
CAP_SYS_CHROOT | 1 | 1 |
CAP_SYS_MODULE | 4 | 2 |
CAP_SYS_NICE | 5 | 2 |
CAP_SYS_PACCT | 1 | 1 |
CAP_SYS_PTRACE | 9 | 9 |
CAP_SYS_RAWIO | 2 | 1 |
CAP_SYS_RESOURCE | 10 | 8 |
CAP_SYS_TIME | 7 | 4 |
CAP_SYS_TTY_CONFIG | 1 | 1 |
Total | 298 | 169 |
In Linux 2.2, CAP_SYS_ADMIN accounted for 42% of the uses of capabilities, and CAP_NET_ADMIN accounted for 25%.
Table 4 repeats the earlier exercise of excluding drivers/ and architectures other than i386 (as the Intel arch/ directory was then named) from the Linux 2.2 data. In this case, an interesting difference emerges.
Table 4: Breakdown of Linux capability uses in Linux 2.2, excluding drivers and architectures other than i386
Capability | #uses | #files |
CAP_CHOWN | 2 | 1 |
CAP_DAC_OVERRIDE | 5 | 5 |
CAP_DAC_READ_SEARCH | 4 | 4 |
CAP_FOWNER | 7 | 5 |
CAP_FSETID | 3 | 2 |
CAP_IPC_LOCK | 4 | 2 |
CAP_IPC_OWNER | 1 | 1 |
CAP_KILL | 0 | 0 |
CAP_LINUX_IMMUTABLE | 2 | 2 |
CAP_NET_ADMIN | 44 | 23 |
CAP_NET_BIND_SERVICE | 3 | 3 |
CAP_NET_BROADCAST | 0 | 0 |
CAP_NET_RAW | 8 | 6 |
CAP_SETGID | 7 | 2 |
CAP_SETPCAP | 2 | 2 |
CAP_SETUID | 7 | 3 |
CAP_SYS_ADMIN | 23 | 17 |
CAP_SYS_BOOT | 1 | 1 |
CAP_SYS_CHROOT | 1 | 1 |
CAP_SYS_MODULE | 4 | 2 |
CAP_SYS_NICE | 5 | 2 |
CAP_SYS_PACCT | 1 | 1 |
CAP_SYS_PTRACE | 2 | 2 |
CAP_SYS_RAWIO | 2 | 1 |
CAP_SYS_RESOURCE | 5 | 4 |
CAP_SYS_TIME | 3 | 1 |
CAP_SYS_TTY_CONFIG | 1 | 1 |
Total | 147 | 94 |
The overall picture differs in a way that I suspect is significant: just under 16% (23/147) of the uses of capabilities are CAP_SYS_ADMIN. (As we saw in Table 2, by Linux 3.2, this figure had grown to 30% (167/552).) This difference suggests to me that as a series of kernel developers was faced with the question: "What capability should I use to govern my new privileged kernel feature?", the answer was often something like "I don't know; maybe CAP_SYS_ADMIN?". (That certainly fits with a few anecdotal cases I've encountered while discussing things with kernel developers as I wrote man pages for new kernel features.)
The script (count_kernel_cap_uses.sh) used to generate the data for these statistics can be found here. The first and third tables above are based on analysis of the "p2" output files produced by the script. The second and fourth tables are based on analysis of the "p4" output files.
No comments:
Post a Comment