Add opt-in Plasma fingerprint workaround

This commit is contained in:
ajp_anton
2026-09-04 23:16:15 +00:00
parent 810c8caf74
commit 19df3c3a75
16 changed files with 920 additions and 0 deletions
@@ -0,0 +1,68 @@
From: Alex Sanchez-Stern <alex@dmodel.ai>
Subject: [PATCH] Don't cancel in-progress authentication on suspend
Aborting an in-progress PAM conversation when the system suspends makes
pam_authenticate() report a failure. The greeter then displays a failed
login on resume, and authentication backends such as fingerprint can be
left unusable for the remainder of that lock-screen session.
Leave the conversation parked across suspend and resume instead. This is
the change proposed upstream in KScreenLocker merge request 340, adapted
to the Plasma 6.7.4 source shipped by Fedora 44.
---
greeter/greeterapp.cpp | 6 ------
greeter/greeterapp.h | 2 --
2 files changed, 8 deletions(-)
diff --git a/greeter/greeterapp.cpp b/greeter/greeterapp.cpp
index b1de459..08d8134 100644
--- a/greeter/greeterapp.cpp
+++ b/greeter/greeterapp.cpp
@@ -10,8 +10,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include "shell_integration.h"
#include "wallpaper_integration.h"
-#include "../logind.h"
-
#include <config-kscreenlocker.h>
#include <iostream>
#include <unistd.h>
@@ -133,7 +131,6 @@ UnlockApp::UnlockApp(int &argc, char **argv)
, m_graceTime(0)
, m_noLock(false)
, m_shellIntegration(new ShellIntegration(this))
- , m_logindIntegration(new LogindIntegration(this))
{
auto interactive = std::make_unique<PamAuthenticator>(QStringLiteral(KSCREENLOCKER_PAM_SERVICE), KUser().loginName());
std::vector<std::unique_ptr<PamAuthenticator>> noninteractive;
@@ -142,9 +139,6 @@ UnlockApp::UnlockApp(int &argc, char **argv)
noninteractive.push_back(
std::make_unique<PamAuthenticator>(QStringLiteral(KSCREENLOCKER_PAM_SMARTCARD_SERVICE), KUser().loginName(), PamAuthenticator::Smartcard));
m_authenticators = new PamAuthenticators(std::move(interactive), std::move(noninteractive), this);
- connect(m_logindIntegration, &LogindIntegration::prepareForSleep, m_authenticators, [this] {
- m_authenticators->cancel();
- });
initialize();
if (KWindowSystem::isPlatformX11()) {
diff --git a/greeter/greeterapp.h b/greeter/greeterapp.h
index 2362dd2..ff355de 100644
--- a/greeter/greeterapp.h
+++ b/greeter/greeterapp.h
@@ -25,7 +25,6 @@ class QuickViewSharedEngine;
}
class Authenticator;
-class LogindIntegration;
struct org_kde_ksld;
@@ -94,6 +93,5 @@ private:
KPackage::Package m_wallpaperPackage;
ShellIntegration *m_shellIntegration;
- LogindIntegration *m_logindIntegration;
};
} // namespace
--
2.51.0
@@ -0,0 +1,30 @@
From: Anton Partanen
Subject: [PATCH] Allow retrying non-interactive authentication
An active password conversation should not prevent a completed fingerprint
conversation from being started again. PamAuthenticator::tryUnlock() already
ignores authenticators that are still running, so let subsequent start
requests reach each authenticator.
This is a minimal backport of the state-guard removal in upstream commit
a5ed9ca0. It allows a fingerprint attempt interrupted by suspend to restart
without cancelling the password conversation.
---
greeter/pamauthenticators.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/greeter/pamauthenticators.cpp b/greeter/pamauthenticators.cpp
index 7c53b73..f60516d 100644
--- a/greeter/pamauthenticators.cpp
+++ b/greeter/pamauthenticators.cpp
@@ -141,7 +141,7 @@ PamAuthenticators::AuthenticatorsState PamAuthenticators::state() const
void PamAuthenticators::startAuthenticating()
{
- if (d->state == AuthenticatorsState::Authenticating || d->graceLocked) {
+ if (d->graceLocked) {
return;
}
--
2.51.0
@@ -0,0 +1,28 @@
From: Anton Partanen
Subject: [PATCH] Allow retry after transient authentication unavailability
PAM_AUTHINFO_UNAVAIL is not necessarily permanent. In particular,
pam_fprintd returns it when an active verification is interrupted by system
suspend. Treat that result as a failed attempt so a later start request can
retry it. Continue to cache PAM_MODULE_UNKNOWN as permanent unavailability.
---
greeter/pamauthenticator.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/greeter/pamauthenticator.cpp b/greeter/pamauthenticator.cpp
index e2011fd..bb2521f 100644
--- a/greeter/pamauthenticator.cpp
+++ b/greeter/pamauthenticator.cpp
@@ -176,7 +176,9 @@ void PamWorker::authenticate()
pam_setcred(m_handle, PAM_REFRESH_CRED);
/* ignore errors on refresh credentials. If this did not work we use the old ones. */
Q_EMIT succeeded();
- } else if (rc == PAM_AUTHINFO_UNAVAIL || rc == PAM_MODULE_UNKNOWN) {
+ } else if (rc == PAM_AUTHINFO_UNAVAIL) {
+ Q_EMIT failed();
+ } else if (rc == PAM_MODULE_UNKNOWN) {
m_unavailable = true;
Q_EMIT unavailabilityChanged(m_unavailable);
} else {
--
2.51.0
@@ -0,0 +1,68 @@
From: Anton Partanen
Subject: [PATCH] Retry transient unavailability for fingerprint only
Other non-interactive authenticators, notably smartcards, also use
PAM_AUTHINFO_UNAVAIL to report that no credential is present. Restrict the
retry behavior to fingerprint authenticators so absent smartcards remain
unavailable instead of repeatedly flashing in the UI.
---
greeter/pamauthenticator.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/greeter/pamauthenticator.cpp b/greeter/pamauthenticator.cpp
index bb2521f..e27e61c 100644
--- a/greeter/pamauthenticator.cpp
+++ b/greeter/pamauthenticator.cpp
@@ -27,7 +27,7 @@ class PamWorker : public QObject
{
Q_OBJECT
public:
- PamWorker();
+ explicit PamWorker(bool retryOnAuthInfoUnavailable);
~PamWorker() override;
Q_DISABLE_COPY_MOVE(PamWorker)
void start(const QString &service, const QString &user);
@@ -52,6 +52,7 @@ private:
bool m_unavailable = false;
bool m_inAuthenticate = false;
std::chrono::steady_clock::time_point m_nextAttemptAllowedTime;
+ const bool m_retryOnAuthInfoUnavailable;
int m_result = -1;
QString m_service;
};
@@ -163,10 +164,11 @@ int PamWorker::converse(int n, const struct pam_message **msg, struct pam_respons
return PAM_SUCCESS;
}
-PamWorker::PamWorker()
+PamWorker::PamWorker(bool retryOnAuthInfoUnavailable)
: QObject(nullptr)
, m_conv({&PamWorker::converse, this})
, m_nextAttemptAllowedTime(std::chrono::steady_clock::now())
+ , m_retryOnAuthInfoUnavailable(retryOnAuthInfoUnavailable)
{
}
@@ -176,9 +178,9 @@ void PamWorker::authenticate()
pam_setcred(m_handle, PAM_REFRESH_CRED);
/* ignore errors on refresh credentials. If this did not work we use the old ones. */
Q_EMIT succeeded();
- } else if (rc == PAM_AUTHINFO_UNAVAIL) {
+ } else if (rc == PAM_AUTHINFO_UNAVAIL && m_retryOnAuthInfoUnavailable) {
Q_EMIT failed();
- } else if (rc == PAM_MODULE_UNKNOWN) {
+ } else if (rc == PAM_AUTHINFO_UNAVAIL || rc == PAM_MODULE_UNKNOWN) {
m_unavailable = true;
Q_EMIT unavailabilityChanged(m_unavailable);
} else {
@@ -268,7 +271,7 @@ PamAuthenticator::PamAuthenticator(const QString &service, const QString &user, N
})
, m_service(service)
, m_authenticatorType(types)
- , d(new PamWorker)
+ , d(new PamWorker(types.testFlag(NoninteractiveAuthenticatorType::Fingerprint)))
{
d->moveToThread(&m_thread);
--
2.51.0