Linux Security — Capabilities (Part 1)

Shlomi Boutnaru, Ph.D.
2 min readSep 8, 2022

--

Historically, Linux has had two levels of permissions relevant from process: low privilege (effective uid is not 0) and high privilege (effective uid is 0, aka root). Since kernel 2.2 Linux has broken up the high privileges of the root user into smaller distinct units called capabilities.

We can assign only selected capabilities for a process/executable without the need to give the full root access. Thus, limiting the risk due to the reduction in the set of privileges granted.

Overall, there are 5 capabilities sets for a task (process or thread): CapEff (Effective Capabilities), CapPrm (Permitted Capabilities), CapInh (Inherited Capabilities), CapBnd (Bounding Set) and CapAmb (Ambient Capabilities Set). Let us go over each of these.

CapEff, this set represents all the capabilities the process is using at a specific moment in time. Those are the privileges which the kernel performs permission checks on.

CapPrm, this set is a superset which acts as a limiting boundary for the effective set. Those capabilities which are not set cannot be enabled in the effective set (they are some edge cases that we are going to talk about in the following write-up).

CapInh, specifies all the capabilities allowed to be inherited from parent to child, after a call to execve syscall (for privilege process/threads).

CapBnd, by using this we can block capabilities that we don’t want a process to receive, only those that are in the set will be allowed in the permitted and inherited sets.

CapAmb, applies to non-suid (non privileged) executables that don’t have file capabilities (more about it in the next write-up). The goal is to keep capabilities in case of calling the execve syscall family. It is important to know that not all the capabilities in the set can be kept like those which are dropped if they are not in the inheritable/permitted capability set.

In order to see the different sets for a task we can read the file “/proc/[pid]/status” (for a process) or “/proc/[pid]/task/[tid]/status” (for a specific thread) — as shown in the screenshot below (taken from a copy.sh).

There are different capabilities such as: CAP_AUDIT_LOG (gives the ability to write data to the kernel audit log), CAP_CHOWN (gives the ability to change the GIDs and UIDs of files), CAP_DAC_OVERRIDE (bypasses the permissions of files [r/w/x]) and more. To see the list of capabilities and the kernel version which they are relevant for please checkout “man capabilities”.

As written above we can set capabilities to a running process or the executables on disk. In the next writeup I am going to go over that — so we are still not finished with capabilities ;-) See you next time.

You can follow me on twitter — @boutnaru (https://twitter.com/boutnaru)

--

--