Record the Login UID with pam_loginuid
pam_loginuid stamps every process with the UID that actually logged in, before sudo or su can rewrite the story. This guide adds it to one real login entry point, on libpam-modules version 1.5.3-5ubuntu5.7. Allow about fifteen minutes, including a rollback check.
The route
Jump straight to the step you need, or tick off Done means at the end.
Checkpoint
This guide only changes a PAM configuration if you complete the optional edit in step 4. Keep an existing root shell or console session open while testing. A malformed PAM stack can lock out new logins, and pam_loginuid is not a general-purpose module for every PAM service.
1. Check the installed module and current login UID
Start with read-only checks. Ordinary users can run these; you do not need elevated privileges:
$ dpkg-query -W -f='${Package} ${Version}\n' libpam-modules:amd64
libpam-modules 1.5.3-5ubuntu5.7
$ test -r /proc/self/loginuid && cat /proc/self/loginuid
1000
$ ls -l /usr/lib/x86_64-linux-gnu/security/pam_loginuid.so
-rw-r--r-- 1 root root ... /usr/lib/x86_64-linux-gnu/security/pam_loginuid.so
That UID is a numeric process attribute, not necessarily the account a later command switches to. The exact number and file metadata are host-specific. If /proc/self/loginuid is absent, the module can return PAM_IGNORE. That is not proof the module is broken.
Checkpoint
The module file exists and the current process can read /proc/self/loginuid. Note the current value so you can compare it after a later login.
2. Choose the right PAM service
pam_loginuid provides only the session module type. Its job is to establish the login identity at an entry point such as login, sshd, a display manager, vsftpd, crond or atd. It should run when the user first enters the system, not afterwards.
- Never add it to sudo or su. Those commands deliberately switch to another account. Recording the switched-to account as the original login UID would wreck the audit trail the module exists to protect.
Find the service file that owns the entry point you intend to configure:
$ grep -Rns --include='*' 'pam_loginuid\.so' /etc/pam.d /etc/pam.conf 2>/dev/null
$ ls -l /etc/pam.d/sshd
-rw-r--r-- 1 root root ... /etc/pam.d/sshd
The first command may print nothing, and that is a useful result: it means you should inspect the service's included PAM files before adding a second line. PAM stacks often use include or substack, so a line in a shared file can affect more services than its filename suggests.
3. Understand the session line
The module's normal configuration is a session rule with the module name and no argument:
session required pam_loginuid.so
The required control flag makes a failure count against the session result, while letting the rest of the stack keep running. The manpage's full example also uses required. Do not copy that whole example into an existing service: its authentication, account and password lines belong to a separate stack and may conflict with your distribution's setup.
require_auditd is an optional module argument, not a command-line switch. When present, the module checks the audit daemon and denies the login if it is not running. That is a deliberate availability-versus-security trade-off. Leave it out unless your host's policy requires auditd to be up for every login, and you have tested the failure path.
4. Add the line with a rollback plan
Warning
Editing PAM can prevent authentication. Do not test a new stack by closing your only working root session. Make a root-owned backup first, then edit the specific entry-point file with elevated privileges. Replace /etc/pam.d/sshd below with the file you identified in step 2:
$ sudo cp -p /etc/pam.d/sshd /etc/pam.d/sshd.pam_loginuid.bak
$ sudoedit /etc/pam.d/sshd
Add one line in the existing session section:
session required pam_loginuid.so
Do not add the line twice, change unrelated controls, or add require_auditd during the first test. Save the file, then check the relevant section before attempting a new login:
$ sudo grep -n -C 3 'pam_loginuid\.so' /etc/pam.d/sshd
12-session required pam_unix.so
13-session required pam_loginuid.so
Spacing and line numbers vary. What matters is one occurrence in the intended stack, on a session line.
5. Test a fresh entry point and verify the value
Open a new connection or login through the entry point you changed, while keeping the original session open. Once inside the new session, run:
$ id -u
1000
$ cat /proc/self/loginuid
1000
The two values should match for a direct login by that user. The output is host-specific, so compare the numbers on your own machine rather than expecting 1000. To see the value a child process inherits, use a fresh shell rather than the old administrative session.
For a second check, inspect the service logs using whatever mechanism your system uses. On a systemd host this is read-only:
$ sudo journalctl -u ssh --since '10 minutes ago' --no-pager
-- No entries --
The unit name and output vary, and a successful session may produce no module-specific message. A clean new login plus a matching /proc/self/loginuid value is the check that actually tells you something.
6. Diagnose failures without guessing
- Rejected login. Stop testing new sessions and use the still-open root session. A
PAM_SESSION_ERRresult means an error prevented the attribute being set, or the requested audit-daemon check failed. Check spelling, module path, stack order and service logs. - Do not add require_auditd as a repair. It turns a missing audit daemon into a deliberate login denial, which makes the outage worse, not better.
- UID namespace in play. If the host uses a UID namespace and the kernel cannot overwrite
loginuid, the module can returnPAM_IGNORE. Check the namespace and kernel behaviour before changing PAM policy. - No /proc/self/loginuid. The same
PAM_IGNOREreturn is expected here, according to the installed manual.
If you need to undo the example, restore the backup from the root session and retest a new login:
$ sudo cp -p /etc/pam.d/sshd.pam_loginuid.bak /etc/pam.d/sshd
$ sudo grep -n 'pam_loginuid\.so' /etc/pam.d/sshd
grep: /etc/pam.d/sshd: no such file or directory
The final command should normally print nothing after rollback. The example path is tied to the earlier placeholder; use the actual service file and backup name you chose.
Done means
- Module confirmed. The installed pam_loginuid.so and its package version are known.
- Rule placed correctly. It appears once, in the session stack of a real login entry point.
- sudo and su left alone. Neither is used as the recording point.
- Fresh login verified. id -u and /proc/self/loginuid match after a new login.
- require_auditd deliberate. Only enabled if its login-denial behaviour was intended.
- Backup still in place until the new login path has earned your trust.