]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pam_systemd_home: clean up sd-bus when called about something else's user
authorLuca Boccassi <bluca@debian.org>
Thu, 20 Apr 2023 11:58:18 +0000 (12:58 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 24 Apr 2023 12:18:22 +0000 (14:18 +0200)
acquire_home() takes a reference to a sd-bus object, which the open_session
hook cleans on success. But only when handling a user actually owned by homed,
it did not clean it up when skipping because it is being invoked on a system
user.
We need to be careful with sd-bus here as pam_sm_open_session is the last
hook before forking, and we want to clean up sd-bus before that happens, or
we'll have a broken reference (FDs are cloexec) in the child process, which
will then assert when attempting to close them, or leak the bus connection
which causes dbus to complain loudly:

 dbus-daemon[62]: [system] Connection has not authenticated soon enough, closing it (auth_timeout=30000ms, elapsed: 30020ms)

src/home/pam_systemd_home.c

index 8a7bfc5837f26fe9b9e3bccea4c3b425994b1229..e28c95f787e6732424676d0b9a0a02b6d29f1b39 100644 (file)
@@ -727,7 +727,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
 
         r = acquire_home(handle, /* please_authenticate = */ false, suspend_please, debug);
         if (r == PAM_USER_UNKNOWN) /* Not managed by us? Don't complain. */
-                return PAM_SUCCESS;
+                goto success; /* Need to free the bus resource, as acquire_home() takes a reference. */
         if (r != PAM_SUCCESS)
                 return r;
 
@@ -741,6 +741,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                 return pam_syslog_pam_error(handle, LOG_ERR, r,
                                             "Failed to set PAM environment variable $SYSTEMD_HOME_SUSPEND: @PAMERR@");
 
+success:
         /* Let's release the D-Bus connection, after all the session might live quite a long time, and we are
          * not going to process the bus connection in that time, so let's better close before the daemon
          * kicks us off because we are not processing anything. */