PLM 免按键人脸登录

Plasma Login Manager 没有让 greeter 自动开始认证的配置。用 Autologin 加一道人脸闸门,开机后通过人脸即可零按键进入桌面,失败则回到正常登录界面。

背景 《人脸登录后的 KWallet 自动解锁》把本文当作背景引用,见文末。

Plasma Login Manager(PLM)的登录界面里,人脸认证要先按 Enter,或者点击登录按钮。Windows Hello 式的“看向摄像头就开始识别”没有对应的配置开关。所以我多少有点标题党了,为了实现这个效果,我没有在 PLM 上死磕,而是转而使用了其他方法。

先决条件

```text
CachyOS(Arch 系)|KDE Plasma 6.7.5|Plasma Login Manager 6.7.4
Wayland|biopass-bin 1.4.1|pam 1.7.2
```

本机 biopass 只开人脸(`methods.face.enable: true`,指纹关闭),单次判定约 2 秒。下面所有配置里的 `<用户名>` 是占位符,安装前换成你自己的登录名。

整套改动落在三个地方,没有新增守护进程,也不需要编译任何东西:

# 位置 作用
1 `/usr/local/libexec/biopass-pam-auth` 人脸闸门包装脚本
2 `/etc/pam.d/plasmalogin-autologin` 覆盖上游的放行式 PAM 栈
3 `/etc/plasmalogin.conf` `[Autologin]` 段指定登录用户

现象

在 greeter 前坐定、把脸对着摄像头,界面不会有任何反应,必须先按一次 Enter 或点一次登录按钮,识别才开始。识别本身没问题:一次通过、约 2 秒进桌面。缺的是谁来发起这次认证。

greeter 为什么不自动认证

上游 `src/frontend/greeter/qml/Login.qml`(6.7)里,能发起认证的入口只有三个:

```qml
passwordBox.onAccepted:            startLogin()   // 密码框回车
loginButton.onClicked:             startLogin()   // 点登录按钮
loginButton.Keys.onReturnPressed:  clicked()      // 按钮聚焦时回车
```

而负责初始化界面的 `Component.onCompleted` 只做三件事:填充上次登录的用户名、把焦点放到密码框、同步界面状态。它没有调用 `startLogin()`。

想加一个触发点也走不通:

所以这是当前设计,不是配置写错了。改 greeter 配置或主题都不会凭空多出一个认证触发点。

为什么不能直接把 biopass 标成 required

在动手前得先绕开一个坑,它决定后面为什么用一个包装脚本而不是直接引用 biopass 的 PAM 模块。

biopass 的 PAM 模块(上游 `auth/pam/pam.cc`)把助手的退出码映射成三种 PAM 返回值:

helper 退出码 PAM 返回值 什么时候出现
0 `PAM_SUCCESS` 人脸匹配
2 `PAM_IGNORE` 跑不起来:摄像头打不开、模型缺失、该用户无人脸
其他非 0 `PAM_AUTH_ERR` 人脸不匹配

问题出在 `PAM_IGNORE` 上。Linux-PAM 的 `pam_dispatch.c` 里,`required` 展开成 `[success=ok new_authtok_reqd=ok ignore=ignore default=bad]`,也就是说模块返回 `PAM_IGNORE` 时对应的动作是 ignore,直接跳过,完全不影响整个栈的成败。于是下面这种写法看起来是把人脸设成了必须项,实际不是:

```ini
auth required libbiopass_pam.so    # 摄像头坏了 → PAM_IGNORE → 不算失败
auth required pam_permit.so        # → 放行 → 无认证进入桌面
```

对 `sudo` 那种“先试人脸、失败回退密码”的场景,这个特性无害;对 autologin 这种无人值守的闸门就是漏洞,摄像头一坏,闸门自己开了。

规避办法是用 `pam_exec` 调 biopass 的助手。`pam_exec`(`man pam_exec`)只看进程退出码,0 是通过、非 0 是失败,它没有 `PAM_IGNORE` 这种中间态:

```plaintext
helper 退出码 0  → pam_exec 返回 PAM_SUCCESS
helper 退出码非 0 → pam_exec 返回 PAM_SERVICE_ERR / PAM_AUTH_ERR
```

于是映射关系变成干净的二分:能跑通并识别成功才算通过,其余一切情况——没识别到、摄像头不可用、助手缺失、脚本自身出错——都是失败。autologin 失败会回落到登录界面,用户还能输密码,不会把自己锁在外面。

代价是多一个包装脚本。后面会看到,它同时还要负责给钱包传递密钥。

选择 Autologin

PLM 的 Autologin 恰好把认证放在了 greeter 之前。上游 `src/daemon/Display.cpp` 的 `Display::start()`:

```cpp
if (m_autologinSession.isValid()) {
    m_auth->setAutologin(true);
    if (startAuth(m_autologinUser, QString(), m_autologinSession))
        return true;                          // ← 前两个参数:用户、空密码
    else
        return handleAutologinFailure();      // ← "Autologin failed!" → 拉起 greeter
}
```

三个性质正好都用得上:

  1. 不需要按键——认证发生在 greeter 和合成器启动之前,屏幕上还没有任何可点的东西。
  2. 失败不锁死——`handleAutologinFailure()` 会正常拉起登录界面,密码框和人脸重试都在。
  3. 失败是可见的——日志里留下 `Autologin failed!` 一行,排查时不用猜。

`PamBackend::start()` 里写明 autologin 用的 PAM 服务名就是 `plasmalogin-autologin`,所以闸门脚本要挂在 `/etc/pam.d/plasmalogin-autologin` 上,而不是 greeter 用的 `/etc/pam.d/plasmalogin`。

运行时序:

```text
开机 → plasmalogin 启动
  └─ Autologin:跑 plasmalogin-autologin 的 PAM 栈
       ├─ 通过 → 创建 Plasma 会话,直接进桌面
       └─ 失败 → Autologin failed! → 拉起 greeter
```

这里会出现两个代价,或许你需要自行抉择:

人脸闸门脚本

脚本要做的事:从 PAM 拿当前用户名和服务名,调 biopass 助手,只把退出码原样交给 `pam_exec`。任何一步不成立都退出非 0。

`pam_exec` 会往子进程环境里放 `PAM_USER`、`PAM_SERVICE`、`PAM_TYPE`。脚本用前两个,并且在任何一个为空时直接拒绝放行。另外 `pam_exec` 默认以调用者的身份执行命令,而 autologin 时代的调用者是 root,所以这个脚本必须是 `root:root 0755`,不能让它可被普通用户改写。

```bash
#!/bin/bash
#
# biopass-pam-auth — 由 pam_exec.so 调用的"人脸闸门"
#
# 安装位置:/usr/local/libexec/biopass-pam-auth   (root:root 0755)
# 调用方式:PAM 文件中写
#     auth required pam_exec.so quiet /usr/local/libexec/biopass-pam-auth
#
# 设计原因(勿改成 auth required libbiopass_pam.so):
#   biopass 的 PAM 模块在"无法运行"(摄像头打不开/模型缺失/该用户无人脸)时
#   helper 退出码为 2,模块会把它映射成 PAM_IGNORE;而 PAM 的 required 会忽略
#   PAM_IGNORE,配合 autologin 栈里原有的 pam_permit.so 就会变成"无认证放行"。
#   pam_exec 只看退出码:0 = 通过,非 0 = 失败(helper 缺失/脚本异常同样失败,fail-closed)。
#
# 环境变量由 pam_exec 注入:PAM_USER / PAM_SERVICE / PAM_TYPE 等。
#
# SPDX-License-Identifier: MIT

set -u

HELPER="/usr/bin/biopass-helper"
LOG_TAG="biopass-pam-auth"

user="${PAM_USER:-}"
service="${PAM_SERVICE:-plasmalogin-autologin}"

if [[ -z "${user}" ]]; then
    logger -t "${LOG_TAG}" -p auth.warning "PAM_USER 为空,拒绝放行(fail-closed)"
    exit 1
fi

if [[ ! -x "${HELPER}" ]]; then
    logger -t "${LOG_TAG}" -p auth.err "找不到可执行的 ${HELPER},拒绝放行(fail-closed)"
    exit 1
fi

# 让 biopass 助手能定位该用户的数据目录(人脸库/配置);失败也不影响,仅尽力而为
home="$(getent passwd "${user}" | cut -d: -f6)"
if [[ -n "${home}" && -d "${home}" ]]; then
    export HOME="${home}"
fi
export USER="${user}"
export LOGNAME="${user}"

start="${SECONDS}"
"${HELPER}" auth --username "${user}" --service "${service}"
rc=$?
elapsed=$(( SECONDS - start ))

if [[ "${rc}" -eq 0 ]]; then
    logger -t "${LOG_TAG}" -p auth.info "人脸认证通过 user=${user} service=${service} 用时 ${elapsed}s"
    exit 0
fi

# rc=2 表示"没有可用认证方式"(例如摄像头不可用)——必须按失败处理,绝不能放行
logger -t "${LOG_TAG}" -p auth.warning "人脸认证未通过 user=${user} service=${service} rc=${rc} 用时 ${elapsed}s"
exit "${rc}"
```

几个处理值得单独说明:

PAM 顺序

目标文件是 `/etc/pam.d/plasmalogin-autologin`。它在 `/etc/pam.d` 下,优先级高于包内默认的 `/usr/lib/pam.d/plasmalogin-autologin`,所以不会和包管理器抢文件,但升级后要留意上游默认值有没有变。

上游那份是这样的(包内默认,关键在 `pam_permit.so` 那一行):

```ini
auth        required    pam_env.so
auth        required    pam_faillock.so preauth
auth        required    pam_shells.so
auth        required    pam_nologin.so
auth        required    pam_permit.so
-auth       optional    pam_gnome_keyring.so
-auth       optional    pam_kwallet5.so
account     include     system-local-login
password    include     system-local-login
session     include     system-local-login
-session    optional    pam_gnome_keyring.so auto_start
-session    optional    pam_kwallet5.so auto_start
```

改完后:

```ini
#%PAM-1.0

# ---- autologin 人脸闸门 + KWallet 自动解锁(本项目新增 2026-09-25)----
#
# 1) 人脸闸门用 pam_exec,只按退出码判定:0=通过,非 0=失败。
#    切勿改回 "auth required libbiopass_pam.so":biopass 模块在摄像头不可用/无人脸/
#    模型缺失时返回 PAM_IGNORE(helper exit 2),而 required 会忽略 PAM_IGNORE,
#    与 pam_permit.so 组合就会变成"无认证直接进入桌面"。
#
# 2) 上游默认的 "auth required pam_permit.so" 已被有意删除:
#    没有它以后,认证结果只能来自真实模块;即使将来有人把 pam_exec 改成 optional
#    或误删该行,autologin 也只会失败并回落到登录界面(fail-closed),不会静默放行。
#    如需临时关闭人脸闸门:删掉 pam_exec 行并恢复 "auth required pam_permit.so"。
#
# 3) pam_walletkey 在认证阶段把 KWallet 密码(/etc/pam_walletkey.key)注入 PAM_AUTHTOK,
#    供 pam_kwallet5 在 session 阶段解锁 kdewallet(人脸登录没有密码可抓)。
auth        required    pam_env.so
auth        required    pam_faillock.so preauth
auth        required    pam_shells.so
auth        required    pam_nologin.so
auth        required    pam_exec.so quiet /usr/local/libexec/biopass-pam-auth
-auth       optional    pam_walletkey.so
-auth       optional    pam_gnome_keyring.so
-auth       optional    pam_kwallet5.so

account     include     system-local-login
password    include     system-local-login
session     include     system-local-login
-session    optional    pam_gnome_keyring.so auto_start
-session    optional    pam_kwallet5.so auto_start
```

两处改动:

  1. 加 `auth required pam_exec.so quiet …`。 它排在 `pam_nologin.so` 之后、`pam_permit.so` 原来的位置。`quiet` 让 `pam_exec` 不要把命令输出写进系统日志(`man pam_exec` 里 `stdout` 默认本来就丢进 `/dev/null`,这个标记省掉的是另一路噪音)。
  2. 删掉 `auth required pam_permit.so`。 这一行是上游给“谁都不用认证”的 autologin 用的。留着它,认证栈里就有一个永远成功的模块;一旦有人把 `pam_exec` 那行改成 `optional`、或者干脆删掉闸门行,结果不会是“进不去”,而是静默放行。删掉之后,认证结果只能来自真实模块,配置被改坏也只会 autologin 失败并回落登录界面。

顺带说明为什么 `pam_walletkey` 和 `pam_kwallet5` 这两行也在这一段的开头:它们是钱包自动解锁用的,属于人脸登录后的 KWallet 自动解锁那一篇的内容。只想先要免按键登录,可以先只加 `pam_exec` 那一行,把这两行留到之后再加。

Autologin 配置

`/etc/plasmalogin.conf` 只需要 `[Autologin]` 段里的三项:

```ini
[Autologin]
User=<用户名>
Session=plasma
Relogin=false
```

安装

装之前先另开一个 root 终端放着别关。(我们接下来修改的是登录链路上的 PAM 文件,如果写坏了,还有一个已经通过认证的 root shell 可以用来改回来)

脚本会自动备份到 `/var/backups/plasmalogin-face-<时间戳>/`,并且是幂等的,重复执行不会重复插入:

```bash
#!/usr/bin/env bash
#
# Plasma Login Manager 免按键人脸登录 —— Autologin + pam_exec 人脸闸门 安装脚本
#
#   用法: sudo bash install.sh
#
# 安装内容:
#   1. /usr/local/libexec/biopass-pam-auth        人脸闸门包装脚本(调 biopass-helper)
#   2. /etc/pam.d/plasmalogin-autologin          覆盖 /usr/lib/pam.d 的上游默认(放行式)
#   3. /etc/plasmalogin.conf                     [Autologin] 段加 User=<你>(Relogin 保持默认 false)
#
# 不重启任何服务(重启 plasmalogin 会杀掉当前会话)。改动在下次开机/重启后生效。
# 幂等:可重复运行;每次都会把原文件备份到 /var/backups/plasmalogin-face-<时间戳>/
#
set -euo pipefail

STAMP="$(date +%Y%m%d-%H%M%S)"
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
BACKUP_DIR="/var/backups/plasmalogin-face-${STAMP}"
PLM_CONF="/etc/plasmalogin.conf"
AUTOLOGIN_PAM="/etc/pam.d/plasmalogin-autologin"
WRAPPER_DST="/usr/local/libexec/biopass-pam-auth"
TARGET_USER="${TARGET_USER:-${SUDO_USER:-}}"

if [[ "${EUID}" -ne 0 ]]; then
    echo "错误:请用 root 运行 → sudo bash \"${BASH_SOURCE[0]}\"" >&2
    exit 1
fi

# 不写死用户名:优先用 TARGET_USER,其次用 sudo 记录的调用者。
if [[ -z "${TARGET_USER}" ]]; then
    echo "错误:无法确定目标用户(SUDO_USER 为空)" >&2
    echo "      请显式指定 → TARGET_USER=你的用户名 sudo -E bash \"${BASH_SOURCE[0]}\"" >&2
    exit 1
fi

if ! id "${TARGET_USER}" >/dev/null 2>&1; then
    echo "错误:用户 ${TARGET_USER} 不存在(可用 TARGET_USER=xxx sudo -E bash install.sh 覆盖)" >&2
    exit 1
fi

for f in biopass-pam-auth plasmalogin-autologin.pam.new; do
    if [[ ! -e "${SCRIPT_DIR}/${f}" ]]; then
        echo "错误:缺少交付文件 ${SCRIPT_DIR}/${f}" >&2
        exit 1
    fi
done

echo "==> 备份到 ${BACKUP_DIR}"
mkdir -p "${BACKUP_DIR}"
chmod 700 "${BACKUP_DIR}"
for f in "${PLM_CONF}" "${AUTOLOGIN_PAM}"; do
    [[ -e "${f}" ]] && cp -a "${f}" "${BACKUP_DIR}/$(basename "${f}")"
done
cp -a /usr/lib/pam.d/plasmalogin-autologin "${BACKUP_DIR}/plasmalogin-autologin.usr-lib.pam.d" 2>/dev/null || true
echo "    回滚: sudo bash \"${SCRIPT_DIR}/rollback.sh\" ${BACKUP_DIR}"

echo "==> [1/3] 安装人脸闸门脚本"
install -D -m 0755 -o root -g root "${SCRIPT_DIR}/biopass-pam-auth" "${WRAPPER_DST}"
echo "    ${WRAPPER_DST}"

echo "==> [2/3] 安装 plasmalogin-autologin 的 PAM 配置"
install -m 0644 -o root -g root "${SCRIPT_DIR}/plasmalogin-autologin.pam.new" "${AUTOLOGIN_PAM}"
echo "    ${AUTOLOGIN_PAM}(覆盖 /usr/lib/pam.d/plasmalogin-autologin,后者保持原样)"

echo "==> [3/3] 在 ${PLM_CONF} 的 [Autologin] 段写入 User=${TARGET_USER}(Relogin 不动,保持 false)"
before_hash="$(sha256sum "${PLM_CONF}" | awk '{print $1}')"
tmp="$(mktemp)"

if ! grep -q '^\[Autologin\]' "${PLM_CONF}"; then
    # 情况 0:[Autologin] 段不存在 → 追加一段
    cp -a "${PLM_CONF}" "${tmp}"
    printf '\n[Autologin]\nUser=%s\n' "${TARGET_USER}" >> "${tmp}"
    echo "    已追加 [Autologin] 段"
elif awk '
        /^\[Autologin\]/ { insec = 1; next }
        /^\[/            { insec = 0 }
        insec && /^[[:space:]]*User[[:space:]]*=/ { found = 1 }
        END { exit(found ? 0 : 1) }
    ' "${PLM_CONF}"; then
    # 情况 1:段内已有 User= → 原位替换(保持行位置,自动纠正旧值)
    awk -v user="${TARGET_USER}" '
        /^\[Autologin\]/ { insec = 1; print; next }
        /^\[/            { insec = 0 }
        insec && /^[[:space:]]*User[[:space:]]*=/ {
            if (!done) { printf "User=%s\n", user; done = 1 }
            next
        }
        { print }
    ' "${PLM_CONF}" > "${tmp}"
    echo "    已原位更新 User="
else
    # 情况 2:段存在但没有 User= → 紧跟段头插入
    awk -v user="${TARGET_USER}" '
        { print }
        /^\[Autologin\]/ && !done { printf "User=%s\n", user; done = 1 }
    ' "${PLM_CONF}" > "${tmp}"
    echo "    已在 [Autologin] 段头后插入 User="
fi

install -m 0644 -o root -g root "${tmp}" "${PLM_CONF}"
rm -f "${tmp}"
after_hash="$(sha256sum "${PLM_CONF}" | awk '{print $1}')"
if [[ "${before_hash}" == "${after_hash}" ]]; then
    echo "    (内容已是 User=${TARGET_USER},无变化)"
fi

echo
echo "==> PAM 栈自检(应看到 pam_exec 行且顺序正确):"
grep -nE 'pam_exec|pam_walletkey|pam_permit' "${AUTOLOGIN_PAM}" | sed 's/^/    /'
echo "==> Autologin 配置:"
sed -n '/^\[Autologin\]/,/^\[/p' "${PLM_CONF}" | head -n -1 | sed 's/^/    /'

cat <<EOF

==> 安装完成。验证方式(不需要注销,先验闸门脚本本身):

  # 1) 直接以 root 触发一次人脸闸门(应打开摄像头并识别人脸)
  sudo env PAM_USER=${TARGET_USER} PAM_SERVICE=plasmalogin-autologin ${WRAPPER_DST}; echo "退出码=\$?"
  #    预期:人脸匹配时退出码 0;遮住脸时非 0;摄像头不可用时为 2(同样会被判为失败)
  #    注:fish 里没有 $?,请改用 "$status"
  journalctl -t biopass-pam-auth -b --no-pager | tail -n 5

  # 2) 确认当前会话/登录界面未被影响(本脚本不重启任何服务)
  #    真正的 autologin 效果需要重启系统:
  #    重启后人脸正常 → 无需任何按键直接进入桌面
  #    遮住脸/移开摄像头 → 出现登录界面(按 Enter 可重试人脸,或直接输密码)

  # 3) 重启后检查日志
  journalctl -b -u plasmalogin | grep -iE 'autologin|pam_exec'
  journalctl -b -u plasmalogin | grep -i pam_kwallet5      # 钱包应自动解锁

==> 回滚: sudo bash "${SCRIPT_DIR}/rollback.sh" ${BACKUP_DIR}
EOF
```

执行:

```bash
sudo bash plasmalogin-install.sh
```

脚本不会重启 plasmalogin,因为那会杀掉当前会话。改动在下次开机或重启后生效。

验证

分两层验。先验闸门脚本本身,无需注销或重启:

```bash
sudo env PAM_USER=<用户名> \
  PAM_SERVICE=plasmalogin-autologin \
  /usr/local/libexec/biopass-pam-auth
printf 'exit=%s\n' "$?"
journalctl -t biopass-pam-auth -b --no-pager | tail -n 5
```

`env PAM_USER=… PAM_SERVICE=…` 就是在手工模拟 `pam_exec` 提供的环境。预期是正脸返回 0、遮住脸返回非 0。

提示

`$?` 在 fish 里不存在,要用 `$status`。用 bash 跑这段最省事。

本机实测:

再验真实开机路径。重启后分两次:一次正常对着镜头,一次把摄像头挡上或移开。

```bash
journalctl -b -u plasmalogin | grep -iE 'autologin|Greeter'
journalctl -t biopass-pam-auth -b --no-pager
```

本机两次开机的结果:

还有两条顺手确认过:TTY(`Ctrl+Alt+F3`)下的 `sudo` 仍能走人脸;`sudo` 走的是 `libbiopass_pam.so` 直连,不经过这个闸门,所以 `journalctl -t biopass-pam-auth` 里不会出现 `service=sudo`——这是预期行为,不是故障。

排错

通用性

回滚

回滚不需要手改文件,脚本会从备份还原,并且在 `/etc/pam.d/plasmalogin-autologin` 原本不存在时把它删掉、回落到 `/usr/lib/pam.d/` 的上游默认:

```bash
#!/usr/bin/env bash
#
# 回滚脚本:撤销 install.sh 的 autologin 人脸闸门改动
#
#   用法: sudo bash rollback.sh [备份目录]
#          不给参数时自动使用 /var/backups/plasmalogin-face-* 中最新的一份
#
set -euo pipefail

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
PLM_CONF="/etc/plasmalogin.conf"
AUTOLOGIN_PAM="/etc/pam.d/plasmalogin-autologin"
WRAPPER_DST="/usr/local/libexec/biopass-pam-auth"

if [[ "${EUID}" -ne 0 ]]; then
    echo "错误:请用 root 运行 → sudo bash \"${BASH_SOURCE[0]}\"" >&2
    exit 1
fi

if [[ $# -ge 1 ]]; then
    BACKUP_DIR="$1"
else
    BACKUP_DIR="$(ls -1dt /var/backups/plasmalogin-face-* 2>/dev/null | head -n 1 || true)"
fi

if [[ -z "${BACKUP_DIR:-}" || ! -d "${BACKUP_DIR}" ]]; then
    echo "错误:找不到备份目录,请手动指定:sudo bash rollback.sh /var/backups/plasmalogin-face-YYYYmmdd-HHMMSS" >&2
    exit 1
fi

echo "==> 使用备份:${BACKUP_DIR}"

if [[ -e "${BACKUP_DIR}/plasmalogin.conf" ]]; then
    install -m 0644 -o root -g root "${BACKUP_DIR}/plasmalogin.conf" "${PLM_CONF}"
    echo "    ${PLM_CONF} 已还原(autologin User= 被移除)"
fi

if [[ -e "${BACKUP_DIR}/plasmalogin-autologin" ]]; then
    install -m 0644 -o root -g root "${BACKUP_DIR}/plasmalogin-autologin" "${AUTOLOGIN_PAM}"
    echo "    ${AUTOLOGIN_PAM} 已还原"
else
    # 安装前 /etc/pam.d 下没有这个文件(包内默认在 /usr/lib/pam.d)
    rm -f "${AUTOLOGIN_PAM}"
    echo "    ${AUTOLOGIN_PAM}(本次新建)已删除,回落到 /usr/lib/pam.d/plasmalogin-autologin"
fi

rm -f "${WRAPPER_DST}"
rmdir /usr/local/libexec 2>/dev/null || true
echo "    ${WRAPPER_DST} 已删除"

cat <<'EOF'

==> 回滚完成。说明:
    * 本脚本不重启 plasmalogin(那会杀掉当前会话);下次开机即恢复"显示登录界面"的行为。
    * KWallet 相关改动属于另一个档案(biopass-sudo-kwallet),未在此回滚。
EOF
```
```bash
sudo bash plasmalogin-rollback.sh          # 不给参数 = 用最新那份备份
```

同样不会重启 plasmalogin,下次开机即恢复“显示登录界面”的行为。回滚只覆盖这一篇的改动;钱包那部分属于另一篇,要单独回滚。

什么时候可以退休

犹分省署直,何日是归休。 ——姚合《和膳部李郎中秋夕》

PLM 的这个缺口已经有上游跟踪项:KDE bug 506025(product `plasma-login-manager`,状态 CONFIRMED,wishlist)。那条报告针对的是指纹登录,诉求和这里一样:让登录服务能在 greeter 之外、由界面主动在后台启动一次生物识别,并允许它与密码认证并行。上游目前没有这个能力。

如果后续版本把它做了进去,判断标准是:登录服务能在 greeter 之外安全地启动生物识别,并在失败时回到正常登录流程。满足之后就没有理由继续用 Autologin 绕,届时:

  1. 删掉 `/etc/plasmalogin.conf` 里的 `[Autologin] User=`;
  2. 删掉 `/etc/pam.d/plasmalogin-autologin`,回落到 `/usr/lib/pam.d/` 的上游默认;
  3. 删掉 `/usr/local/libexec/biopass-pam-auth`。

这三步正好就是回滚脚本做的事,直接跑它也可以。

参考

本文引用的文章

引用本文的文章