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
Figure 3: Even if ping is setuid-root binary on Ubuntu, revoking a CAP_NET_RAW capability renders it perfectly useless.

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.

Figure 4: Filesystem attributes aren't strictly about capabilities, yet they also help to do tricky things with your files.

Infos

  1. Linux capabilities list: http://lxr.free-electrons.com/source/include/uapi/linux/capability.h
  2. capabilities(7) man page: http://man7.org/linux/man-pages/man7/capabilities.7.html
  3. "Core Technology: Extended Attributes & POSIX ACLs" by V. Sinitsyn. Linux Voice, Issue 30 (September 2016), pp. 94-97.
  4. cap_bprm_set_creds() kernel function: http://lxr.free-electrons.com/source/security/commoncap.c#L492
  5. cap_from_text(3) man page: https://linux.die.net/man/3/cap_from_text
  6. 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.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • AppArmor

    After penetrating a remote system, intruders might think they are home and dry, but AppArmor spoils the fun, locking the miscreants in a virtual cage.

  • Security Lessons

    We look at the history of the rootkit, including its newest incarnation, the DR RootKit.

  • Pony Programming Language

    Pony, an object-oriented programming language with static typecasting, trots down well-mapped paths to deliver secure, high-performance code for concurrent applications.

  • Pinger

    The Pinger network monitoring tool uses ping to look for switches and estimate cable lengths.

  • AppArmor

    Today's security environment is a tumultuous landscape riddled with threats. AppArmor offers an extra ring of protection for your system, and it is easier to learn and implement than many alternative mandatory access control solutions.

comments powered by Disqus
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.

Learn More

News