diff --git a/bin/omarchy-setup-security-fingerprint b/bin/omarchy-setup-security-fingerprint index 383aa37629a..ec9dc3f0be0 100755 --- a/bin/omarchy-setup-security-fingerprint +++ b/bin/omarchy-setup-security-fingerprint @@ -65,6 +65,14 @@ account include system-local-login EOF } +install_sleep_hook() { + # Stopping fprintd before suspend keeps the lock screen from opening the + # reader inside a sleep transition that no longer accepts new inhibitors. + if [[ -e $OMARCHY_PATH/default/systemd/system-sleep/50-fprintd-release ]]; then + sudo install -Dm755 "$OMARCHY_PATH/default/systemd/system-sleep/50-fprintd-release" /usr/lib/systemd/system-sleep/50-fprintd-release 2>/dev/null || true + fi +} + echo -e "\e[32mSetting up fingerprint scanner for authentication.\n\e[0m" @@ -103,6 +111,7 @@ if sudo fprintd-enroll "$USER"; then # pam_fprintd with nothing to match. setup_pam_config setup_lock_fingerprint_pam + install_sleep_hook echo -e "\e[32m\nPerfect! Fingerprint authentication is now configured.\e[0m" echo "You can use your fingerprint for sudo, polkit, and lock screen (Super + Ctrl + L)." else diff --git a/default/systemd/system-sleep/50-fprintd-release b/default/systemd/system-sleep/50-fprintd-release new file mode 100755 index 00000000000..7a380a83df7 --- /dev/null +++ b/default/systemd/system-sleep/50-fprintd-release @@ -0,0 +1,11 @@ +#!/bin/bash + +# Stop fprintd before suspend/hibernate so the lock screen cannot open the +# fingerprint reader inside a sleep transition that has already stopped +# honoring new inhibitors. fprintd is Type=dbus, so it re-activates on the +# next touch after resume. +if [[ $1 == "pre" ]]; then + if systemctl is-active --quiet fprintd.service 2>/dev/null; then + systemctl stop fprintd.service 2>/dev/null || true + fi +fi diff --git a/migrations/1788797303.sh b/migrations/1788797303.sh new file mode 100644 index 00000000000..9d6c813db2c --- /dev/null +++ b/migrations/1788797303.sh @@ -0,0 +1,26 @@ +echo "Stop fprintd before suspend so the reader cannot be opened inside a sleep transition" + +# The lock screen starts after PrepareForSleep(true), and pam_fprintd +# D-Bus-activates fprintd once the lock is already in progress. fprintd then +# asks logind for a delay inhibitor, but logind has already stopped honouring +# new inhibitors, so the reader can be cut mid-transaction. Stopping fprintd in +# the pre-sleep hook keeps it from being opened while the machine is going down. +# fprintd is Type=dbus, so it re-activates on the next unlock attempt. +hook_source="$OMARCHY_PATH/default/systemd/system-sleep/50-fprintd-release" +hook_dest=/usr/lib/systemd/system-sleep/50-fprintd-release + +as_root() { + if (( EUID == 0 )); then + "$@" + else + sudo "$@" + fi +} + +[[ -e $hook_source ]] || exit 0 + +if [[ -e $hook_dest ]] && cmp -s "$hook_source" "$hook_dest"; then + exit 0 +fi + +as_root install -Dm755 "$hook_source" "$hook_dest" diff --git a/test/shell.d/fprintd-sleep-release-test.sh b/test/shell.d/fprintd-sleep-release-test.sh new file mode 100644 index 00000000000..6dd84ddaade --- /dev/null +++ b/test/shell.d/fprintd-sleep-release-test.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +set -euo pipefail + +source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh" + +hook="$ROOT/default/systemd/system-sleep/50-fprintd-release" +[[ -x $hook ]] || fail "fprintd sleep release hook is executable" + +grep -Fx '#!/bin/bash' "$hook" >/dev/null || fail "sleep hook uses bash" +grep -F 'if [[ $1 == "pre" ]]; then' "$hook" >/dev/null || fail "sleep hook only acts on pre-sleep" +grep -F 'systemctl is-active --quiet fprintd.service' "$hook" >/dev/null || fail "sleep hook checks fprintd is active" +grep -F 'systemctl stop fprintd.service' "$hook" >/dev/null || fail "sleep hook stops fprintd" +grep -F '|| true' "$hook" >/dev/null || fail "sleep hook does not abort suspend on a stop failure" + +migration="$ROOT/migrations/1788797303.sh" +[[ -f $migration ]] || fail "fprintd sleep hook migration exists" +grep -F '50-fprintd-release' "$migration" >/dev/null || fail "migration installs the fprintd sleep hook" +grep -F 'install -Dm755' "$migration" >/dev/null || fail "migration preserves the executable hook" + +setup="$ROOT/bin/omarchy-setup-security-fingerprint" +grep -F 'install_sleep_hook' "$setup" >/dev/null || fail "setup installs the fprintd sleep hook" + +pass "fprintd sleep release hook is wired into setup and migrations"