Skip to content

systemd-user doesn't properly close its PAM session #8598

@ebiggers

Description

@ebiggers

The systemd --user instance that is started when a user first logs in (if pam_systemd is enabled) starts a subprocess "(sd-pam)" that opens a PAM session for the user, using the "systemd-user" service name. See setup_pam() in src/core/execute.c.

However, this PAM session is not properly closed. There are two related bugs:

  • The sd-pam subprocess drops privileges after pam_open_session(), so pam_close_session() runs as the user rather than as root. This breaks PAM modules that need to do privileged tasks to clean up the session, such as unmounting the user's home directory. Note that the man page for pam_close_session() explicitly says that privileges are needed:

It should be noted that the effective uid, geteuid(2). of the application should be of sufficient privilege to perform such tasks as unmounting the user's home directory for example.

  • systemd doesn't wait for the sd-pam subprocess to close the PAM session and exit but rather sends it SIGKILL. It can be killed while in the middle of pam_close_session(), so not all of the PAM hooks are guaranteed to be run. I verified this using strace; PID 1 was iterating through all processes in the user's cgroup, including sd-pam, and killing them. This breaks PAM modules such as pam_mount, pam_ecryptfs, and pam_fscrypt. That is, with pam_mount the user's filesystems are left mounted; with pam_ecryptfs the user's encrypted home directory is left mounted/unlocked; and with pam_fscrypt the user's login passphrase-protected directories are left "unlocked". This appears to be a longstanding bug that many users have reported in many Linux distributions over the past few years; the preceding links were just a couple examples. The Debian bug for ecryptfs was reported for the Jessie release which was the release that Debian switched from sysvinit to systemd.

I observed these bugs on systemd 238 and on Arch Linux, though from what I gather these bugs are already years old at this point, and affect all Linux distributions that use systemd. To be very clear, these bugs are not caused by the user having background processes running; the problem is that systemd is not properly closing a PAM session when the systemd-user instance exits.

Unfortunately I don't have an easy solution in mind, though I haven't had time to look into it in depth yet. It's possible that having the sd-pam process be a child of systemd-user is just fundamentally wrong, so the order will need to be flipped around to have sd-pam spawn systemd-user, which would make it more similar to how other processes like 'login' or display managers manage PAM sessions.

In the mean time, here are some possible workarounds for people affected by this bug:

  • One workaround is to configure /etc/pam.d/systemd-user to exclude the relevant PAM module(s). This prevents systemd-user from opening a PAM session with the relevant PAM modules, so it doesn't matter that it doesn't get closed. I'm using this workaround on my Arch Linux system with pam_fscrypt. However, this has the disadvantage that if systemd-run is used to run a long-lived service like 'screen' that persists past logout, then the home directory is not kept unlocked as might be expected.

  • An alternative workaround which might be implemented for fscrypt (though a similar workaround could be used for ecryptfs as well) is to do the directory locking/unlocking in a systemd service instead of a PAM module. It's an ugly hack though, and the PAM session hook would still be needed for non-broken init systems.

  • Or pam_systemd can be disabled, though this breaks other functionality.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions