fix: reset faillock after a face unlock of the lock screen

This commit is contained in:
Felitendo committed 2026-09-22 20:52:15 +02:00
1 parent 2ff27160e3
commit 7c87adb733
5 files changed
+39

No files matched your search

+13
View File
@@ -69,6 +69,10 @@ QJsonObject result(bool ok, const QString &reason = {})
return o;
}
// A face unlock and the lock screen going away this soon after belong
// together.
constexpr qint64 UnlockPairSeconds = 30;
bool isFailureThatCounts(const QString &reason)
{
// A face that did not match, a fake, or a match that never showed a sign
@@ -403,6 +407,15 @@ void Server::handleWatch(Client *client)
void Server::handleUnlocked(Client *client)
{
UserState state = UserState::load(m_options.stateDir, client->uid());
// Our unlock goes through logind. The lock screen's password prompt is
// cut off mid-question by it and counts that as a wrong password, so a
// few face unlocks would lock the account (pam_faillock). Taken back here.
const qint64 now = QDateTime::currentSecsSinceEpoch();
if (geteuid() == 0 && state.lastPurpose == u"unlock" && now - state.lastUnlock <= UnlockPairSeconds) {
System::resetFailedLogins(client->uid());
}
if (state.failures || state.lockedUntil) {
state.failures = 0;
state.lockedUntil = 0;
+15
View File
@@ -6,6 +6,8 @@
#include <QDBusInterface>
#include <QDir>
#include <QFile>
#include <QProcess>
#include <QStandardPaths>
#include <pwd.h>
#include <unistd.h>
@@ -79,4 +81,17 @@ quint64 processStartTime(pid_t pid)
const QList<QByteArray> fields = line.mid(close + 2).split(' ');
return fields.size() > 19 ? fields.at(19).toULongLong() : 0;
}
bool resetFailedLogins(uid_t uid)
{
// Not from PATH: this runs as root.
const QString faillock = QStandardPaths::findExecutable(QStringLiteral("faillock"),
{QStringLiteral("/usr/sbin"), QStringLiteral("/usr/bin"), QStringLiteral("/sbin")});
if (faillock.isEmpty()) {
return false;
}
QProcess p;
p.start(faillock, {QStringLiteral("--user"), nameOf(uid), QStringLiteral("--reset")});
return p.waitForFinished(3000) && p.exitStatus() == QProcess::NormalExit && p.exitCode() == 0;
}
} // namespace System
+4
View File
@@ -20,4 +20,8 @@ bool lidClosed();
// When a process started, in clock ticks since boot, as polkit wants it to
// tell a process from a later one that got the same pid.
quint64 processStartTime(pid_t pid);
// Forget the failed logins pam_faillock counted for somebody, as a correct
// password does. False without faillock.
bool resetFailedLogins(uid_t uid);
} // namespace System