]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: rework the special casing we give root's sessions 30731/head
authorLennart Poettering <lennart@poettering.net>
Mon, 27 Nov 2023 17:19:50 +0000 (18:19 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 4 Jan 2024 15:11:16 +0000 (16:11 +0100)
Let's add an explicit session class "user-early" for this, so that
change of behaviour on logind is primarily bound to the "class"
property, and not some explicit root checks. This has the benefit that
we can be more fine grained with implying this class: only do so for tty
sessions, not others.

src/login/logind-session.c
src/login/logind-session.h
src/login/logind-user.c
src/login/pam_systemd.c

index 979e506897e8adfce2eeee418334ddc0821355ea..ed19129300eea2ee6fe4e72e6006d817494b0ad0 100644 (file)
@@ -743,7 +743,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er
                  * of STRV_IGNORE with strv_new() to skip these order constraints when needed. */
                 after = strv_new("systemd-logind.service",
                                  s->user->runtime_dir_service,
-                                 !uid_is_system(s->user->user_record->uid) ? "systemd-user-sessions.service" : STRV_IGNORE,
+                                 SESSION_CLASS_IS_EARLY(s->class) ? STRV_IGNORE : "systemd-user-sessions.service",
                                  s->user->service);
                 if (!after)
                         return log_oom();
@@ -1637,6 +1637,7 @@ DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
 
 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
         [SESSION_USER]        = "user",
+        [SESSION_USER_EARLY]  = "user-early",
         [SESSION_GREETER]     = "greeter",
         [SESSION_LOCK_SCREEN] = "lock-screen",
         [SESSION_BACKGROUND]  = "background",
index a947c8541a221ffd0c765caf58806709e6796e6b..f018cb30f90c84f24059c9788f29520ba364bc57 100644 (file)
@@ -21,6 +21,7 @@ typedef enum SessionState {
 
 typedef enum SessionClass {
         SESSION_USER,               /* A regular user session */
+        SESSION_USER_EARLY,         /* A user session, that is not ordered after systemd-user-sessions.service (i.e. for root) */
         SESSION_GREETER,            /* A login greeter pseudo-session */
         SESSION_LOCK_SCREEN,        /* A lock screen */
         SESSION_BACKGROUND,         /* Things like cron jobs, which are non-interactive */
@@ -28,6 +29,10 @@ typedef enum SessionClass {
         _SESSION_CLASS_INVALID = -EINVAL,
 } SessionClass;
 
+/* Whether we shall allow sessions of this class to run before 'systemd-user-sessions.service'. For now,
+ * there's only one class we allow this for. It's generally set for root sessions, but noone else. */
+#define SESSION_CLASS_IS_EARLY(class) ((class) == SESSION_USER_EARLY)
+
 typedef enum SessionType {
         SESSION_UNSPECIFIED,
         SESSION_TTY,
index 4e6b20eb11e85f0522c06c6a9244f616fdfc4479..2675fa7e93d4818756842c7471bf53f4ee56e14e 100644 (file)
@@ -782,6 +782,9 @@ static int elect_display_compare(Session *s1, Session *s2) {
         if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
                 return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
 
+        if ((s1->class != SESSION_USER_EARLY) != (s2->class != SESSION_USER_EARLY))
+                return (s1->class != SESSION_USER_EARLY) - (s2->class != SESSION_USER_EARLY);
+
         if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
                 return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
 
index 20ec5530d9a0ffabcbd6028fdc859009f8a912b1..297689203b0a5d6a5318cc60278f2bb7f46f5070 100644 (file)
@@ -1011,7 +1011,9 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                            !isempty(tty) ? "tty" : "unspecified";
 
         if (isempty(class))
-                class = streq(type, "unspecified") ? "background" : "user";
+                class = streq(type, "unspecified") ? "background" :
+                        ((IN_SET(user_record_disposition(ur), USER_INTRINSIC, USER_SYSTEM, USER_DYNAMIC) &&
+                         streq(type, "tty")) ? "user-early" : "user");
 
         remote = !isempty(remote_host) && !is_localhost(remote_host);