Bug 438099 - Endless loop when using PAM module pam_systemd_home.so after wrong password
Summary: Endless loop when using PAM module pam_systemd_home.so after wrong password
Status: RESOLVED FIXED
Alias: None
Product: kscreenlocker
Classification: Plasma
Component: general (show other bugs)
Version: unspecified
Platform: Arch Linux Linux
: VHI critical
Target Milestone: ---
Assignee: Plasma Bugs List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-06-05 00:41 UTC by roms
Modified: 2021-07-23 14:44 UTC (History)
4 users (show)

See Also:
Latest Commit:
Version Fixed In: 5.22.4


Attachments
Working but but probably no where near correct fix - beware! (554 bytes, text/plain)
2021-06-05 00:41 UTC, roms
Details
Looped messages from syslog (12.21 KB, text/plain)
2021-06-05 00:46 UTC, roms
Details

Note You need to log in before you can comment on or make changes to this bug.
Description roms 2021-06-05 00:41:26 UTC
Created attachment 139007 [details]
Working but but probably no where near correct fix - beware!

SUMMARY
Trying to unlock screen as a user created with systemd-homed (or more specific: homectl) results in an loop when using wrong password. kscreenlocker/kcheckpass will try to authenticate forever.

I can see this behavior in current Arch Linux and Fedora 34.

STEPS TO REPRODUCE
1. Get current Arch Linux installation or VM with KDE. (Systemd-homed is ready-to-use in Arch, but not in Fedora 34.)
2. Create user as root: homectl create testuser --storage=directory --uid=12345
   Setting the UID here as users with UIDs over 60000 (which are otherwise chosen by default) are not shown in SDDM.
3. Log in SDDM as this new user (X11/Wayland-Session doesn't matter)
4. Switch to TTY and as root run: journalctl -f
3. Switch back, lock screen and try to unlock but with a wrong password.
4. Switch to TTY to watch error messages. Kill kcheckpass to end loop and use "loginctl unlock-session $(session)" to unlock.

OBSERVED RESULT
The endless loop will hit the systemd-homed authentication rate limit on first try with a wrong password (see "homectl inspect testuser"). kscreenlocker won't allow another authentication attempt.

EXPECTED RESULT
Another authentication attempt with kscreenlocker acquiring new user password.


SOFTWARE/OS VERSIONS

Linux/KDE Plasma: Updated Arch Linux or Fedora 34
KDE Plasma Version: 5.21.5
KDE Frameworks Version: 5.82.0
Qt Version: 5.15.2

ADDITIONAL INFORMATION
It seems that the PAM module pam_systemd_home.so tries to reacquire a new password after initial failed attempt and continues the PAM-conversation. But kcheckpass continues (without actually reacquiring a new PW from user) where it should probably bail.

The whole thing can be debugged with "kcheckpass_test --direct".
I found that the attached patch fixes the problem for me. But I can't in any way assess if this is a proper solution.
Comment 1 roms 2021-06-05 00:46:24 UTC
Created attachment 139008 [details]
Looped messages from syslog

Attached syslog error messages
Comment 2 Nate Graham 2021-06-09 16:28:47 UTC
It never hurts to submit it anyway, as developers are more likely to see it there. Go ahead!

https://invent.kde.org/plasma/kscreenlocker/-/merge_requests/
Comment 3 David Edmundson 2021-06-12 16:53:31 UTC
Patch itself looks sound, but it is super important to understand the full context to make sure we're fixing things at the root. 

We only get into the abort flag if we go through:

checkpass_pam.c:84
```
            if (!repl[count].resp) {
                pd->abort = 1;
                goto conv_err;
            }
```

Which means we were in a handled: msg[count]->msg_style, but not one that provided a reply. 
From the code surrounding it, that implies we were in the first path of this ternary operator and putting a null pointer here.

            case PAM_PROMPT_ECHO_OFF:
                repl[count].resp = pd->conv(ConvGetHidden, pd->classic ? 0 : msg[count]->msg);


FWITC pd->classic is uninitialised?! Does setting that to false explicitly also fix it?
Comment 4 roms 2021-07-18 23:33:11 UTC
Please excuse my late response ...

Next time, I shall directly submit a patch to invent.kde.org

Someone else already did so and fortunately seems to be more knowledgeable about PAM than I am:
https://invent.kde.org/plasma/kscreenlocker/-/merge_requests/39

I guess this issue can be closed when this gets merged.

@David Edmundson
FYI, doing this (I hope I understand correctly what you had in mind) doesn't also fix the loop (Fedora 34 with kscreenlocker-5.22.3):

            case PAM_PROMPT_ECHO_OFF:
                pd->classic = 0; // hack
                repl[count].resp = pd->conv(ConvGetHidden, pd->classic ? 0 : msg[count]->msg);
                break;

Thanks a lot to everyone :-)
Comment 5 David Edmundson 2021-07-19 22:22:40 UTC
Git commit f78ccfc9c0177c4a46ef6e6f2dd29cc2d8b95205 by David Edmundson, on behalf of Gibeom Gwon.
Committed on 19/07/2021 at 22:22.
Pushed by davidedmundson into branch 'master'.

Handle ConvPutAuthAbort as an authentication failure

If an incorrect password is provided for a systemd-homed based user,
kcheckpass sends ConvPutAuthAbort. Currently, ConvPutAuthAbort is
handled like ConvPutReadyForAuthentication. This causes the problem
of repeating authentication indefinitely. So, treating ConvPutAuthAbort
as an authentication failure solves the problem.

M  +1    -1    greeter/authenticator.cpp

https://invent.kde.org/plasma/kscreenlocker/commit/f78ccfc9c0177c4a46ef6e6f2dd29cc2d8b95205
Comment 6 David Edmundson 2021-07-19 22:23:22 UTC
Git commit fca315cf72826f93eda7a026016b33818b9d1f39 by David Edmundson, on behalf of Gibeom Gwon.
Committed on 19/07/2021 at 22:23.
Pushed by davidedmundson into branch 'Plasma/5.22'.

Handle ConvPutAuthAbort as an authentication failure

If an incorrect password is provided for a systemd-homed based user,
kcheckpass sends ConvPutAuthAbort. Currently, ConvPutAuthAbort is
handled like ConvPutReadyForAuthentication. This causes the problem
of repeating authentication indefinitely. So, treating ConvPutAuthAbort
as an authentication failure solves the problem.


(cherry picked from commit f78ccfc9c0177c4a46ef6e6f2dd29cc2d8b95205)

M  +1    -1    greeter/authenticator.cpp

https://invent.kde.org/plasma/kscreenlocker/commit/fca315cf72826f93eda7a026016b33818b9d1f39