Skip to content

Troubleshooting

McDope edited this page Jul 2, 2026 · 31 revisions

Troubleshooting

Don't panic!

Log Analysis

Most pam_usb tools log to syslog, but not all:

Tool Logs to syslog Facility / tag
pam_usb.so Yes AUTH — usually /var/log/auth.log
pamusb-agent Yes AUTH — usually /var/log/auth.log
pamusb-keyring-unlock-gnome Yes LOCAL0 — tag pamusb-keyring-unlock-gnome
pinentry-pamusb Yes AUTH — tag pinentry-pamusb

This can be useful for GUI-driven applications (for instance GDM) where you don't get to see console output. AUTH messages are usually written to /var/log/auth.log but may vary depending on the operating system you're using.

# tail -f /var/log/auth.log
pamusb-agent[25429]: Device "sandisk" has been inserted. Performing
verification...
pamusb-agent[25429]: Executing "/usr/bin/pamusb-check --quiet
--config=/etc/pamusb.conf --service=pamusb-agent scox"
pam_usb[25485]: Authentication request for user "scox" (pamusb-agent)
pam_usb[25485]: Device "sandisk" is connected (good).
pam_usb[25485]: Access granted.
pamusb-agent[25429]: Authentication succeeded. Unlocking user "scox"...
pamusb-agent[25429]: Unlocked.

On systems using systemd without a traditional syslog daemon, /var/log/auth.log may not exist. Use journalctl instead:

# journalctl -f -t pam_usb -t pamusb-agent -t pamusb-keyring-unlock-gnome -t pinentry-pamusb

Troubleshooting pinentry-pamusb: Authentication results, passphrase delivery, and fallback events are logged to syslog (AUTH facility, tag pinentry-pamusb). Check the log with:

journalctl -t pinentry-pamusb

For deeper gpg-agent protocol issues, enable gpg-agent debug logging (--debug-all in ~/.gnupg/gpg-agent.conf).

For pamusb-check you can also use the --debug argument, but that is only temporary and wont help you with i.e login manager issues.

Enabling debug

Enabling debug messages may help you find out what's wrong.

To enable them, edit /etc/security/pam_usb.conf and set the following option:

<defaults>
  <option name="debug">trueoption>
defaults>

You can also enable debug messages only for a specific user, device or service.

<services>
  <service id="sudo">
    <option name="debug">trueoption>
  service>
services>

Device not detected at all

If pam_usb reports no device is connected even though the USB stick is plugged in, work through these steps:

1. Verify pam_usb can see your device at all:

pamusb-conf --list-devices

This lists every removable device UDisks2 currently sees. If your device appears here but authentication still fails, the serial/vendor/model in /etc/security/pam_usb.conf does not match the device.

If your device does not appear here, continue below.

2. Check that UDisks2 is running:

systemctl status udisks2

pam_usb talks to UDisks2 over D-Bus to enumerate devices. If UDisks2 is stopped or crashed you will see "Unable to check for device, could not get UDisksClient!" in the log and no device will ever be found. Start and enable it:

sudo systemctl start udisks2
sudo systemctl enable udisks2

3. Device detected but authentication still fails — check for config mismatch:

Run pamusb-check --debug with the device plugged in and look for lines like:

Serial "XXXX" doesn't match "YYYY"

This means the serial number in your config does not match the physical device. Re-run pamusb-conf --add-device to pick up the correct values.

4. Device takes too long to be detected:

pam_usb waits up to probe_timeout seconds (default 10s) for the device volume to appear. On slower USB sticks or busy systems this can expire before the device is ready, producing a "not connected" denial even though the device is physically present.

Increase the timeout in /etc/security/pam_usb.conf — either globally or for the specific device:

<device id="MyDevice">
  <option name="probe_timeout">20soption>
device>

Getting 'Access denied' on graphical terminals / when using agent

Most times this is caused by pamusb not being able to determine your login/session tty. This shouldn't happen with current builds since we support multiple ways to determine it by now.

If it does happen, enable debug and look for this specific line in the log:

Couldn't confirm login tty to be neither local or remote - denying.

If you see that line, pam_usb exhausted all TTY detection methods without being able to confirm the session is local. Please create an issue which should contain the output of w and pamusb-check --debug . Please also specify your distribution, login manager and desktop environment used. The default issue template will assist you with this.

Getting 'Pad checking failed!' when trying to authenticate

This error means that either the machine/host specific pad file on the device, or - more likely - the user specific pad file in your homedir is not in sync anymore. It can also be caused if you use the same device on two computers and both share the same username (guess why I know 🤦).

It can happen if you remove the authentication device without unmounting it before, manually mess with the pad files (like copying from a previous device) or your system crashed before file buffers were written to the media and similar.

Or, worst case scenario - someone tried to tamper with your system. In example someone could deep-clone (not only FS but also HW Ids) your authentication device and use it to login or sudo (if you use pamusb as the only factor), pads will then be updated on system and the attacking device but not on your original device since it wasn't connected at the time of your login. On next authentication request with your original device you will then get "Pad checking failed!". Of course for most persons this is an unlikely scenario. Also this would only work if the attacker uses his device before you use yours the next time. Else your authentication would invalidate his pads. But if your system and/or device is accessible to other persons, keep it in mind.

Related pad errors you may see in the debug log:

  • "Device pad is incomplete" / "System pad is incomplete" — the pad file exists but is shorter than expected (1024 bytes). Usually caused by a filesystem write interrupted by an unclean unmount or system crash.
  • "System pad missing but device pad exists" — the pad file was deleted from your home directory (or never written) but the device-side pad still exists. This can indicate an interrupted first authentication, a manual deletion, or — in the tamper scenario — that someone authenticated from your device on another machine.

All of these have the same resolution: reset the pads so they are regenerated cleanly on the next successful authentication.

To resolve this you can use pamusb-conf --reset-pads=, which will remove the pad files for the given user and its configured device so they will be regenerated on next authentication.

Agent configuration / commands don't work like expected

You have restarted the agent service after your config changes, right? RIIIIIIGHT? Seriously, you need to restart it for changes to be picked up.

The agent will log all executed commands, as well as their exitcode; stdout and stderr (since v0.8.3). You can view this log either via systemd, or by tail'ing /var/log/auth.log — or on systems without a traditional syslog daemon:

# journalctl -f -t pamusb-agent

You can use this to a) verify your config is picked up like expected and b) configured commands do what you want. For some programs, esp. ones expecting to be run within a graphical environment, you will have to provide environment values via tags in the agent configuration. Usually the log will provide you with some good clues. But feel free to open a support issue if you need help.

Environment variables silently rejected:

The agent blocks a set of dangerous environment variables to prevent privilege escalation. If you set any of the following in an tag they will be ignored and a warning logged — the command will run without them:

LD_PRELOAD, LD_LIBRARY_PATH, LD_AUDIT, LD_DEBUG, GLIBC_TUNABLES,
PYTHONPATH, PERL5LIB, RUBYLIB, IFS, CDPATH, ENV, BASH_ENV, PATH

Look for Rejecting dangerous env var in the agent log if a command behaves unexpectedly. If you need to set PATH for a command, wrap it in a small shell script that sets the path internally, and call the script from instead.

pam_usb not working in login manager when the device wasn't plugged before login manager started / always asked for password

Are you using lightdm by any chance?

Some login managers auto-select the first user they have in their list. This starts the pam chain and pam_usb will see "device is not plugged" and deny the request. At that point then pam_unix (or whatever your next module is) kicks in and asks for the password. This is intended behavior in pam_usb - the actual issue here is the login manager assuming which user wants to login.

Even if you now plug the device, from pam_usb POV the request is failed/finished and it wont care anymore. You will have to press [ESC] to abort the current authentication request and click/select the user again (if not auto-selected).

You can reduce how often this happens by configuring a service-specific probe_timeout for lightdm. This gives pam_usb a longer window to detect the device after the chain starts — if you plug in the USB stick within that window, authentication succeeds without needing to press ESC:

<services>
  <service id="lightdm">
    <option name="probe_timeout">30soption>
  service>
services>

My screen wont lock when using pam_usb

Are you using KDE / klockscreen by any chance? And is your device still plugged?

Some lockscreens start the PAM chain already at time of lock. If you use only a password, that's fine. But if you use pam_usb, it will see "hey, the device is there and valid - I'll allow this". It's basically the inverted version of the topic in the paragraph above (see https://github.com/mcdope/pam_usb/wiki/Troubleshooting#pam_usb-not-working-in-login-manager-when-the-device-wasnt-plugged-before-login-manager-started--always-asked-for-password)

If you are not using KDE, please create an issue.

SELinux and pam_usb

If you have SELinux enabled you will likely get errors with pam_usb. At least on Fedora 40 you need to allow some things that are by default denied.

There is now a profile available for Fedora 40 that you can install to allow pam_usb to work like intended. To install it download both files from selinux/ to some directory, open a shell in that directory and then run semodule login.pp. Replace "login" with the actual profile you want to install, but so far there is only one for login. It may work on other distributions or releases, too but this is untested.

In case it doesn't work for you, see the discussion at https://github.com/mcdope/pam_usb/discussions/241 to find out how to create your own profile.

PolicyKit 127 and pam_usb

PolicyKit starting from 127 and pam_usb are incompatible in the default configuration. This is caused by the introduction of a socket based polkit-agent-helper. You will have to a) disable the socket service b) re-enable suid and c) redo that on every polkit upgrade until they fix their agent (not only pam_usb is influenced by this).

Details:

1. Disable the Systemd Socket

Stop and disable the socket so systemd stops intercepting the authentication requests. Open your terminal and run:

sudo systemctl disable --now polkit-agent-helper.socket

2. Restore the SUID Bit on the Helper Binary

Because you disabled the socket, polkit will fall back to executing the agent helper directly. For this to work, the binary must have the SUID (Set Owner User ID) bit set. Since your distribution's package manager likely stripped this bit in the v127 update, you will need to restore it manually.

First, locate your polkit-agent-helper-1 binary. It is typically found at one of these two paths, depending on your distribution:

  • /usr/lib/polkit-1/polkit-agent-helper-1 (Debian, Ubuntu, Fedora, openSUSE)
  • /usr/libexec/polkit-1/polkit-agent-helper-1 (Arch Linux)

Once you confirm the path, restore the SUID bit and set root ownership:

sudo chown root:root /usr/lib/polkit-1/polkit-agent-helper-1
sudo chmod u+s /usr/lib/polkit-1/polkit-agent-helper-1

(Remember to replace the path if your system uses the /usr/libexec/ directory).

A Quick Warning on Package Updates

Because you are modifying the permissions of a package-managed file manually, a future update to the polkit package might overwrite your changes and strip the SUID bit again. Many distributions are currently working on patches or have temporarily downgraded polkit to 126 in their repositories, so keeping your system up-to-date should eventually resolve the underlying bug natively.

Alternative way, without messing with polkit

Create a copy of your common-auth pam config (or whatever file it is on your distribution) and name it polkit-1. Remove pam_usb from it.

Remote Desktop / Remote Access Detection

pam_usb can block authentication when it detects an active remote desktop session. This page covers how the check works, why it might fire unexpectedly, and how to handle it.

How it works

When deny_remote and remote_desktop_check are both enabled (the defaults), pam_usb checks for remote access via two layers before accepting a USB token:

  1. Remote service detection — checks for known remote desktop software
  2. Virtual input device detection — checks for BUS_VIRTUAL evdev devices (commonly created by remote desktop tools)

Both must clear for authentication to proceed.

Detected services and their trigger conditions

Service What triggers a deny
AnyDesk Process anydesk is running (any connection state)
VNC (gnome-remote-desktop, x11vnc, Xvnc) External ESTABLISHED connection on local TCP port 5900 and a matching VNC server process
RDP (gnome-remote-desktop, xrdp) External ESTABLISHED connection on local TCP port 3389 and a matching process (gnome-remote-de, xrdp) running
TeamViewer Outbound ESTABLISHED connection to remote TCP port 5938 and TeamViewer_Desk or teamviewerd process running

All checks use /proc/net/tcp (IPv4) and /proc/net/tcp6 (IPv6). Loopback connections (127.x.x.x, ::1) are never counted as external.

"External" means: ESTABLISHED state + non-loopback remote address.


Common false positives

AnyDesk installed but not in a session

AnyDesk is detected by process presence alone — if the daemon is running in the background (which it does by default on many installs), pam_usb will deny even without an active connection.

Fix: Disable the AnyDesk background service when not needed:

systemctl disable --now anydesk

Or stop it temporarily before authenticating:

sudo systemctl stop anydesk
Accessibility tools / input remappers

Software that creates virtual input devices (e.g. key remappers, on-screen keyboards, tablet drivers, disability assistance tools) may register a BUS_VIRTUAL evdev node. pam_usb treats this as a signal that a remote desktop tool could be injecting input.

Affected tools include (non-exhaustive):

  • Screen readers / on-screen keyboards that synthesise input
  • Drawing tablet drivers that register virtual devices (some Wacom, Huion setups)
  • Key remappers (e.g. keyd, xremap, input-remapper)
  • Accessibility software like xdotool daemons

Workaround: Disable remote_desktop_check in pam_usb.conf if you rely on such devices and cannot remove them:

<option name="remote_desktop_check">falseoption>

Or disable the virtual device service before authenticating, then re-enable it.

VNC/RDP port in use by an unrelated app

Any process that listens on port 5900 (VNC) or 3389 (RDP) with an external ESTABLISHED connection will trigger the port check. The matching process name must also be present — but if it is, authentication is denied.

If you run a non-standard VNC or RDP server on these ports, pam_usb will catch it. Move the service to a non-standard port or disable remote_desktop_check.

TeamViewer installed but idle

TeamViewer will not trigger a deny unless it has an active outbound connection to a relay server (port 5938). Simply having TeamViewer installed or the daemon running without an active session is fine.

If it is denying unexpectedly, check:

grep ' 1742 ' /proc/net/tcp   # hex 1742 = port 5938
grep ' 1742 ' /proc/net/tcp6

If you see 01 in the state column, TeamViewer has an active relay connection.

Permission errors on the virtual input device check (EACCES / "permission denied")

The virtual input device check needs read access to /dev/input, which is normally restricted to root and members of the input group. Since v0.9.3, packages install a setgid helper binary, /usr/lib/pam_usb/pamusb-evdev-helper (owned root:input, setgid bit set), so the check works for non-root invocations — e.g. screen lockers (i3lock, swaylock, gnome-screensaver) or a manually run pamusb-check — without any group membership changes. This is automatic for package installs and for make install when the input group exists on the system; no action is required.

If you see a debug line like:

Checking for virtual input devices...
Failed to open /dev/input/eventX: Permission denied

it means the helper is missing or not installed with the correct setgid permissions (e.g. a manual install without the input group present at install time, or a custom PREFIX build). Re-running make install after creating the input group, or reinstalling the package, will pick up the setgid bit.

As a manual fallback (only if the helper cannot be used), add the user to the input group:

sudo usermod -aG input <username>

Warning: membership in the input group grants read access to all input devices, including keyboards — effectively keylogger-level access for every process the user runs. Only use this on trusted, single-user systems, and prefer the setgid helper wherever possible. See man pamusb-conf (NOTES section) for details.

Diagnosing a deny

Enable debug logging in pam_usb.conf:

<option name="debug">trueoption>

Then attempt authentication and read the output. Relevant log lines:

Checking for active remote desktop services...
  Checking for known remote desktop processes...
    Found remote service process: anydesk
Active remote desktop service with connection detected, denying.
Virtual input device detected (possible remote desktop tool), denying.
XRDP session detected (), denying.

The debug output will name the exact check that fired.

Disabling the check entirely

To skip remote desktop detection while keeping all other pam_usb protection:

<option name="remote_desktop_check">falseoption>

To disable all remote/local discrimination (not recommended):

<option name="deny_remote">falseoption>

Both options can be scoped to a specific user or service in the config hierarchy.

Configuration reference

Option Default Effect
deny_remote true Master switch — if false, no remote checks run at all
remote_desktop_check true Enables process + port + virtual-device checks described on this page

Clone this wiki locally