Skip to content

fix(greeter): do not cancel the session on a non-fatal PAM error message - #512

Merged
mmstick merged 1 commit into
pop-os:masterfrom
chris-010:fix/greeter-auth-error-not-fatal
Aug 25, 2026
Merged

mmstick merged 1 commit into
pop-os:masterfrom
chris-010:fix/greeter-auth-error-not-fatal

Conversation

@chris-010

Copy link
Copy Markdown
Contributor

One failed fingerprint press at the login screen ends the PAM conversation, and
the fingerprint reader stays unusable until the greeter restarts.

This is a different cause from the two open reports that share the symptom, and
neither is fixed by this change:

Cause

AuthMessageType::Error is PAM_ERROR_MSG — a message about the current
attempt, not the end of the conversation. pam_fprintd sends
Failed to match fingerprint that way and keeps going until max-tries is
reached. src/greeter/ipc.rs turned it into Message::Error, which cancels the
greetd session.

The session created right afterwards then loses the race for the fingerprint
reader: its PAM worker calls fprintd's Claim 14 ms after the cancel, while the
previous worker still holds it, so the claim is denied and no fingerprint prompt
ever appears again.

Delaying the new session does not help. The previous worker keeps the claim until
it next tries to talk to the greeter, which can be arbitrarily far away — in one
measurement 7.76 s, and it was the correct finger that finally woke it, which
the dead worker then consumed instead of logging in.

Change

The message is routed to its own Message::AuthError, which shows the text and
acknowledges it with PostAuthMessageResponse { response: None } — the same
handling the Info arm already uses, as the greetd protocol requires for a
non-interactive message. Message::Error and the Response::Error path are
unchanged, so a genuinely failed authentication still cancels the session.

Testing

ThinkPad T490, Synaptics 06cb:00bd, pam_fprintd max-tries=5, Pop!_OS 24.04.
Four greeter sessions: three after logging out, one after a cold boot.

  • failed press, then correct press (logout path) → the prompt comes back by
    itself after 111 ms and the correct finger logs in. Before the change: reader
    dead, password only.
  • five failed presses, once after logout and once after a cold boot →
    max-tries is exhausted on a single device claim, PAM falls through to
    pam_unix, and the password field appears on its own.
  • wrong password → still cancels, via Response::Error; the new session gets the
    claim and fingerprint login works again.
  • successful press on the first try → unchanged.

In all four sessions a single greetd worker served the whole login, and there was
no Device was already claimed in the journal.

Measured on one sensor model; I cannot speak for other readers.

  • I have disclosed use of any AI generated code in my commit messages.
  • I understand these changes in full and will be able to respond to review comments.
  • My change is accurately described in the commit message.
  • My contribution is tested and working as described.
  • I have read the Developer Certificate of Origin and certify my contribution under its conditions.

greetd delivers PAM_ERROR_MSG as an auth message of type Error, and ipc.rs
turned that into Message::Error, which cancels the greetd session. But such a
message describes the current attempt, not the end of the conversation:
pam_fprintd reports "Failed to match fingerprint" this way and then retries
until max-tries is reached.

The consequence at the login screen is that a single failed fingerprint press
ends the conversation. The greeter reconnects and immediately creates a new
session, whose PAM worker calls fprintd's Claim 14 ms later while the previous
worker still holds it, so the claim is denied and no fingerprint prompt ever
appears again. The previous worker only exits when it next tries to talk to the
greeter, which can be arbitrarily far in the future, so delaying the new session
does not help either.

Per the greetd protocol every auth message has to be acknowledged with
PostAuthMessageResponse, and for a non-interactive one the response is None,
which is what the Info arm already does. Route the Error message to its own
Message::AuthError that shows the text and acknowledges it. Message::Error and
the Response::Error path stay as they are, so a failed authentication still
cancels the session.

Drafted with AI assistance (Claude Code); the change and the measurements behind
it were reviewed and tested by me on real hardware.

Signed-off-by: chris-010 <10660568+chris-010@users.noreply.github.com>
@mmstick
mmstick requested a review from a team August 24, 2026 11:52
@jacobktm jacobktm self-assigned this Aug 24, 2026
@mmstick
mmstick merged commit 935891e into pop-os:master Aug 25, 2026
2 checks passed
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.

3 participants