Linux Capabilities
Linux capabilities break down the traditional all-powerful root
privilege into smaller, fine-grained privileges. Instead of granting a process full root access, you can assign only the permissions it needs.
This helps improve security by applying the principle of least privilege: processes and binaries only get the powers they require, nothing more.
Key Concepts
-
Capability Sets: Each process has three important sets:
- Permitted → capabilities the process can potentially use
- Effective → capabilities the process is currently using
- Inheritable → capabilities that can be passed across
exec()
-
File Capabilities: Assigned to executables, so when run, the process gains only those privileges.
-
Process Capabilities: Can be modified at runtime, especially within containers or using tools like
capsh
.
Common Capabilities
Here are some commonly used ones (see man 7 capabilities
for the full list):
Capability | Description |
---|---|
CAP_NET_BIND_SERVICE | Bind to TCP/UDP ports below 1024 |
CAP_NET_RAW | Open raw sockets (needed for ping ) |
CAP_SYS_TIME | Change the system clock |
CAP_CHOWN | Change file ownership |
CAP_DAC_OVERRIDE | Bypass file read, write, and execute permission checks |
CAP_SYS_ADMIN | Catch-all for many privileged operations (sometimes called "root-lite") |
Examples
1. Granting ping
Non-root Access
By default, ping
requires raw sockets and thus root privileges. With capabilities, you can safely allow normal users to run it:
# Install capability tools if needed
sudo apt install libcap2-bin # Debian/Ubuntu
# Grant raw socket capability to ping
sudo setcap cap_net_raw+ep /bin/ping
# Verify
getcap /bin/ping
# /bin/ping = cap_net_raw+ep
Now any user can run ping
without requiring setuid root
.
2. Allowing a Service to Bind to Port 80
Normally, only root can bind to ports below 1024. You can allow a non-root web server to bind to port 80:
# Add capability to the binary
sudo setcap cap_net_bind_service=ep /usr/bin/mywebserver
# Check
getcap /usr/bin/mywebserver
# /usr/bin/mywebserver = cap_net_bind_service+ep
Then run mywebserver
as a regular user—no root required.
3. Restricting Access with Groups
You can combine capabilities with Unix groups for tighter control:
# Create group
sudo groupadd netbind
# Assign ownership and restrict permissions
sudo chgrp netbind /usr/bin/mywebserver
sudo chmod 750 /usr/bin/mywebserver
# Add users who should run the server
sudo usermod -aG netbind reece
Only members of netbind
can execute the binary, and when they do, it runs with the assigned capability.
4. Using Systemd to Control Capabilities
When running daemons, it’s safer to configure capabilities via systemd
:
[Service]
ExecStart=/usr/bin/mywebserver
User=www-data
Group=www-data
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
This ensures the service runs as www-data
with the minimal required privileges.
Best Practices
- Assign the least capabilities necessary.
- Avoid using
CAP_SYS_ADMIN
unless absolutely required. - Prefer file capabilities over
setuid root
binaries. - For services, use systemd’s capability options to enforce privilege boundaries.