Skip to content

Troubleshooting

Atay Özcan edited this page May 2, 2026 · 5 revisions

Troubleshooting

I see two dialogs when running pkexec

This is expected on v0.2.x. Sentinel doesn't ship a polkit agent yet, so on desktops that have their own (cosmic-osd, polkit-gnome, polkit-kde) you'll see both: the desktop's password prompt and Sentinel's dialog (the latter spawned by pam_sentinel.so from inside polkit-agent-helper-1).

It's fixable today by suppressing your desktop's agent — e.g. on cosmic-comp:

sudo chmod -x /usr/bin/cosmic-osd
# log out / log back in

Side effect: you lose the desktop's volume/brightness OSDs that cosmic-osd handles. There's no per-feature toggle.

Since v0.4, a proper Sentinel polkit agent (Polkit Agent) ships that registers ahead of cosmic-osd's same-subject attempt — the duplicate UI is gone and you can leave cosmic-osd executable.

pkexec shows the slow PAM dialog instead of the fast bypass

Symptom: after pkexec true (or any polkit-mediated action), the journal shows event=auth.allow source=dialog ... instead of event=auth.allow source=agent .... Both work, but the agent path is faster (no fork + setuid + exec dance) and gives richer process info in the dialog.

Root cause: the Sentinel polkit agent isn't currently the authoritative agent registered with polkitd. Verify with:

journalctl -t sentinel-polkit-agent --since "1 minute ago" --no-pager \
  | grep -E "registered|already exists"

If you see An authentication agent already exists for the given subject, another agent (typically cosmic-osd on COSMIC) won the race after install or relogin. Since v0.5.1, Sentinel retries registration up to 8 times with 500 ms backoff — it'll eventually take over IF the competitor exits or backs off.

For session-supervised competitors that hard-respawn forever (cosmic-sessioncosmic-osd is the canonical case), the only reliable workaround is to disable the competitor outright:

pkexec chmod -x /usr/bin/cosmic-osd     # COSMIC users
# or
pkexec chmod -x /usr/lib/polkit-gnome-authentication-agent-1
pkexec chmod -x /usr/lib/polkit-kde-authentication-agent-1

Side effect on COSMIC: you lose cosmic-osd's brightness/volume OSDs. There's no per-feature toggle. Sentinel becomes the sole polkit agent.

I'm locked out of sudo

The fastest recovery, in order of preference:

1. Another root shell on a different TTY

Switch to a free TTY (Ctrl+Alt+F2F6), log in directly as root (if root login is enabled) or as another user that doesn't go through Sentinel:

# Inside the second shell, with root:
mv /etc/pam.d/sudo.pre-sentinel.bak /etc/pam.d/sudo
# or:
sed -i '/pam_sentinel/d' /etc/pam.d/sudo
# or:
/path/to/sentinel-source/uninstall.sh --yes

2. Single-user mode

Reboot. At the boot loader (GRUB / systemd-boot), edit the kernel command line and append init=/bin/bash. Boot. Filesystem will be mounted read-only — remount r/w:

mount -o remount,rw /
mv /etc/pam.d/sudo.pre-sentinel.bak /etc/pam.d/sudo
sync && reboot -f

3. Live USB

Boot any Linux live USB, mount your root partition, edit <mountpoint>/etc/pam.d/sudo directly. Same fix as above.

4. The full uninstall path

If the install state file is intact, the cleanest recovery from any of the above is:

cd /path/to/sentinel-source
./uninstall.sh --yes        # already running as root in the recovery shell

This restores every file Sentinel touched (including any pre-existing polkit-1 / sudo you'd customised before installing).

The dialog never appears

Check, in order:

# 1. Is the PAM module loaded? (you should see this every sudo attempt)
journalctl -t pam_sentinel -f

# 2. Is the helper installed and runnable?
ls -l /usr/lib/sentinel-helper /usr/lib/security/pam_sentinel.so

# 3. Does the helper run by hand?
/usr/lib/sentinel-helper --timeout 10 --randomize --process-exe /usr/bin/sudo

# 4. Is your compositor providing zwlr-layer-shell-v1?
grep -r layer_shell /usr/share/wayland-sessions   # rough check
# or: weston-info | grep layer-shell  (if weston-info is installed)

# 5. Are you on GNOME/Mutter? (Mutter doesn't implement layer-shell)
echo "$XDG_CURRENT_DESKTOP"

If WAYLAND_DISPLAY isn't set in the user environment that PAM sees (some screen lockers / login flows scrub it), the helper exits DENY silently and PAM falls through to pam_unix — you get a password prompt instead of the dialog. With headless_action = "password" this is the correct fallback.

"wrong mode" / "wrong ownership" install error

The install script's verify step caught a file with the wrong permissions. Likely cause: a previous failed install left a half-written file. Easiest fix:

pkexec ./uninstall.sh --yes      # cleans up via state file
pkexec ./install.sh

Helper compiles but won't run: "WAYLAND_DISPLAY not set"

The helper is Wayland-only. It doesn't run on X11, headless, or SSH. This is intentional — for headless paths, the PAM module returns PAM_IGNORE and the password fallback runs at the PAM layer.

You can still smoke-test the helper from a Wayland session:

just helper-test

"ext-session-lock-v1 path not yet implemented"

You're on a pre-0.2.0 build. The session-lock plan was dropped in v0.2.0 — upgrade and the warning is gone.

GNOME / Mutter

GNOME (Mutter) doesn't implement zwlr-layer-shell-v1, so the overlay won't render. Two options:

  1. Run with --windowed (debug fallback to xdg-toplevel — doesn't block input or grab keyboard, just a regular window).
  2. Use a different Wayland compositor (cosmic-comp, Hyprland, Sway, KWin/Wayland) for sessions that you want gated by Sentinel.

This is a Mutter limitation we can't work around from inside the helper.

Helper hangs after Allow / Deny

The helper exits via cosmic::iced::exit(). If it hangs, the compositor probably refused to destroy the layer surface — kill it:

pkill sentinel-helper

PAM's safety-margin poll (helper timeout + 5 s) will SIGKILL it automatically; users won't be permanently stuck.

syslog spam

If log_attempts = true is too chatty, set it to false per service:

[services.polkit-1]
log_attempts = false

Or globally in [general]. The default is true because losing the audit trail on a security tool is worse than the syslog noise.

Debug logging

The PAM module logs to syslog facility auth. To get more verbose logs, build with RUST_LOG=debug and add debug to the PAM line:

auth   sufficient   pam_sentinel.so   debug

This is recognised by libpam as a generic flag and is forwarded to the module. Most third-party PAM modules treat it as "log everything"; pam_sentinel follows the same convention.

Upgrading

# Source build:
git pull
pkexec ./install.sh           # re-runs all of install, replacing files

# AUR:
yay -Syu sentinel             # or sentinel-git

# Debian / RPM:
sudo apt install ./sentinel_$NEW_VERSION-1_amd64.deb
sudo dnf install ./sentinel-$NEW_VERSION-1.x86_64.rpm

install.sh is idempotent — re-running it is the supported upgrade path. The state file and .pre-sentinel.bak files are preserved across re-runs (your original pre-Sentinel files don't get overwritten).

Since v0.5, install.sh also restarts the running polkit agent in place — you no longer need to log out + back in for the new binary to take effect on upgrade. This requires the install script to be running in a session whose audit sessionid matches the compositor's (the typical case when you launched it from a terminal opened by the compositor); if the sessionids differ, the script logs a warning and falls back to "the new agent will activate at next login".

The dialog appears in English even when my LANG is set

The helper picks a locale from LC_ALL → LC_MESSAGES → LANG. If none matches one of the embedded bundles (en-US, de-DE, es-ES, fr-FR, it-IT, ja-JP, nl-NL, pl-PL, pt-BR, ru-RU, tr-TR, zh-CN), the helper silently falls back to en-US.

For the PAM-spawned dialog path (sudo, pkexec via PAM), the locale env vars are scrubbed by the privileged binary before pam_sentinel.so runs. v0.5 recovers them by reading the requesting user's /proc/<pid>/environ. If you've explicitly cleared LANG in your shell or your terminal doesn't propagate it, you'll see the fallback. Check with:

env | grep -E '^LC_|^LANG=' | head

For the polkit agent path (anything that triggers sentinel-polkit-agent's dialog), the agent inherits env from your compositor at autostart time. Logging out / back in after changing your shell's LANG defaults is the cleanest way to update it.

The dialog crashed / never appeared on GNOME

GNOME's Mutter doesn't implement zwlr-layer-shell-v1, so prior to v0.5 the helper hard-failed on GNOME. v0.5 detects GNOME-family desktops via XDG_CURRENT_DESKTOP and auto-falls back to --windowed mode (a regular xdg-toplevel window instead of the full-screen overlay). You should see a one-line stderr notice when this kicks in:

sentinel-helper: detected compositor without zwlr-layer-shell-v1 …

Override either way: --layer-shell to force the overlay even on GNOME (will fail), --windowed to force the regular window even elsewhere (debugging).

Querying the audit log

Auth-outcome events are structured key=value lines (logfmt) since v0.5:

# Last 50 auth events, JSON-formatted:
journalctl -t pam_sentinel -t sentinel-polkit-agent --output=json -n 50 \
  | jq 'select(.MESSAGE | startswith("event=auth.")) | .MESSAGE'

# Just the denials in the last hour:
journalctl -t pam_sentinel -t sentinel-polkit-agent --since "1 hour ago" \
  | grep "event=auth.deny"

# Latency distribution:
journalctl -t pam_sentinel -t sentinel-polkit-agent --since today \
  | grep -oP 'latency_ms=\K\d+' | sort -n | uniq -c

Fields available:

  • eventauth.allow / auth.deny / auth.timeout / auth.error
  • sourcedialog / bypass / headless / agent / agent.bypass
  • user, service, action, process, uid, peer_pid, latency_ms

Clone this wiki locally