diff --git a/pam-1.6.1-pam-faillock-skip.patch b/pam-1.6.1-pam-faillock-skip.patch new file mode 100644 index 0000000..02012dd --- /dev/null +++ b/pam-1.6.1-pam-faillock-skip.patch @@ -0,0 +1,89 @@ +From 7d96d452e65ba5dec73f2c77104113977dd3aeb1 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 18 Jul 2025 16:11:39 +0200 +Subject: [PATCH] pam_faillock: skip clearing user's failed attempt + +Automated services, like `crond` or `systemd-user`, skip the +`auth` stack and directly invoke the `account` stack. Thus, they can +clear the user's failed attempt records. With this new logic simply +skip resetting the failed login counter when `auth` stack hasn't been +been run prior to `account` stack. + +* modules/pam_faillock/pam_faillock.c: Skip clearing the user's failed +attempt record during `account` stack when `auth` stack isn't run. +* modules/pam_faillock/pam_faillock.8.xml: Document new behaviour. + +Resolves: https://issues.redhat.com/browse/RHEL-32294 +Signed-off-by: Iker Pedrosa +--- + modules/pam_faillock/pam_faillock.8.xml | 8 ++++++++ + modules/pam_faillock/pam_faillock.c | 13 +++++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/modules/pam_faillock/pam_faillock.8.xml b/modules/pam_faillock/pam_faillock.8.xml +index ce0ae050..42f87e81 100644 +--- a/modules/pam_faillock/pam_faillock.8.xml ++++ b/modules/pam_faillock/pam_faillock.8.xml +@@ -243,6 +243,14 @@ + user accounts allowing the adversary to infer that a particular account + is not existing on a system. + ++ ++ If the stack has not been run prior to the ++ stack, the logic to reset the failed login counter is intentionally skipped. This prevents ++ automated services, such as crond or systemd-user, ++ which might only perform account management tasks, from inadvertently clearing a user's ++ failed attempt records. This ensures the faillock counter is only reset by a service that ++ performs a full, successful authentication. ++ + + + +diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c +index 2d847aeb..a8363b6c 100644 +--- a/modules/pam_faillock/pam_faillock.c ++++ b/modules/pam_faillock/pam_faillock.c +@@ -62,6 +62,8 @@ + #define FAILLOCK_ACTION_AUTHSUCC 1 + #define FAILLOCK_ACTION_AUTHFAIL 2 + ++#define FAILLOCK_AUTH_EXECUTED "pam_faillock:auth_executed" ++ + static int + args_parse(pam_handle_t *pamh, int argc, const char **argv, + int flags, struct options *opts) +@@ -478,6 +480,10 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, + goto err; + } + ++ rv = pam_set_data(pamh, FAILLOCK_AUTH_EXECUTED, (void *)1, NULL); ++ if (rv != PAM_SUCCESS) ++ goto err; ++ + if (!(opts.flags & FAILLOCK_FLAG_LOCAL_ONLY) || + check_local_user (pamh, opts.user) != 0) { + switch (opts.action) { +@@ -531,6 +537,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + struct options opts; + int rv, fd = -1; + struct tally_data tallies; ++ const void *auth_flag; + + memset(&tallies, 0, sizeof(tallies)); + +@@ -541,6 +548,12 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + + opts.action = FAILLOCK_ACTION_AUTHSUCC; + ++ rv = pam_get_data(pamh, FAILLOCK_AUTH_EXECUTED, &auth_flag); ++ if (rv == PAM_NO_MODULE_DATA) { ++ rv = PAM_SUCCESS; ++ goto err; ++ } ++ + if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { + goto err; + } +-- +2.52.0 + diff --git a/pam.spec b/pam.spec index 9b75e28..bb7576d 100644 --- a/pam.spec +++ b/pam.spec @@ -4,7 +4,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.6.1 -Release: 8%{?dist} +Release: 9%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ # - this option is redundant as the BSD license allows that anyway. # pam_timestamp and pam_loginuid modules are GPLv2+. @@ -37,6 +37,8 @@ Patch7: pam-1.6.1-pam-access-resolve-ip.patch Patch8: pam-1.6.1-pam-inline-pam-asprintf.patch # https://github.com/linux-pam/linux-pam/commit/976c20079358d133514568fc7fd95c02df8b5773 Patch9: pam-1.6.1-pam-namespace-rebase.patch +# https://github.com/linux-pam/linux-pam/commit/7d96d452e65ba5dec73f2c77104113977dd3aeb1 +Patch10: pam-1.6.1-pam-faillock-skip.patch %{load:%{SOURCE3}} @@ -136,6 +138,7 @@ cp %{SOURCE18} . %patch -P 7 -p1 -b .pam-access-resolve-ip %patch -P 8 -p1 -b .pam-inline-pam-asprintf %patch -P 9 -p1 -b .pam-namespace-rebase +%patch -P 10 -p1 -b .pam-faillock-skip autoreconf -i @@ -374,6 +377,10 @@ done %{_pam_libdir}/libpam_misc.so.%{so_ver}* %changelog +* Mon Dec 1 2025 Iker Pedrosa - 1.6.1-9 +- pam_faillock: skip clearing user's failed attempt. + Resolves: RHEL-130871 + * Tue Jul 1 2025 Iker Pedrosa - 1.6.1-8 - pam_namespace: fix potential privilege escalation. Resolves: CVE-2025-6020 and RHEL-101174