pam: use "pam_rootok" rather than "pam_deny" in the "auth" stacks of our PAM configs

PAM is a bit quirky: the main libpam calls are pam_authenticate(),
pam_open_session(), pam_acctmgmt(), pam_chauthtok(), pam_setcred() and
each have their own PAM "management group" in PAM configuration files
that configure the modules to call: "auth", "account", "session",
"password" – except for pam_setcred() which shares its grpup with
pam_authenticate() and uses "auth".

Both our PAM configuration files we ship by default are never used for
authentication (they just appear in PAMname= in a service to get a PAM
session set up, and PAMName= never calls pam_authenticate()). However,
they end up being used for pam_setcreds() (because some modules want to
use that the service manager calls it).

So far we used the pam_deny module for the "auth" management group for
these two PA; configurations (since
d6aed1dca8) but that's not ideal, since it
means we'll always cause pam_setcreds() to fail which will create debug
log noise (since the service manager debug logs pam_secreds() failures).

Let's switch to pam_rootok for this instead. This has the benefit that
pam_setcred() will always succeed for this, and pam_authenticate() only
if the caller is root anyway.

This is great, because it means our PAM configuration cannot be misused
for other purposes accidentally (authentication will fail, unless you
are already root), but won't result in any log noise (debug or
otherwise).

Follow-up for: d6aed1dca8
Fixes: #39617
This commit is contained in:
Lennart Poettering
2026-08-31 12:06:43 +02:00
parent f5d545ab77
commit 34e5f14c34
2 changed files with 12 additions and 2 deletions
+6 -1
View File
@@ -8,7 +8,12 @@
{% endif %}
account required pam_unix.so no_pass_expiry
auth required pam_deny.so
# systemd never invokes pam_authenticate() on this stack, but it does invoke pam_setcred(), which runs the
# "auth" stack too. Hence an "auth" entry is needed that lets pam_setcred() succeed, without falling back to
# the "other" service (which typically consists of pam_warn/pam_deny, and thus generates log noise).
# pam_rootok's pam_sm_setcred() unconditionally succeeds, while its pam_sm_authenticate() only succeeds for
# callers running as root (which the service manager does).
auth required pam_rootok.so
{% if HAVE_SELINUX %}
session required pam_selinux.so close
+6 -1
View File
@@ -8,7 +8,12 @@
{% endif %}
account required pam_unix.so
auth required pam_deny.so
# systemd never invokes pam_authenticate() on this stack (authorization for run0 is done via polkit), but it
# does invoke pam_setcred(), which runs the "auth" stack too. Hence an "auth" entry is needed that lets
# pam_setcred() succeed, without falling back to the "other" service (which typically consists of
# pam_warn/pam_deny, and thus generates log noise). pam_rootok's pam_sm_setcred() unconditionally succeeds,
# while its pam_sm_authenticate() only succeeds for callers running as root (which the service manager does).
auth required pam_rootok.so
{% if HAVE_SELINUX %}
session required pam_selinux.so close