Skip to content

auth/pam: auto-retry once on PAM_SYSTEM_ERR with configurable delay - #1079

Closed
rsacherer wants to merge 1 commit into
hyprwm:mainfrom
rsacherer:pam-system-err-retry
Closed

rsacherer wants to merge 1 commit into
hyprwm:mainfrom
rsacherer:pam-system-err-retry

Conversation

@rsacherer

Copy link
Copy Markdown

Problem

On systems using SSSD with Kerberos/IPA authentication (common in enterprise environments), hyprlock frequently requires the user to enter their password twice after long idle periods.

Root cause

When hyprlock locks, pam_authenticate() is called immediately (necessary for fingerprint auth). This triggers SSSD's Kerberos preauth flow, which spawns a krb5_child subprocess that contacts the KDC and then waits for the password via a pipe.

SSSD's krb5_child_handler.c has a hardcoded 300-second keep-alive timer for this child process:

tv = tevent_timeval_current_ofs(300, 0);
te = tevent_add_timer(ev, io, tv, child_keep_alive_timeout, io);
// "This timeout is quite big to allow additional user interactions
//  when the child is kept alive for further communication."

After 5 minutes, SSSD kills krb5_child. When the user eventually unlocks, pam_sss attempts to send the password to the now-dead process and returns PAM_SYSTEM_ERR (code 4). The second attempt spawns a fresh child and succeeds.

There is no SSSD configuration option to change this hardcoded timeout.

Solution

Detect PAM_SYSTEM_ERR specifically — it is a transient infrastructure failure, never a wrong password — and automatically retry pam_authenticate() once after a short delay using the same credentials. An autoRetry flag on SPamConversationState tells conv() to skip waitForInput() and return the already-available password immediately.

Two new auth:pam config options (both with sensible defaults so no config change is required):

auth {
    pam {
        retry_on_error = true   # retry once on PAM_SYSTEM_ERR
        retry_delay = 3000      # delay in ms before retrying (default 3s)
    }
}

PAM_AUTH_ERR (wrong password) is never retried.

Behaviour

  • Normal case: no change — PAM_SYSTEM_ERR is rare when SSSD is healthy
  • After long idle (>5 min) on Kerberos/SSSD: instead of "Authentication failed" + re-prompt, user sees a brief ~3s pause, then unlocks transparently
  • retry_on_error = false: restores previous behaviour exactly

🤖 Generated with Claude Code

PAM_SYSTEM_ERR (code 4) from pam_sss is a transient infrastructure
failure, not a wrong password. It occurs when SSSD's krb5_child process
has been killed by its hardcoded 300-second keep-alive timer before the
user submits their password — the dead process can no longer receive
credentials, so pam_sss returns a system error.

Rather than surfacing this as an authentication failure and forcing the
user to re-enter their password, detect PAM_SYSTEM_ERR specifically,
wait retry_delay milliseconds, and retry pam_authenticate once with the
same credentials. The retry uses the autoRetry flag to skip the conv()
waitForInput() block since the password is already available.

Two new auth:pam config options (both enabled by default):
  auth:pam:retry_on_error = true   # enable/disable the retry
  auth:pam:retry_delay    = 3000   # delay in ms before retrying

If the retry also fails, the error is surfaced normally. PAM_AUTH_ERR
(wrong password) is never retried.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@rsacherer

Copy link
Copy Markdown
Author

Closing while we investigate a follow-up issue — the retry sometimes fails due to PAM stack interaction (pam_faildelay + pam_sss forward_pass). Will reopen with a proper fix once confirmed working.

@rsacherer rsacherer closed this Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant