mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
An ambient capability only reaches the effective set when euid is
non-zero, so a service that pairs `capabilities = { "^cap_..." }` with a
root user gets none of the restriction it asks for, and keeps the full
root set instead. Finit read the list, applied it, and said nothing. A
build without libcap dropped the list on the floor just as quietly.
Both now warn, naming the service:
nginx: ambient capabilities ('^') have no effect as root, use a
non-root user, or '%' and '!' entries
The ambient entries are read back from the parsed IAB value rather than
matched in the text, so inheritable ('%') and bounding ('!') entries stay
silent -- those work fine as root.
The warning repeats when the .conf files are re-read on runlevel change,
as parse warnings here already do.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
202 lines
6.8 KiB
Markdown
202 lines
6.8 KiB
Markdown
Linux Capabilities
|
|
==================
|
|
|
|
Finit supports Linux capabilities, allowing services to run with minimal
|
|
required privileges instead of running as root. This significantly improves
|
|
system security by following the principle of least privilege.
|
|
|
|
## Overview
|
|
|
|
Linux capabilities divide the traditional root privileges into distinct units
|
|
that can be independently granted to processes. For example, a web server only
|
|
needs the capability to bind to privileged ports (< 1024), not full root access.
|
|
|
|
Finit uses the modern IAB (Inheritable, Ambient, Bounding) API from libcap,
|
|
which is the same approach used by other modern service managers like dinit.
|
|
|
|
## Basic Usage
|
|
|
|
Capabilities are specified with the `capabilities` key, alias `caps`:
|
|
|
|
```conf
|
|
service nginx {
|
|
description = "Web server"
|
|
runlevel = "2345"
|
|
user = "www-data"
|
|
group = "www-data"
|
|
capabilities = { "^cap_net_bind_service" }
|
|
command = "/usr/sbin/nginx -g 'daemon off;'"
|
|
}
|
|
```
|
|
|
|
This example allows nginx to bind to privileged ports (like 80 and 443) while
|
|
running as the unprivileged `www-data` user.
|
|
|
|
## IAB Format
|
|
|
|
The capability string uses the IAB (Inheritable, Ambient, Bounding) format
|
|
with the following prefixes:
|
|
|
|
- `^` **Ambient** (and Inheritable) - **Recommended for most use cases**
|
|
- Capabilities survive across `exec()` calls
|
|
- Automatically raised to effective after exec
|
|
- Example: `^cap_net_bind_service`
|
|
|
|
- `%` **Inheritable** only
|
|
- Requires the executed binary to have matching file capabilities
|
|
- Less common, more complex setup
|
|
- Example: `%cap_net_admin`
|
|
|
|
- `!` **Bounding** - Block capability from bounding set
|
|
- Prevents the service from ever acquiring this capability
|
|
- Useful for security hardening
|
|
- Example: `!cap_sys_admin`
|
|
|
|
Multiple capabilities can be specified as a comma-separated list:
|
|
|
|
```conf
|
|
capabilities = { "^cap_net_raw", "^cap_net_admin", "^cap_net_bind_service" }
|
|
```
|
|
|
|
## Common Use Cases
|
|
|
|
### Web Server (Privileged Ports)
|
|
|
|
Allow a web server to bind to ports 80 and 443 without running as root:
|
|
|
|
```conf
|
|
service webserver {
|
|
runlevel = "2345"
|
|
user = "www-data"
|
|
group = "www-data"
|
|
capabilities = { "^cap_net_bind_service" }
|
|
command = "/usr/sbin/nginx -g 'daemon off;'"
|
|
}
|
|
```
|
|
|
|
### Network Monitoring (Raw Sockets)
|
|
|
|
Allow packet capture without root privileges:
|
|
|
|
```conf
|
|
service tcpdump {
|
|
runlevel = "2345"
|
|
user = "tcpdump"
|
|
capabilities = { "^cap_net_raw", "^cap_net_admin" }
|
|
command = "/usr/sbin/tcpdump -i eth0 -w /var/log/capture.pcap"
|
|
}
|
|
```
|
|
|
|
### NTP Daemon (System Time)
|
|
|
|
Allow time synchronization without full root:
|
|
|
|
```conf
|
|
service ntpd {
|
|
runlevel = "2345"
|
|
user = "ntp"
|
|
capabilities = { "^cap_sys_time", "^cap_sys_nice" }
|
|
command = "/usr/sbin/ntpd -n"
|
|
}
|
|
```
|
|
|
|
## Available Capabilities
|
|
|
|
Common capabilities include (see `man 7 capabilities` for the complete list):
|
|
|
|
- `cap_chown` - Make arbitrary changes to file UIDs and GIDs
|
|
- `cap_dac_override` - Bypass file read, write, and execute permission checks
|
|
- `cap_dac_read_search` - Bypass file read permission checks
|
|
- `cap_fowner` - Bypass permission checks on operations that normally require filesystem UID
|
|
- `cap_kill` - Bypass permission checks for sending signals
|
|
- `cap_net_admin` - Perform various network-related operations
|
|
- `cap_net_bind_service` - Bind to privileged ports (< 1024)
|
|
- `cap_net_raw` - Use RAW and PACKET sockets
|
|
- `cap_setgid` - Make arbitrary manipulations of process GIDs
|
|
- `cap_setuid` - Make arbitrary manipulations of process UIDs
|
|
- `cap_sys_admin` - Perform system administration operations (very powerful!)
|
|
- `cap_sys_module` - Load and unload kernel modules
|
|
- `cap_sys_nice` - Raise process nice value and change scheduling
|
|
- `cap_sys_time` - Set system clock
|
|
|
|
## Security Best Practices
|
|
|
|
1. **Use the minimum required capabilities**
|
|
- Only grant what the service actually needs
|
|
- Don't grant `cap_sys_admin` unless absolutely necessary
|
|
|
|
2. **Specify a user (preferably non-root)**
|
|
- The `user` setting is **required** for `capabilities` to take effect
|
|
- For ambient capabilities (`^`), use a non-root user (not `"root"`)
|
|
- Example: `user = "www-data"`, `user = "nginx"`, `user = "tcpdump"`
|
|
|
|
3. **Use ambient capabilities (`^`)**
|
|
- The `^` prefix ensures capabilities survive exec()
|
|
- Simpler than setting file capabilities on binaries
|
|
|
|
4. **Block dangerous capabilities**
|
|
- Use `!` to explicitly block capabilities you don't want
|
|
- Example: `!cap_sys_admin,!cap_sys_module`
|
|
|
|
5. **Test with `getpcaps`**
|
|
- After starting a service, verify its capabilities:
|
|
```bash
|
|
getpcaps $(pidof nginx)
|
|
```
|
|
- Should show only the capabilities you granted
|
|
|
|
## Verification
|
|
|
|
After configuring a service with capabilities, verify it works correctly:
|
|
|
|
```bash
|
|
# Start the service
|
|
initctl start webserver
|
|
|
|
# Check the process capabilities
|
|
getpcaps $(pidof nginx)
|
|
|
|
# Should show something like:
|
|
# 12345: cap_net_bind_service=eip
|
|
|
|
# Verify the user
|
|
ps -o user,pid,cmd -p $(pidof nginx)
|
|
|
|
# Should show the service running as the specified user
|
|
```
|
|
|
|
## Requirements
|
|
|
|
- Linux kernel 4.3+ (for ambient capabilities support)
|
|
- libcap library installed
|
|
- Finit built with `--enable-libcap`, otherwise a `capabilities` list is
|
|
ignored, with a warning
|
|
|
|
## Limitations
|
|
|
|
- `capabilities` requires `user` to be set for it to take effect
|
|
- Without `user`, the service runs as root with full capabilities and
|
|
the `capabilities` list is silently ignored
|
|
- You can use `user = "root"`, but see below about ambient capabilities
|
|
- For ambient capabilities (`^`, recommended), the user **must be non-root**
|
|
- Using `user = "root"` with `^` capabilities will not work effectively, as ambient
|
|
capabilities are only added to the effective set when euid ≠ 0
|
|
- Use inheritable (`%`) or bounding (`!`) capabilities with `user = "root"` if needed
|
|
- Finit warns about this when reading the .conf file:
|
|
|
|
nginx: ambient capabilities ('^') have no effect as root, use a
|
|
non-root user, or '%' and '!' entries
|
|
- Services without `capabilities` use standard privilege dropping:
|
|
- Services with a non-root `user` have no special capabilities
|
|
- Services without `user` run as root with full capabilities
|
|
- Some very old binaries may not work correctly with ambient capabilities
|
|
- File system capabilities are not managed by Finit (use `setcap` for that)
|
|
|
|
## See Also
|
|
|
|
- [capabilities(7)](https://man7.org/linux/man-pages/man7/capabilities.7.html) - Linux capabilities overview
|
|
- [cap_iab(3)](https://man7.org/linux/man-pages/man3/cap_iab.3.html) - IAB capability API documentation
|
|
- [setcap(8)](https://man7.org/linux/man-pages/man8/setcap.8.html) - Set file capabilities
|
|
- [getcap(8)](https://man7.org/linux/man-pages/man8/getcap.8.html) - Query file capabilities
|
|
- [capsh(1)](https://man7.org/linux/man-pages/man1/capsh.1.html) - Capability shell wrapper
|