Skip to main content

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):

CapabilityDescription
CAP_NET_BIND_SERVICEBind to TCP/UDP ports below 1024
CAP_NET_RAWOpen raw sockets (needed for ping)
CAP_SYS_TIMEChange the system clock
CAP_CHOWNChange file ownership
CAP_DAC_OVERRIDEBypass file read, write, and execute permission checks
CAP_SYS_ADMINCatch-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.

References