Capabilities
A Helpless Ping
Enough theory for now – let's go play. As a systems administrator, you are mostly concerned with file capabilities. These are also the most natural way to assign thread capabilities: The kernel does this for you during an execve(2)
call, following the rules above. In fact, there are only so many ways to change thread capabilities beyond this, even if you are a developer.
Two tools help us here. setcap sets file capabilities, while getcap reads them back. This is pretty simple. However, capabilities are somewhat convoluted, and so is the syntax of these tools.
setcap and getcap come via the libcap-something package and are likely already installed on your system, even if it doesn't use capabilities. Among distributions I have on my boxes, Fedora and Arch Linux employ capabilities while Ubuntu doesn't. Yet most distribution kernels now come with capabilities support enabled, so nothing prevents you from "deploying" capabilities on your own.
Consider a simple experiment (Figure 3). I open a terminal on my Kubuntu 16.04 LTS box and type:
$ ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.095 ms
Of course, it works. ping is setuid-root binary, so it has no troubles opening raw network sockets:
$ ls -l /bin/ping -rwsr-xr-x 1 root root 44168 May 8 2014 /bin/ping
Now, I do the following:
$ sudo setcap cap_net_raw-pe /bin/ping
Note that this requires root, as changing file capabilities is obviously a privileged operation. The CAP_SET_FCAP
capability controls who can do it, but as Ubuntu doesn't use capabilities system-wide, the most straightforward way to get CAP_SET_FCAP
in the thread effective set is sudo. Now, ping becomes hopelessly useless, even if it's still setuid-root:
$ ping 127.0.0.1 ping: icmp open socket: Operation not permitted
What's happened here? I've withdrawn CAP_NET_RAW
from the permitted file capabilities and effective capabilities set. The latter is a single bit on file level, so if you tell setcap to change effective capabilities, both permitted and inheritable are adjusted accordingly. A companion getcap tool will now show file capabilities as empty (Figure 1 again), but it's not the same as no capabilities at all.
Mixing capabilities with setuid/setgid bits isn't a good idea, and you can watch the kernel complaining about it in the logs:
$ dmesg | tail [39034.641585] warning: `/bin/ping' has both setuid-root and effective capabilities. Therefore not raising all capabilities
You only get a single instance of this warning regardless of how many times you execute the command. Note, however, that the root user still has all capabilities assigned, even if we've removed one from the file set:
$ sudo ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.095 ms
The comments in the kernel says it is done "just to cause the least surprise to an admin."
So, how do you make ping
operable again? There are two options. The first option is to grant the ping
command the capability you previously revoked:
$ setcap cap_net_raw+ep /bin/ping
Now, getcap shows it really worked as expected:
sudo getcap /bin/ping /bin/ping = cap_net_raw+ep
The second option is to rip /bin/ping
off file capabilities, just as it was before this experiment. setcap -r /bin/ping
does just this.
Now you may be wondering what these "cap_net_raw+ep" things are all about. This syntax comes from the cap_from_text(3)
function, which is a part of the libcap library (not to be confused with libpcap). Each expression starts with a case-insensitive capability name (or "all"), which is followed by a so-called action list. Each action is a combination of the operator (=
, +
, or -
) and a flag (e
, p
, i
for effective, permitted, and inheritable capabilities, respectively). The =
operator resets the capability in all three sets, whereas two others raise or lower it in a set denoted by the flag. So, cap_net_raw=
would also do the trick in our experiment, and cap_net_raw=+i
resets the capability in the permitted and effective set while raising it in the inheritable one. You can find further details in the cap_from_text(3)
man page [5].
Command of the Month: chattr
Capabilities are all about making root a less powerful user. However, there are other ways to limit what root can do on a Linux system.
You probably know how to write-protect a file. Do chmod ogu-w foo, and no one will be able to write to it. Do the same for the containing directory, and no one will be able to remove the file. Well, except the root user, obviously.
Is there a way to really write-protect a file? Yes, and it comes through a file-attributes mechanism. This mechanism is similar to capabilities in the sense that it's always there, but few people seem to know or care about it. Yet, it makes tricky things possible (Figure 4). Do you want a file you can only append, not overwrite?
$ sudo chattr +a foo $ echo bar >foo bash: foo: Operation not permitted $ echo baz >>foo $ cat foo baz
In a similar fashion, you can make a file immutable with chattr +i. Immutable files can't be modified or deleted, and it's impossible to create links to them. This is true even for the root user:
$ sudo chattr +i foo $ sudo rm foo rm: cannot remove 'foo': Operation not permitted
Of course, root or anyone else with CAP_LINUX_IMMUTABLE can remove these attributes with chattr -a and chattr -i, but they are still great to guard against accidental modifications.
Infos
- Linux capabilities list: http://lxr.free-electrons.com/source/include/uapi/linux/capability.h
- capabilities(7) man page: http://man7.org/linux/man-pages/man7/capabilities.7.html
- "Core Technology: Extended Attributes & POSIX ACLs" by V. Sinitsyn. Linux Voice, Issue 30 (September 2016), pp. 94-97.
cap_bprm_set_creds()
kernel function: http://lxr.free-electrons.com/source/security/commoncap.c#L492- cap_from_text(3) man page: https://linux.die.net/man/3/cap_from_text
- Valentine Sinitsyn develops high-loaded services and teaches students completely unrelated subjects. He also has a KDE developer account that he's never really used.
« Previous 1 2
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
TUXEDO Computers Unveils Linux Laptop Featuring AMD Ryzen CPU
This latest release is the first laptop to include the new CPU from Ryzen and Linux preinstalled.
-
XZ Gets the All-Clear
The back door xz vulnerability has been officially reverted for Fedora 40 and versions 38 and 39 were never affected.
-
Canonical Collaborates with Qualcomm on New Venture
This new joint effort is geared toward bringing Ubuntu and Ubuntu Core to Qualcomm-powered devices.
-
Kodi 21.0 Open-Source Entertainment Hub Released
After a year of development, the award-winning Kodi cross-platform, media center software is now available with many new additions and improvements.
-
Linux Usage Increases in Two Key Areas
If market share is your thing, you'll be happy to know that Linux is on the rise in two areas that, if they keep climbing, could have serious meaning for Linux's future.
-
Vulnerability Discovered in xz Libraries
An urgent alert for Fedora 40 has been posted and users should pay attention.
-
Canonical Bumps LTS Support to 12 years
If you're worried that your Ubuntu LTS release won't be supported long enough to last, Canonical has a surprise for you in the form of 12 years of security coverage.
-
Fedora 40 Beta Released Soon
With the official release of Fedora 40 coming in April, it's almost time to download the beta and see what's new.
-
New Pentesting Distribution to Compete with Kali Linux
SnoopGod is now available for your testing needs
-
Juno Computers Launches Another Linux Laptop
If you're looking for a powerhouse laptop that runs Ubuntu, the Juno Computers Neptune 17 v6 should be on your radar.