From 2ba325791bf1cf8b3fd4deddff39d978ba936baa Mon Sep 17 00:00:00 2001 From: David Date: Wed, 2 Sep 2026 15:12:58 +0200 Subject: [PATCH] pam: delay auth init until grace period expires During a grace period, hyprlock allows unlocking via mouse movement or a keypress without completing PAM authentication. However, PAM (and therefore any module in the stack, e.g. pam_u2f) was being initialised immediately on startup regardless of grace, causing FIDO2 security keys to light up and wait for a touch that is never needed when the user unlocks during grace. Fix this by waiting at the start of CPam::init()'s thread until the grace period wall-clock time has elapsed before calling into pam_authenticate(). The wait uses the existing inputSubmittedCondition condvar so that terminate() wakes the thread immediately if the session is unlocked (via grace, SIGUSR1, etc.) before the grace period ends, avoiding a hang on exit. --- src/auth/Pam.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/auth/Pam.cpp b/src/auth/Pam.cpp index 9cd16c92..9d262a64 100644 --- a/src/auth/Pam.cpp +++ b/src/auth/Pam.cpp @@ -96,6 +96,20 @@ CPam::~CPam() { void CPam::init() { m_thread = std::thread([this]() { + // If a grace period is active, delay PAM initialisation until it expires. + // Without this, modules such as pam_u2f immediately issue a FIDO2 challenge + // and light up the security key even though the user can still unlock via + // mouse/keyboard movement during grace — leaving the key stuck waiting for a + // touch that is never needed. + const auto GRACE_END = g_pHyprlock->m_tGraceEnds; + if (GRACE_END > std::chrono::system_clock::now()) { + Log::logger->log(Log::INFO, "PAM: grace period active, delaying auth start until grace expires"); + std::unique_lock lk(m_sConversationState.inputMutex); + m_sConversationState.inputSubmittedCondition.wait_until(lk, GRACE_END, [this] { + return m_sConversationState.terminateRequested || g_pHyprlock->isFadingOutOrTerminating(); + }); + } + while (true) { resetConversation();