Set PAM Inheritable Capabilities Safely with pam_cap
You will configure pam_cap so a selected user receives a defined inheritable capability set during PAM authentication, then verify the result from a fresh login. The examples match 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 a reason to grant the capability. This module changes authentication-time process state. It does not make a capability useful by itself, and an incorrect PAM edit can disrupt logins.
1. Check the installed contract
Confirm the package and read-only module configuration before editing anything:
$ dpkg-query -W -f='${Package} ${Version}\n' libpam-cap:amd64
libpam-cap 1:2.66-5ubuntu2.4
$ man pam_cap
$ man capability.conf
In 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 present before changing 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. Inspect the existing PAM hook
Find where authentication is 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 presence of a hook vary by installation. The standard arrangement described by 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 can make troubleshooting confusing, and placing the module in a service that does not authenticate users will not produce the result you expect.
3. Back up the two files before editing
This step needs elevated privileges and creates recoverable copies. Use a private directory with a timestamp 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 prevent a new login. Do not close your working session until a separate login has been tested.
4. Add the narrowest capability rule
Open the configuration with root privileges:
$ sudoedit /etc/security/capability.conf
For the installed 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 its inheritable set:
cap_net_raw developer
Use names or numeric capability values, and do not 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 set; it is a useful explicit deny rule for a user, but it is still a security policy decision.
The first matching entry wins. 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 matched earlier. A later rule cannot add to or subtract from an earlier set, because the configured list replaces the process's current inheritable capabilities. If any capability name or number is invalid on the local system, the set is rejected and is not modified.
Checkpoint: inspect the active, non-comment lines and check for accidental trailing rules:
$ sudo awk 'NF && $1 !~ /^#/ {print NR ":" $0}' /etc/security/capability.conf
14:cap_net_raw developer
15:none *
5. Ensure the authentication hook is present
If the 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 one application that does not include common-auth, put the same line in that application's PAM file. The optional control flag means the module's result does not by itself determine the overall authentication result. The module can still set capabilities when authentication reaches it.
An alternate configuration file can be selected explicitly, but use an absolute path and protect that file 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 enabled debug, expect diagnostic logging and remove it after troubleshooting; 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. The useful check is that the inheritable portion contains the capability you configured for the authenticated user. With none, expect an empty inheritable set. If capsh is not installed, inspect the new process status instead:
$ grep '^CapInh:' /proc/self/status
CapInh: 0000000000002000
The hexadecimal value is host and capability-number dependent. Compare it with the capability mapping on that host rather than treating the sample number as universal.
If the result is unchanged, check the service actually used the PAM file, the username matched the first applicable rule, and the test was a new authentication. A successful PAM login alone does not prove that a capability was granted.
7. Recover or remove the policy
To undo the example, remove its active rule and remove the hook only if it was added for this change. Use the backup while the trusted root shell is still available:
$ 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
- The installed
libpam-capversion and module location were checked. - A specific capability rule appears before any wildcard rule.
- The rule uses the local file format and replaces, rather than augments, the inheritable set.
- The PAM hook is present exactly where the target application authenticates.
- A fresh login was checked with
capshor/proc/self/status. - A trusted recovery shell and backups remain available until the test passes.