Grant PAM Inheritable Capabilities with pam_cap
pam_cap hands a chosen user a defined set of inheritable capabilities the moment they authenticate. This covers configuring it and verifying the result from a fresh login, matching libpam-cap version 1:2.66-5ubuntu2.4 and its installed 2011-format manpages on Ubuntu 24.04.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need root access, a second login path or an existing root shell for recovery, and an actual reason to grant the capability. This module changes authentication-time process state; it does not make a capability useful by itself, and a bad PAM edit can disrupt logins for everyone.
1. Check the installed contract
Confirm the package and read the module's own configuration before you change anything:
$ dpkg-query -W -f='${Package} ${Version}\n' libpam-cap:amd64
libpam-cap 1:2.66-5ubuntu2.4
$ man pam_cap
$ man capability.conf
On this installed version, pam_cap reads /etc/security/capability.conf unless the PAM line supplies config=/path/to/capability.conf. It provides the authentication module type. The local manpage documents debug and config=; do not copy syntax from newer libcap documentation without checking the version on the target host.
Checkpoint
Make sure the module is actually present before you touch PAM:
$ test -r /usr/lib/x86_64-linux-gnu/security/pam_cap.so && echo 'pam_cap module is readable'
pam_cap module is readable
2. Find the existing PAM hook
Find where authentication gets assembled. This is an ordinary read-only check:
$ grep -RIn --include='common-auth' --include='login' --include='sshd' 'pam_cap\.so' /etc/pam.d 2>/dev/null
/etc/pam.d/common-auth:...:auth optional pam_cap.so
The line number and whether a hook exists at all vary by installation. The standard arrangement in the installed manual is an auth optional pam_cap.so line in /etc/pam.d/common-auth for applications that include common-auth, or the same line in a specific service file.
Do not add a second hook casually. Two calls make troubleshooting confusing, and dropping the module into a service that does not authenticate users will not do what you expect.
3. Back up both files before editing
This step needs elevated privileges and creates copies you can actually recover from. Use a private, timestamped directory rather than overwriting an older backup:
$ sudo install -d -m 700 /root/pam-cap-backup
$ sudo cp -a /etc/security/capability.conf /root/pam-cap-backup/capability.conf.before
$ sudo cp -a /etc/pam.d/common-auth /root/pam-cap-backup/common-auth.before
Warning
Keep an already authenticated root shell or console available. A malformed PAM stack can block every new login. Do not close your working session until a separate login has been tested and passed.
4. Add the narrowest capability rule
Open the configuration with root privileges:
$ sudoedit /etc/security/capability.conf
In this file format, each active rule has a comma-separated capability list followed by one or more whitespace-separated usernames. This example gives developer only cap_net_raw in their inheritable set:
cap_net_raw developer
Use names or numeric capability values, and never put whitespace inside the comma-separated list. The special names all and none must stand alone. none replaces the current inheritable set with an empty one; it is a useful explicit deny rule for a user, but it is still a security policy decision, not a no-op.
The first matching entry wins, so put a specific username before a wildcard rule:
# Specific users must precede the fallback.
cap_net_raw developer
none *
The wildcard applies to everyone not already matched. A later rule cannot add to or subtract from an earlier set, because the configured list replaces the process's current inheritable capabilities outright. If any capability name or number is invalid on the local system, the whole set is rejected and nothing is modified.
Checkpoint
Inspect the active, non-comment lines and watch for an accidental trailing rule:
$ sudo awk 'NF && $1 !~ /^#/ {print NR ":" $0}' /etc/security/capability.conf
14:cap_net_raw developer
15:none *
5. Make sure the authentication hook is present
If your earlier search found no suitable hook, edit the relevant PAM file as root. For applications that include common-auth, the installed manual gives this form:
$ sudoedit /etc/pam.d/common-auth
auth optional pam_cap.so
For an application that does not include common-auth, put the same line in that application's own PAM file. The optional control flag means the module's result does not by itself decide the overall authentication result; the module can still set capabilities when authentication reaches it.
You can point at an alternate configuration file explicitly, but use an absolute path and protect it exactly like the default:
auth optional pam_cap.so config=/etc/security/capability-developer.conf
Do not put secrets or user-controlled paths in this setting. If you switched on debug, expect diagnostic logging, and remove it once troubleshooting is done; it does not fix a bad rule.
6. Test a fresh authentication
Existing processes do not gain a new inheritable set retroactively. Start a new login through the service you configured, then inspect the child process. If capsh is installed, run:
$ command -v capsh
/sbin/capsh
$ capsh --print | grep -E 'Current IAB|Current:'
Current: =
Current IAB: cap_net_raw
The exact output depends on the host and the rest of its capability state. What matters is that the inheritable portion contains the capability you configured for that user. With none, expect an empty inheritable set. If capsh is not installed, inspect the new process's status instead:
$ grep '^CapInh:' /proc/self/status
CapInh: 0000000000002000
That hexadecimal value is host and capability-number dependent. Compare it against the capability mapping on that host rather than treating the sample number as universal.
If nothing has changed, check three things: the service actually used the PAM file you edited, the username matched the first applicable rule, and your test really was a new authentication. A successful PAM login on its own does not prove a capability was granted.
7. Recover or remove the policy
To undo the example, remove its active rule and remove the hook only if you added it for this change. Use the backup while your trusted root shell is still open:
$ sudo cp -a /root/pam-cap-backup/capability.conf.before /etc/security/capability.conf
$ sudo cp -a /root/pam-cap-backup/common-auth.before /etc/pam.d/common-auth
Then authenticate through a separate session and confirm the intended baseline. Do not restore both files blindly if other administrators have made legitimate changes since the backup; compare first with sudo diff -u.
Done means
- Version checked. The installed
libpam-capversion and module location were confirmed. - Order correct. A specific capability rule appears before any wildcard rule.
- Rule replaces, not adds. The rule uses the local file format and replaces, rather than augments, the inheritable set.
- Hook in the right place. The PAM hook sits exactly where the target application authenticates.
- Fresh login tested. A new login was checked with
capshor/proc/self/status. - Way back kept. A trusted recovery shell and your backups remain available until the test passes.