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
+60
View File
@@ -0,0 +1,60 @@
# Plasma fingerprint workaround
This is an experimental and unaudited replacement for Fedora's KScreenLocker
package. It changes security-sensitive session-locking and authentication code.
Review the patches and build the package yourself if you do not trust the
provided binary.
Installing `plasma-fingerprint-workaround` does not enable the workaround or
modify KScreenLocker. The controller only acts when explicitly asked:
```bash
sudo plasma-fingerprint-workaround enable
plasma-fingerprint-workaround status
sudo plasma-fingerprint-workaround disable
```
The default payload is kept outside the DNF repository. The controller checks
its pinned SHA-256 digest, RPM integrity, package name, architecture, and
workaround metadata before asking DNF to install it. Disabling the workaround
restores the current KScreenLocker package from Fedora's `fedora` or `updates`
repository.
The provided build currently supports Fedora 44 on x86_64 and is based on
`kscreenlocker-6.7.4-1.fc44`. A different base version is rejected by default.
To intentionally install the older provided build after a KScreenLocker update:
```bash
sudo plasma-fingerprint-workaround enable --force
```
## Locally built package
Build dependencies can be installed and the package built with:
```bash
sudo dnf5 builddep plasma-fingerprint-workaround/kscreenlocker/kscreenlocker.spec
./scripts/build-patched-kscreenlocker-rpm
```
Install the resulting package directly through the controller:
```bash
sudo plasma-fingerprint-workaround enable \
--rpm rpmbuild/RPMS/x86_64/kscreenlocker-6.7.4-1.fc44.ajp5.x86_64.rpm
```
For another upstream version, supply its version, Fedora base release, and
source archive checksum. The patches must still apply and compile cleanly.
```bash
KSCREENLOCKER_VERSION=6.7.5 \
KSCREENLOCKER_BASE_RELEASE=1 \
KSCREENLOCKER_SOURCE_SHA256=SHA256 \
./scripts/build-patched-kscreenlocker-rpm
```
A locally built package based on a different installed version requires
`--force`. This flag permits the version mismatch and allows DNF to downgrade;
it does not bypass the package identity, architecture, integrity, or workaround
metadata checks.
@@ -0,0 +1,108 @@
%{!?upstream_version:%global upstream_version 6.7.4}
%{!?base_release:%global base_release 1}
%{!?workaround_release:%global workaround_release 5}
Name: kscreenlocker
Version: %{upstream_version}
Release: %{base_release}%{?dist}.ajp%{workaround_release}
Summary: Library and components for secure lock screen architecture
License: BSD-3-Clause AND CC0-1.0 AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-only AND LGPL-2.1-only AND LGPL-3.0-only AND (GPL-2.0-only OR GPL-3.0-only) AND (LGPL-2.1-only OR LGPL-3.0-only)
URL: https://invent.kde.org/plasma/%{name}
Source0: https://download.kde.org/stable/plasma/%{version}/%{name}-%{version}.tar.xz
Source1: restart-fprintd-after-resume
Patch0: 0001-dont-cancel-authentication-on-suspend.patch
Patch1: 0002-allow-retrying-noninteractive-authentication.patch
Patch2: 0003-allow-retry-after-transient-auth-unavailability.patch
Patch3: 0004-retry-transient-unavailability-for-fingerprint-only.patch
# Marks packages that the controller may install and records the Fedora build
# on which the patches were based.
Provides: plasma-fingerprint-workaround-payload = 1
Provides: plasma-fingerprint-workaround-base = %{version}-%{base_release}%{?dist}
Provides: kscreenlocker = %{version}-%{base_release}%{?dist}
# Help upgrades; kscreenlocker was split from plasma-workspace in Plasma 5.5.
Conflicts: plasma-workspace < 5.5
BuildRequires: cmake(LayerShellQt)
BuildRequires: perl-generators
BuildRequires: qt6-qtbase-devel
BuildRequires: qt6-qtbase-private-devel
BuildRequires: cmake(Qt6Quick)
BuildRequires: kf6-rpm-macros
BuildRequires: extra-cmake-modules
BuildRequires: cmake(KF6Crash)
BuildRequires: cmake(KF6GlobalAccel)
BuildRequires: cmake(KF6I18n)
BuildRequires: cmake(KF6IdleTime)
BuildRequires: cmake(KF6KCMUtils)
BuildRequires: cmake(KF6KIO)
BuildRequires: cmake(KF6Notifications)
BuildRequires: cmake(KF6Screen)
BuildRequires: cmake(KF6Solid)
BuildRequires: cmake(KF6Svg)
BuildRequires: cmake(KF6XmlGui)
BuildRequires: cmake(KF6GuiAddons)
BuildRequires: cmake(KF6KirigamiPlatform)
BuildRequires: libX11-devel
BuildRequires: xcb-util-keysyms-devel
BuildRequires: wayland-devel
BuildRequires: pkgconfig(xi)
BuildRequires: pkgconfig(xcb-event)
BuildRequires: cmake(PlasmaQuick)
BuildRequires: libXcursor-devel
BuildRequires: pam-devel
%description
%{summary}.
This experimental Fedora 44 build contains local fingerprint authentication
workarounds. It has not received the security review of Fedora's package.
%package devel
Summary: Development files for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
The %{name}-devel package contains libraries and header files for developing
applications that use %{name}.
%prep
%autosetup -p1
%build
%cmake_kf6
%cmake_build
%install
%cmake_install
install -D -m 0755 %{SOURCE1} \
%{buildroot}%{_prefix}/lib/systemd/system-sleep/restart-fprintd-after-resume
%find_lang %{name} --with-qt --all-name
%files -f %{name}.lang
%license COPYING
%{_kf6_libdir}/libKScreenLocker.so.*
%{_kf6_datadir}/knotifications6/*.notifyrc
%{_libexecdir}/kscreenlocker_greet
%dir %{_kf6_datadir}/ksmserver/
%{_kf6_datadir}/ksmserver/screenlocker/
%{_kf6_datadir}/applications/kcm_screenlocker.desktop
%{_kf6_qtplugindir}/plasma/kcms/systemsettings/kcm_screenlocker.so
%{_kf6_datadir}/qlogging-categories6/kscreenlocker.categories
%{_prefix}/lib/systemd/system-sleep/restart-fprintd-after-resume
%files devel
%{_kf6_libdir}/libKScreenLocker.so
%{_kf6_libdir}/cmake/ScreenSaverDBusInterface/
%{_kf6_libdir}/cmake/KScreenLocker/
%{_includedir}/KScreenLocker/
%{_datadir}/dbus-1/interfaces/*.xml
%changelog
* Fri Sep 04 2026 Anton - 6.7.4-1.fc44.ajp5
- Package the fprintd resume hook and compatibility metadata
- Apply the tested fingerprint retry patch set
@@ -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
@@ -0,0 +1,6 @@
#!/bin/sh
[ "$1" = post ] || exit 0
systemctl --quiet is-active fprintd.service || exit 0
systemctl --no-block restart fprintd.service
@@ -0,0 +1,2 @@
payload_url=https://git.ajpanton.se/api/packages/ajp_anton/generic/plasma-fingerprint-workaround/6.7.4-1.fc44.ajp5/kscreenlocker-6.7.4-1.fc44.ajp5.x86_64.rpm
payload_sha256=d64515f3c7cb9c44b1c8fc194e90503be5944b1d24094aab2f68d989b3eca381
+306
View File
@@ -0,0 +1,306 @@
#!/usr/bin/bash
set -euo pipefail
PATH=/usr/sbin:/usr/bin
readonly data_dir=/usr/share/plasma-fingerprint-workaround
readonly payload_config="$data_dir/payload.conf"
readonly program=${0##*/}
temporary_dir=
usage() {
cat <<EOF
Usage:
$program status
$program enable [--rpm PATH] [--force] [--yes]
$program disable [--yes]
Without --rpm, enable downloads the tested prebuilt package. A local package
must have been built from this tool's KScreenLocker spec. --force permits a
base-version mismatch, including an intentional downgrade.
EOF
}
die() {
printf 'Error: %s\n' "$*" >&2
exit 1
}
require_root() {
(( EUID == 0 )) || die "run this command as root"
}
require_fedora() {
# shellcheck source=/dev/null
source /etc/os-release
[[ ${ID:-} == fedora ]] || die "this workaround only supports Fedora Linux"
}
cleanup() {
[[ -n $temporary_dir ]] || return
rm -f -- "$temporary_dir/kscreenlocker.rpm"
rmdir -- "$temporary_dir"
}
package_value() {
local mode=$1
local format=$2
local package=$3
rpm "$mode" --qf "$format" -- "$package"
}
package_base() {
local mode=$1
local package=$2
local provides
provides=$(rpm "$mode" --provides -- "$package")
sed -n 's/^plasma-fingerprint-workaround-base = //p' <<<"$provides"
}
is_workaround_package() {
local mode=$1
local package=$2
local provides
provides=$(rpm "$mode" --provides -- "$package")
grep -qx 'plasma-fingerprint-workaround-payload = 1' <<<"$provides"
}
is_legacy_workaround() {
[[ $(installed_value '%{RELEASE}') =~ \.ajp[[:digit:]]+$ ]]
}
is_any_workaround() {
is_workaround_package -q kscreenlocker || is_legacy_workaround
}
installed_value() {
package_value -q "$1" kscreenlocker
}
installed_base() {
local base
base=$(package_base -q kscreenlocker)
if [[ -n $base ]]; then
printf '%s\n' "$base"
elif is_legacy_workaround; then
printf '%s-%s\n' \
"$(installed_value '%{VERSION}')" \
"$(installed_value '%{RELEASE}' | sed 's/\.ajp[[:digit:]]*$//')"
else
installed_value '%{EVR}'
fi
}
show_status() {
if ! rpm -q kscreenlocker >/dev/null 2>&1; then
printf 'KScreenLocker is not installed.\n'
return 1
fi
if is_workaround_package -q kscreenlocker; then
printf 'Fingerprint workaround: enabled\n'
printf 'Installed package: kscreenlocker-%s.%s\n' \
"$(installed_value '%{EVR}')" "$(installed_value '%{ARCH}')"
printf 'Based on Fedora package: kscreenlocker-%s\n' "$(installed_base)"
elif is_legacy_workaround; then
printf 'Fingerprint workaround: enabled (legacy unmanaged build)\n'
printf 'Installed package: kscreenlocker-%s.%s\n' \
"$(installed_value '%{EVR}')" "$(installed_value '%{ARCH}')"
printf 'Based on Fedora package: kscreenlocker-%s\n' "$(installed_base)"
else
printf 'Fingerprint workaround: disabled\n'
printf 'Installed package: kscreenlocker-%s.%s\n' \
"$(installed_value '%{EVR}')" "$(installed_value '%{ARCH}')"
fi
}
confirm() {
local answer
if (( assume_yes )); then
return
fi
printf 'Continue? [y/N] '
read -r answer || exit 0
[[ $answer == y || $answer == Y ]] || exit 0
}
load_payload_config() {
[[ -r $payload_config ]] || die "payload configuration is missing"
unset payload_url payload_sha256
# This root-owned file is installed by the controller RPM.
# shellcheck source=/dev/null
source "$payload_config"
[[ ${payload_url:-} == https://* ]] || die "invalid payload URL"
[[ ${payload_sha256:-} =~ ^[[:xdigit:]]{64}$ ]] ||
die "invalid payload checksum"
}
validate_candidate() {
local candidate=$1
local name arch candidate_evr candidate_base current_base current_evr
rpm -K --nosignature "$candidate" >/dev/null || die "the RPM is corrupt"
name=$(package_value -qp '%{NAME}' "$candidate")
[[ $name == kscreenlocker ]] ||
die "expected a kscreenlocker RPM, got $name"
is_workaround_package -qp "$candidate" ||
die "the RPM was not built from this workaround's KScreenLocker spec"
arch=$(package_value -qp '%{ARCH}' "$candidate")
[[ $arch == "$(installed_value '%{ARCH}')" ]] ||
die "RPM architecture $arch does not match installed architecture $(installed_value '%{ARCH}')"
candidate_base=$(package_base -qp "$candidate")
[[ -n $candidate_base ]] || die "the RPM has no base-version marker"
candidate_evr=$(package_value -qp '%{EVR}' "$candidate")
current_base=$(installed_base)
current_evr=$(installed_value '%{EVR}')
printf 'Installed: kscreenlocker-%s\n' "$current_evr"
printf 'Candidate: kscreenlocker-%s (based on %s)\n' \
"$candidate_evr" "$candidate_base"
if [[ $candidate_base != "$current_base" ]]; then
if (( ! force )); then
die "candidate base $candidate_base does not match installed base $current_base; use --force to allow the version change"
fi
printf 'Warning: forcing a KScreenLocker base-version change.\n' >&2
fi
}
enable_workaround() {
local rpm_path='' candidate
local -a dnf_args
force=0
assume_yes=0
while (( $# )); do
case $1 in
--rpm)
(( $# >= 2 )) || die "--rpm requires a path"
rpm_path=$2
shift 2
;;
--force)
force=1
shift
;;
--yes)
assume_yes=1
shift
;;
*)
die "unknown enable option: $1"
;;
esac
done
require_root
require_fedora
rpm -q kscreenlocker >/dev/null 2>&1 || die "KScreenLocker is not installed"
umask 077
temporary_dir=$(mktemp -d /var/tmp/plasma-fingerprint-workaround.XXXXXX)
trap cleanup EXIT
candidate="$temporary_dir/kscreenlocker.rpm"
if [[ -n $rpm_path ]]; then
[[ -f $rpm_path ]] || die "RPM not found: $rpm_path"
install -m 0600 -- "$rpm_path" "$candidate"
else
load_payload_config
printf 'Downloading the tested KScreenLocker build...\n'
curl --fail --location --show-error --silent \
--proto '=https' --proto-redir '=https' \
--output "$candidate" "$payload_url"
printf '%s %s\n' "$payload_sha256" "$candidate" |
sha256sum --check --status - || die "downloaded RPM checksum does not match"
fi
validate_candidate "$candidate"
printf '\nThis replaces Fedora\x27s security-sensitive KScreenLocker package.\n'
confirm
dnf_args=(install --assumeyes)
(( force )) && dnf_args+=(--allow-downgrade)
dnf5 "${dnf_args[@]}" "$candidate"
is_workaround_package -q kscreenlocker ||
die "DNF completed without enabling the workaround"
printf 'Fingerprint workaround enabled. Reboot before testing it.\n'
}
disable_workaround() {
assume_yes=0
while (( $# )); do
case $1 in
--yes)
assume_yes=1
shift
;;
*)
die "unknown disable option: $1"
;;
esac
done
require_root
require_fedora
if ! is_any_workaround; then
printf 'Fingerprint workaround is already disabled.\n'
return
fi
printf 'This will replace the workaround with Fedora\x27s current KScreenLocker package.\n'
confirm
dnf5 \
--repo=fedora,updates \
--refresh \
distro-sync \
--assumeyes \
kscreenlocker
if is_any_workaround; then
die "no suitable Fedora KScreenLocker package was installed"
fi
printf 'Fingerprint workaround disabled. Reboot before testing the lock screen.\n'
}
command=${1:-}
[[ -n $command ]] || {
usage
exit 2
}
shift
case $command in
status)
(( $# == 0 )) || die "status takes no options"
show_status
;;
enable)
enable_workaround "$@"
;;
disable)
disable_workaround "$@"
;;
-h|--help|help)
usage
;;
*)
usage >&2
exit 2
;;
esac
@@ -0,0 +1,54 @@
Name: plasma-fingerprint-workaround
Version: 0.1.0
Release: 1%{?dist}
Summary: Opt-in installer for a patched Fedora KScreenLocker
License: MIT
URL: https://git.ajpanton.se/ajp_anton/fedora-tools
Source0: plasma-fingerprint-workaround
Source1: payload.conf
Source2: LICENSE
Source3: README.md
Source4: test-controller
BuildArch: noarch
BuildRequires: bash
BuildRequires: grep
Requires: bash
Requires: coreutils
Requires: curl
Requires: dnf5
Requires: grep
Requires: rpm
Requires: sed
%description
Provides an explicit, reversible installer for an experimental KScreenLocker
fingerprint workaround. Installing this package alone makes no system changes.
%prep
%build
%check
bash %{SOURCE4} %{SOURCE0} %{SOURCE1}
%install
install -D -m 0755 %{SOURCE0} \
%{buildroot}%{_bindir}/plasma-fingerprint-workaround
install -D -m 0644 %{SOURCE1} \
%{buildroot}%{_datadir}/plasma-fingerprint-workaround/payload.conf
install -D -m 0644 %{SOURCE2} \
%{buildroot}%{_licensedir}/%{name}/LICENSE
install -D -m 0644 %{SOURCE3} \
%{buildroot}%{_docdir}/%{name}/README.md
%files
%license %{_licensedir}/%{name}/LICENSE
%doc %{_docdir}/%{name}/README.md
%{_bindir}/plasma-fingerprint-workaround
%{_datadir}/plasma-fingerprint-workaround/payload.conf
%changelog
* Fri Sep 04 2026 Anton - 0.1.0-1
- Initial package
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/bash
set -euo pipefail
controller=$1
payload_config=$2
bash -n "$controller"
"$controller" --help | grep -q '^ .* enable \[--rpm PATH\] \[--force\] \[--yes\]$'
if "$controller" unknown-command >/dev/null 2>&1; then
printf 'Unknown command unexpectedly succeeded.\n' >&2
exit 1
fi
payload_url=
payload_sha256=
# shellcheck source=/dev/null
source "$payload_config"
[[ $payload_url == https://*/*.rpm ]]
[[ $payload_sha256 =~ ^[[:xdigit:]]{64}$ ]]
printf 'Controller tests passed.\n'
@@ -0,0 +1,16 @@
#!/usr/bin/bash
set -euo pipefail
rpm_path=$1
expected_base=$2
provides=$(rpm -qp --provides "$rpm_path")
files=$(rpm -qpl "$rpm_path")
rpm -K --nosignature "$rpm_path" >/dev/null
[[ $(rpm -qp --qf '%{NAME}' "$rpm_path") == kscreenlocker ]]
grep -qx 'plasma-fingerprint-workaround-payload = 1' <<<"$provides"
grep -qx "plasma-fingerprint-workaround-base = $expected_base" <<<"$provides"
grep -qx '/usr/lib/systemd/system-sleep/restart-fprintd-after-resume' <<<"$files"
printf 'Patched KScreenLocker package tests passed.\n'