pam_systemd: fix regression introduced in v258 by preserving the FIFO fd

Upstream commit 3180c4d introduced a version incompatibility between
pam_systemd.so v258 and logind v257. This is problematic because such version
mismatches can occur in practice: logind still cannot be restarted during a
systemd package upgrade (it's a long-standing limitation, see
https://github.com/systemd/systemd/issues/17308).

When pam_systemd requests a new session, logind v257 returns a FIFO
fd. pam_systemd.so v258 ignores this fd and closes it. logind interprets the
closure as the session leader exiting and immediately terminates the session.

This patch partially reverts commit 3180c4d and restores the handling of the
FIFO fd in pam_systemd. The change is limited to the D-Bus APIs, since the
varlink API was only introduced in logind v258.

Follow-up for 3180c4d461.
This commit is contained in:
Franck Bui
2026-01-22 19:13:13 +01:00
committed by Mike Yuan
parent b61aeeb315
commit 49f7149947
+18 -1
View File
@@ -10,6 +10,7 @@
#include <unistd.h>
#include "sd-bus.h"
#include "sd-daemon.h"
#include "sd-varlink.h"
#include "alloc-util.h"
@@ -1254,19 +1255,35 @@ static int register_session(
return PAM_SESSION_ERR;
}
int session_fd;
r = sd_bus_message_read(
reply,
"soshusub",
&id,
&object_path,
&runtime_path,
/* session_fd= */ NULL,
&session_fd,
&original_uid,
&real_seat,
&real_vtnr,
&existing);
if (r < 0)
return pam_bus_log_parse_error(pamh, r);
/* Since v258, logind fully relies on pidfd to monitor the lifetime of the session leader
* process and returns a dummy session_fd (no longer a fifo). However because logind cannot
* be restarted (known long-standing issue), we must still be prepared to receive a fifo fd
* from a running logind older than v258. */
if (sd_is_fifo(session_fd, NULL) > 0) {
_cleanup_close_ int fd = fcntl(session_fd, F_DUPFD_CLOEXEC, 3);
if (fd < 0)
return pam_syslog_errno(pamh, LOG_ERR, errno, "Failed to dup session fd: %m");
r = pam_set_data(pamh, "systemd.session-fd", FD_TO_PTR(fd), NULL);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(pamh, LOG_ERR, r, "Failed to install session fd: @PAMERR@");
TAKE_FD(fd);
}
}
pam_debug_syslog(pamh, debug,