diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 58086305030..31c37d4e2be 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -36,6 +36,7 @@ #include "strv.h" #include "terminal-util.h" #include "tmpfile-util.h" +#include "uid-alloc-range.h" #include "user-util.h" #include "util.h" @@ -645,6 +646,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er assert(s->user); if (!s->scope) { + _cleanup_strv_free_ char **after = NULL; _cleanup_free_ char *scope = NULL; const char *description; @@ -656,6 +658,19 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er description = strjoina("Session ", s->id, " of User ", s->user->user_record->user_name); + /* We usually want to order session scopes after systemd-user-sessions.service since the + * latter unit is used as login session barrier for unprivileged users. However the barrier + * doesn't apply for root as sysadmin should always be able to log in (and without waiting + * for any timeout to expire) in case something goes wrong during the boot process. Since + * ordering after systemd-user-sessions.service and the user instance is optional we make use + * 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, + s->class != SESSION_BACKGROUND ? s->user->service : STRV_IGNORE); + if (!after) + return log_oom(); + r = manager_start_scope( s->manager, scope, @@ -665,11 +680,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er /* These two have StopWhenUnneeded= set, hence add a dep towards them */ STRV_MAKE(s->user->runtime_dir_service, s->class != SESSION_BACKGROUND ? s->user->service : NULL), - /* And order us after some more */ - STRV_MAKE("systemd-logind.service", - "systemd-user-sessions.service", - s->user->runtime_dir_service, - s->class != SESSION_BACKGROUND ? s->user->service : NULL), + after, user_record_home_directory(s->user->user_record), properties, error, diff --git a/units/meson.build b/units/meson.build index e8f81f22302..40f784ec683 100644 --- a/units/meson.build +++ b/units/meson.build @@ -312,6 +312,11 @@ meson.add_install_script('meson-add-wants.sh', add_wants) install_data('user-.slice.d/10-defaults.conf', install_dir : systemunitdir + '/user-.slice.d') +install_data('user@.service.d/10-login-barrier.conf', + install_dir : systemunitdir + '/user@.service.d') +install_data('user@0.service.d/10-login-barrier.conf', + install_dir : systemunitdir + '/user@0.service.d') + ############################################################ if install_sysconfdir diff --git a/units/user-.slice.d/10-defaults.conf b/units/user-.slice.d/10-defaults.conf index cb3651b728d..f688eac2304 100644 --- a/units/user-.slice.d/10-defaults.conf +++ b/units/user-.slice.d/10-defaults.conf @@ -10,7 +10,6 @@ [Unit] Description=User Slice of UID %j Documentation=man:user@.service(5) -After=systemd-user-sessions.service StopWhenUnneeded=yes [Slice] diff --git a/units/user-runtime-dir@.service.in b/units/user-runtime-dir@.service.in index 61becff2c63..73141733242 100644 --- a/units/user-runtime-dir@.service.in +++ b/units/user-runtime-dir@.service.in @@ -10,7 +10,7 @@ [Unit] Description=User Runtime Directory /run/user/%i Documentation=man:user@.service(5) -After=systemd-user-sessions.service dbus.service +After=dbus.service StopWhenUnneeded=yes IgnoreOnIsolate=yes diff --git a/units/user@.service.d/10-login-barrier.conf b/units/user@.service.d/10-login-barrier.conf new file mode 100644 index 00000000000..d88df10dbf4 --- /dev/null +++ b/units/user@.service.d/10-login-barrier.conf @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +# Make sure user instances are started after logins are allowed. However this +# is not desirable for user@0.service since root should be able to log in +# earlier during the boot process especially if something goes wrong. +After=systemd-user-sessions.service diff --git a/units/user@.service.in b/units/user@.service.in index eff0d5bcb6a..1660de03264 100644 --- a/units/user@.service.in +++ b/units/user@.service.in @@ -10,7 +10,7 @@ [Unit] Description=User Manager for UID %i Documentation=man:user@.service(5) -After=systemd-user-sessions.service user-runtime-dir@%i.service dbus.service +After=user-runtime-dir@%i.service dbus.service Requires=user-runtime-dir@%i.service IgnoreOnIsolate=yes diff --git a/units/user@0.service.d/10-login-barrier.conf b/units/user@0.service.d/10-login-barrier.conf new file mode 100644 index 00000000000..6f8ff43b799 --- /dev/null +++ b/units/user@0.service.d/10-login-barrier.conf @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# Empty file to mask its counterpart for unpriviledged users and thus cancels +# "After=systemd-user-session.service" ordering constraint so that root can log +# in even if the boot process is not yet finished.