systemd/1297-pam_systemd-honor-session-class-provided-via-PAM-env.patch
Jan Macku f453f2c6ee systemd-252-63
Resolves: RHEL-109833,RHEL-127859
2025-11-27 14:33:52 +01:00

119 lines
5.5 KiB
Diff

From d5d08290cf66a0c491a875345902d5c3bfeb6c5a Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 25 Aug 2025 15:09:36 +0200
Subject: [PATCH] pam_systemd: honor session class provided via PAM environment
Replaces #38638
Co-authored-by: Lennart Poettering <lennart@poettering.net>
(cherry picked from commit cf2630acaa87ded5ad99ea30ed4bd895e71ca503)
Resolves: RHEL-109833
[msekleta: this is absolutely minimal version of the ideas implemented in
https://github.com/systemd/systemd/pull/30884. At this point I want to avoid
big/risky backports and what I am proposing here should suffice.]
---
man/pam_systemd.xml | 11 ++++++++++-
src/login/logind-session.c | 5 +++--
src/login/logind-user.c | 16 +++++++++++++++-
src/login/pam_systemd.c | 6 ++++--
4 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml
index 60b8577822..55239ea3d7 100644
--- a/man/pam_systemd.xml
+++ b/man/pam_systemd.xml
@@ -95,8 +95,17 @@
<literal>lock-screen</literal> or <literal>background</literal>. See
<citerefentry><refentrytitle>sd_session_get_class</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
details about the session class.</para></listitem>
- </varlistentry>
+ <para>If no session class is specified via either the PAM module option or via the
+ <varname>$XDG_SESSION_CLASS</varname> environment variable, the class is automatically chosen, depending on
+ various session parameters, such as the session type (if known), whether the session has a TTY or X11
+ display, and the user disposition. Note that various tools allow setting the session class for newly
+ allocated PAM sessions explicitly by means of the <varname>$XDG_SESSION_CLASS</varname> environment variable.
+ For example, classic UNIX cronjobs support environment variable assignments (see
+ <citerefentry project='man-pages'><refentrytitle>crontab</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
+ which may be used to choose between the <constant>background</constant> and
+ <constant>background-light</constant> session class individually per cronjob.</para>
+ </varlistentry>
<varlistentry>
<term><varname>type=</varname></term>
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 5ba1e690ac..2ad05e3798 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -680,8 +680,9 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er
s->user->slice,
description,
/* These two have StopWhenUnneeded= set, hence add a dep towards them */
- STRV_MAKE(s->user->runtime_dir_service,
- s->user->service),
+ s->class == SESSION_BACKGROUND_LIGHT ?
+ STRV_MAKE(s->user->runtime_dir_service) :
+ STRV_MAKE(s->user->runtime_dir_service, s->user->service),
after,
user_record_home_directory(s->user->user_record),
properties,
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index e02ad754ee..ffa32c6ce5 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -441,6 +441,19 @@ static int user_update_slice(User *u) {
return 0;
}
+static bool user_wants_service_manager(User *u) {
+ assert(u);
+
+ LIST_FOREACH(sessions_by_user, s, u->sessions)
+ if (s->class != SESSION_BACKGROUND_LIGHT)
+ return true;
+
+ if (user_check_linger_file(u) > 0)
+ return true;
+
+ return false;
+}
+
int user_start(User *u) {
assert(u);
@@ -464,7 +477,8 @@ int user_start(User *u) {
(void) user_update_slice(u);
/* Start user@UID.service */
- user_start_service(u);
+ if (user_wants_service_manager(u))
+ user_start_service(u);
if (!u->started) {
if (!dual_timestamp_is_set(&u->timestamp))
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index a288b3602a..c7377e21a8 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -753,14 +753,16 @@ _public_ PAM_EXTERN int pam_sm_open_session(
* (as they otherwise even try to update it!) — but cron doesn't actually allocate a TTY for its forked
* off processes.) */
type = "unspecified";
- class = "background";
+ if (isempty(class))
+ class = "background";
tty = NULL;
} else if (streq(tty, "ssh")) {
/* ssh has been setting PAM_TTY to "ssh" (for the same reason as cron does this, see above. For further
* details look for "PAM_TTY_KLUDGE" in the openssh sources). */
type ="tty";
- class = "user";
+ if (isempty(class))
+ class = "user";
tty = NULL; /* This one is particularly sad, as this means that ssh sessions — even though usually
* associated with a pty — won't be tracked by their tty in logind. This is because ssh
* does the PAM session registration early for new connections, and registers a pty only