diff --git a/SOURCES/0611-Added-option-check-inhibitors-for-non-tty-usage.patch b/SOURCES/0611-Added-option-check-inhibitors-for-non-tty-usage.patch
new file mode 100644
index 0000000..c913f65
--- /dev/null
+++ b/SOURCES/0611-Added-option-check-inhibitors-for-non-tty-usage.patch
@@ -0,0 +1,222 @@
+From f875436b93c6c5e83f46ab32429c977db4f0b10c Mon Sep 17 00:00:00 2001
+From: Felix Stupp <felix.stupp@outlook.com>
+Date: Thu, 29 Oct 2020 12:48:48 +0100
+Subject: [PATCH] Added option --check-inhibitors for non-tty usage
+
+As described in #2680, systemctl did ignore inhibitors if it is not
+attached to a tty to allow scripts to ignore inhibitors automatically.
+This pull request preserves this behavior but allows scripts to
+explicit check inhibitors if required.
+
+The new parameter '--check-inhibitors=yes' enables this feature.
+The old parameter '-i'/'--ignore-inhibitors' was deprecated in favor
+of '--check-inhibitors=no', the default behaviour can be specified
+with '--check-inhibitors=auto'.
+The new parameter is also described in the documentations and shell
+completions found here.
+
+(cherry picked from commit b8ebe378b49a31549b8531d4b3177095ef385d55)
+
+Related: #1269726
+---
+ man/systemctl.xml                  | 38 ++++++++++++++++++++----------
+ shell-completion/bash/systemctl.in |  7 ++++--
+ shell-completion/zsh/_systemctl.in |  9 ++++++-
+ src/systemctl/systemctl.c          | 37 +++++++++++++++++++++--------
+ 4 files changed, 65 insertions(+), 26 deletions(-)
+
+diff --git a/man/systemctl.xml b/man/systemctl.xml
+index ed60a0739f..9f0f4d46ea 100644
+--- a/man/systemctl.xml
++++ b/man/systemctl.xml
+@@ -323,23 +323,35 @@
+         </listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++        <term><option>--check-inhibitors=</option></term>
++
++        <listitem>
++          <para>When system shutdown or sleep state is request, this option controls how to deal with
++          inhibitor locks. It takes one of <literal>auto</literal>, <literal>yes</literal> or
++          <literal>no</literal>. Defaults to <literal>auto</literal>, which will behave like
++          <literal>yes</literal> for interactive invocations (i.e. from a TTY) and <literal>no</literal>
++          for non-interactive invocations.
++          <literal>yes</literal> will let the request respect inhibitor locks.
++          <literal>no</literal> will let the request ignore inhibitor locks.
++          </para>
++          <para>Applications can establish inhibitor locks to avoid that certain important operations
++          (such as CD burning or suchlike) are interrupted by system shutdown or a sleep state. Any user may
++          take these locks and privileged users may override these locks.
++          If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged)
++          and a list of active locks is printed.
++          However, if <literal>no</literal> is specified or <literal>auto</literal> is specified on a
++          non-interactive requests, the established locks are ignored and not shown, and the operation
++          attempted anyway, possibly requiring additional privileges.
++          May be overriden by <option>--force</option>.</para>
++        </listitem>
++      </varlistentry>
++
+       <varlistentry>
+         <term><option>-i</option></term>
+-        <term><option>--ignore-inhibitors</option></term>
+ 
+         <listitem>
+-          <para>When system shutdown or a sleep state is requested,
+-          ignore inhibitor locks. Applications can establish inhibitor
+-          locks to avoid that certain important operations (such as CD
+-          burning or suchlike) are interrupted by system shutdown or a
+-          sleep state. Any user may take these locks and privileged
+-          users may override these locks. If any locks are taken,
+-          shutdown and sleep state requests will normally fail
+-          (regardless of whether privileged or not) and a list of active locks
+-          is printed. However, if <option>--ignore-inhibitors</option>
+-          is specified, the locks are ignored and not printed, and the
+-          operation attempted anyway, possibly requiring additional
+-          privileges.</para>
++          <para>Shortcut for <option>--check-inhibitors=no</option>.</para>
+         </listitem>
+       </varlistentry>
+ 
+diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
+index ba51ae0d34..0c7afea57d 100644
+--- a/shell-completion/bash/systemctl.in
++++ b/shell-completion/bash/systemctl.in
+@@ -111,9 +111,9 @@ _systemctl () {
+                [STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
+                              --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall --now
+                              --quiet -q --system --user --version --runtime --recursive -r --firmware-setup
+-                             --show-types -i --ignore-inhibitors --plain --failed --value --fail --dry-run --wait'
++                             --show-types --plain --failed --value --fail --dry-run --wait'
+                       [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root
+-                             --preset-mode -n --lines -o --output -M --machine --message'
++                             --preset-mode -n --lines -o --output -M --machine --message --check-inhibitors'
+         )
+ 
+         if __contains_word "--user" ${COMP_WORDS[*]}; then
+@@ -163,6 +163,9 @@ _systemctl () {
+                         --machine|-M)
+                                 comps=$( __get_machines )
+                         ;;
++                        --check-inhibitors)
++                                comps='auto yes no'
++                        ;;
+                 esac
+                 COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+                 return 0
+diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
+index 9f576ed77d..b3c51cc843 100644
+--- a/shell-completion/zsh/_systemctl.in
++++ b/shell-completion/zsh/_systemctl.in
+@@ -363,6 +363,13 @@ _job_modes() {
+     _values -s , "${_modes[@]}"
+ }
+ 
++(( $+functions[_systemctl_check_inhibitors] )) ||
++    _systemctl_check_inhibitors() {
++        local -a _modes
++        _modes=(auto yes no)
++        _values -s , "${_modes[@]}"
++    }
++
+ # Build arguments for "systemctl" to be used in completion.
+ local -a _modes; _modes=("--user" "--system")
+ # Use the last mode (they are exclusive and the last one is used).
+@@ -380,7 +387,7 @@ _arguments -s \
+     '--before[Show units ordered before]' \
+     {-l,--full}"[Don't ellipsize unit names on output]" \
+     '--show-types[When showing sockets, show socket type]' \
+-    {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \
++    '--check-inhibitors[Specify if inhibitors should be checked]:mode:_systemctl_check_inhibitors' \
+     {-q,--quiet}'[Suppress output]' \
+     '--no-block[Do not wait until operation finished]' \
+     '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 8bec798373..8bcbf6bf4b 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -121,7 +121,7 @@ static bool arg_no_wall = false;
+ static bool arg_no_reload = false;
+ static bool arg_value = false;
+ static bool arg_show_types = false;
+-static bool arg_ignore_inhibitors = false;
++static int arg_check_inhibitors = -1;
+ static bool arg_dry_run = false;
+ static bool arg_quiet = false;
+ static bool arg_full = false;
+@@ -3313,17 +3313,19 @@ static int logind_check_inhibitors(enum action a) {
+         char **s;
+         int r;
+ 
+-        if (arg_ignore_inhibitors || arg_force > 0)
++        if (arg_check_inhibitors == 0 || arg_force > 0)
+                 return 0;
+ 
+         if (arg_when > 0)
+                 return 0;
+ 
+-        if (geteuid() == 0)
+-                return 0;
++        if (arg_check_inhibitors < 0) {
++                if (geteuid() == 0)
++                        return 0;
+ 
+-        if (!on_tty())
+-                return 0;
++                if (!on_tty())
++                        return 0;
++        }
+ 
+         if (arg_transport != BUS_TRANSPORT_LOCAL)
+                 return 0;
+@@ -7237,8 +7239,10 @@ static void systemctl_help(void) {
+                "                      When enqueuing a unit job, show full transaction\n"
+                "     --show-types     When showing sockets, explicitly show their type\n"
+                "     --value          When showing properties, only print the value\n"
+-               "  -i --ignore-inhibitors\n"
+-               "                      When shutting down or sleeping, ignore inhibitors\n"
++               "     --check-inhibitors=MODE\n"
++               "                      Specify if checking inhibitors before shutting down,\n"
++               "                      sleeping or hibernating\n"
++               "  -i                  Shortcut for --check-inhibitors=no\n"
+                "     --kill-who=WHO   Who to send signal to\n"
+                "  -s --signal=SIGNAL  Which signal to send\n"
+                "     --now            Start or stop unit in addition to enabling or disabling it\n"
+@@ -7475,6 +7479,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
+                 ARG_REVERSE,
+                 ARG_AFTER,
+                 ARG_BEFORE,
++                ARG_CHECK_INHIBITORS,
+                 ARG_DRY_RUN,
+                 ARG_SHOW_TYPES,
+                 ARG_IRREVERSIBLE,
+@@ -7520,7 +7525,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
+                 { "fail",                no_argument,       NULL, ARG_FAIL                }, /* compatibility only */
+                 { "irreversible",        no_argument,       NULL, ARG_IRREVERSIBLE        }, /* compatibility only */
+                 { "ignore-dependencies", no_argument,       NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
+-                { "ignore-inhibitors",   no_argument,       NULL, 'i'                     },
++                { "ignore-inhibitors",   no_argument,       NULL, 'i'                     }, /* compatibility only */
++                { "check-inhibitors",    required_argument, NULL, ARG_CHECK_INHIBITORS    },
+                 { "value",               no_argument,       NULL, ARG_VALUE               },
+                 { "user",                no_argument,       NULL, ARG_USER                },
+                 { "system",              no_argument,       NULL, ARG_SYSTEM              },
+@@ -7813,7 +7819,18 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
+                         break;
+ 
+                 case 'i':
+-                        arg_ignore_inhibitors = true;
++                        arg_check_inhibitors = 0;
++                        break;
++
++                case ARG_CHECK_INHIBITORS:
++                        if (streq(optarg, "auto"))
++                                arg_check_inhibitors = -1;
++                        else {
++                                r = parse_boolean(optarg);
++                                if (r < 0)
++                                        return log_error_errno(r, "Failed to parse --check-inhibitors= argument: %s", optarg);
++                                arg_check_inhibitors = r;
++                        }
+                         break;
+ 
+                 case ARG_PLAIN:
diff --git a/SOURCES/0612-logind-Introduce-RebootWithFlags-and-others.patch b/SOURCES/0612-logind-Introduce-RebootWithFlags-and-others.patch
new file mode 100644
index 0000000..fc9c119
--- /dev/null
+++ b/SOURCES/0612-logind-Introduce-RebootWithFlags-and-others.patch
@@ -0,0 +1,769 @@
+From d375206fe822903b16f3b9006ea47ffd938d88cb Mon Sep 17 00:00:00 2001
+From: Deepak Rawat <drawat.floss@gmail.com>
+Date: Mon, 25 Jan 2021 09:14:08 -0800
+Subject: [PATCH] logind: Introduce RebootWithFlags and others
+
+Add new systemd-logind WithFlags version for Reboot and others. These
+methods add a unit64 parameter, with which can send additional control flags.
+
+(cherry picked from commit 00971ea5164e2e7a5f2d7ffe12a566b62d282556)
+
+Related: #1269726
+---
+ src/basic/login-util.h      |   8 +
+ src/login/logind-dbus.c     | 498 +++++++++++++++++++++++++++++++-----
+ src/systemctl/systemctl.c   |  26 ++
+ src/systemd/sd-bus-vtable.h |  19 +-
+ 4 files changed, 480 insertions(+), 71 deletions(-)
+
+diff --git a/src/basic/login-util.h b/src/basic/login-util.h
+index e1e62e12b7..9832207458 100644
+--- a/src/basic/login-util.h
++++ b/src/basic/login-util.h
+@@ -4,6 +4,14 @@
+ #include <stdbool.h>
+ #include <unistd.h>
+ 
++#define SD_LOGIND_ROOT_CHECK_INHIBITORS           (UINT64_C(1) << 0)
++
++/* For internal use only */
++#define SD_LOGIND_INTERACTIVE                     (UINT64_C(1) << 63)
++
++#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS)
++#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_ALL    (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_INTERACTIVE)
++
+ bool session_id_valid(const char *id);
+ 
+ static inline bool logind_running(void) {
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index 3f122fcbd9..0c43fbb3e0 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -1698,14 +1698,14 @@ static int verify_shutdown_creds(
+                 Manager *m,
+                 sd_bus_message *message,
+                 InhibitWhat w,
+-                bool interactive,
+                 const char *action,
+                 const char *action_multiple_sessions,
+                 const char *action_ignore_inhibit,
++                uint64_t flags,
+                 sd_bus_error *error) {
+ 
+         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+-        bool multiple_sessions, blocked;
++        bool multiple_sessions, blocked, interactive;
+         uid_t uid;
+         int r;
+ 
+@@ -1728,6 +1728,7 @@ static int verify_shutdown_creds(
+ 
+         multiple_sessions = r > 0;
+         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
++        interactive = flags & SD_LOGIND_INTERACTIVE;
+ 
+         if (multiple_sessions && action_multiple_sessions) {
+                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
+@@ -1737,12 +1738,19 @@ static int verify_shutdown_creds(
+                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+         }
+ 
+-        if (blocked && action_ignore_inhibit) {
+-                r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
+-                if (r < 0)
+-                        return r;
+-                if (r == 0)
+-                        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
++        if (blocked) {
++                /* We don't check polkit for root here, because you can't be more privileged than root */
++                if (uid == 0 && (flags & SD_LOGIND_ROOT_CHECK_INHIBITORS))
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED,
++                                                 "Access denied to root due to active block inhibitor");
++
++                if (action_ignore_inhibit) {
++                        r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
++                        if (r < 0)
++                                return r;
++                        if (r == 0)
++                                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
++                }
+         }
+ 
+         if (!multiple_sessions && !blocked && action) {
+@@ -1765,9 +1773,11 @@ static int method_do_shutdown_or_sleep(
+                 const char *action_multiple_sessions,
+                 const char *action_ignore_inhibit,
+                 const char *sleep_verb,
++                bool with_flags,
+                 sd_bus_error *error) {
+ 
+-        int interactive, r;
++        int interactive = false, r;
++        uint64_t flags = 0;
+ 
+         assert(m);
+         assert(message);
+@@ -1775,10 +1785,20 @@ static int method_do_shutdown_or_sleep(
+         assert(w >= 0);
+         assert(w <= _INHIBIT_WHAT_MAX);
+ 
+-        r = sd_bus_message_read(message, "b", &interactive);
++        if (with_flags)
++                r = sd_bus_message_read(message, "t", &flags);
++        else
++                r = sd_bus_message_read(message, "b", &interactive);
++
+         if (r < 0)
+                 return r;
+ 
++        if (with_flags && (flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC))
++                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
++                                         "Invalid flags parameter");
++
++        SET_FLAG(flags, SD_LOGIND_INTERACTIVE, interactive);
++
+         /* Don't allow multiple jobs being executed at the same time */
+         if (m->action_what)
+                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
+@@ -1795,8 +1815,8 @@ static int method_do_shutdown_or_sleep(
+                         return r;
+         }
+ 
+-        r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
+-                                  action_ignore_inhibit, error);
++        r = verify_shutdown_creds(m, message, w, action, action_multiple_sessions,
++                                  action_ignore_inhibit, flags, error);
+         if (r != 0)
+                 return r;
+ 
+@@ -1818,6 +1838,7 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error
+                         "org.freedesktop.login1.power-off-multiple-sessions",
+                         "org.freedesktop.login1.power-off-ignore-inhibit",
+                         NULL,
++                        sd_bus_message_is_method_call(message, NULL, "PowerOffWithFlags"),
+                         error);
+ }
+ 
+@@ -1832,6 +1853,7 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
+                         "org.freedesktop.login1.reboot-multiple-sessions",
+                         "org.freedesktop.login1.reboot-ignore-inhibit",
+                         NULL,
++                        sd_bus_message_is_method_call(message, NULL, "RebootWithFlags"),
+                         error);
+ }
+ 
+@@ -1846,6 +1868,7 @@ static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *er
+                         "org.freedesktop.login1.halt-multiple-sessions",
+                         "org.freedesktop.login1.halt-ignore-inhibit",
+                         NULL,
++                        sd_bus_message_is_method_call(message, NULL, "HaltWithFlags"),
+                         error);
+ }
+ 
+@@ -1860,6 +1883,7 @@ static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error
+                         "org.freedesktop.login1.suspend-multiple-sessions",
+                         "org.freedesktop.login1.suspend-ignore-inhibit",
+                         "suspend",
++                        sd_bus_message_is_method_call(message, NULL, "SuspendWithFlags"),
+                         error);
+ }
+ 
+@@ -1874,6 +1898,7 @@ static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_erro
+                         "org.freedesktop.login1.hibernate-multiple-sessions",
+                         "org.freedesktop.login1.hibernate-ignore-inhibit",
+                         "hibernate",
++                        sd_bus_message_is_method_call(message, NULL, "HibernateWithFlags"),
+                         error);
+ }
+ 
+@@ -1888,6 +1913,7 @@ static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_e
+                         "org.freedesktop.login1.hibernate-multiple-sessions",
+                         "org.freedesktop.login1.hibernate-ignore-inhibit",
+                         "hybrid-sleep",
++                        sd_bus_message_is_method_call(message, NULL, "HybridSleepWithFlags"),
+                         error);
+ }
+ 
+@@ -1902,6 +1928,7 @@ static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata
+                         "org.freedesktop.login1.hibernate-multiple-sessions",
+                         "org.freedesktop.login1.hibernate-ignore-inhibit",
+                         "hybrid-sleep",
++                        sd_bus_message_is_method_call(message, NULL, "SuspendThenHibernateWithFlags"),
+                         error);
+ }
+ 
+@@ -2089,8 +2116,8 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
+         } else
+                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
+ 
+-        r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
+-                                  action, action_multiple_sessions, action_ignore_inhibit, error);
++        r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, action, action_multiple_sessions,
++                                  action_ignore_inhibit, 0, error);
+         if (r != 0)
+                 return r;
+ 
+@@ -2683,60 +2710,395 @@ const sd_bus_vtable manager_vtable[] = {
+         SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
+         SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+ 
+-        SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
+-        SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
+-        SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+-        SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
+-
+-        SD_BUS_SIGNAL("SessionNew", "so", 0),
+-        SD_BUS_SIGNAL("SessionRemoved", "so", 0),
+-        SD_BUS_SIGNAL("UserNew", "uo", 0),
+-        SD_BUS_SIGNAL("UserRemoved", "uo", 0),
+-        SD_BUS_SIGNAL("SeatNew", "so", 0),
+-        SD_BUS_SIGNAL("SeatRemoved", "so", 0),
+-        SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
+-        SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
++        SD_BUS_METHOD_WITH_NAMES("GetSession",
++                                 "s",
++                                 SD_BUS_PARAM(session_id),
++                                 "o",
++                                 SD_BUS_PARAM(object_path),
++                                 method_get_session,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("GetSessionByPID",
++                                 "u",
++                                 SD_BUS_PARAM(pid),
++                                 "o",
++                                 SD_BUS_PARAM(object_path),
++                                 method_get_session_by_pid,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("GetUser",
++                                 "u",
++                                 SD_BUS_PARAM(uid),
++                                 "o",
++                                 SD_BUS_PARAM(object_path),
++                                 method_get_user,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("GetUserByPID",
++                                 "u",
++                                 SD_BUS_PARAM(pid),
++                                 "o",
++                                 SD_BUS_PARAM(object_path),
++                                 method_get_user_by_pid,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("GetSeat",
++                                 "s",
++                                 SD_BUS_PARAM(seat_id),
++                                 "o",
++                                 SD_BUS_PARAM(object_path),
++                                 method_get_seat,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("ListSessions",
++                                 NULL,,
++                                 "a(susso)",
++                                 SD_BUS_PARAM(sessions),
++                                 method_list_sessions,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("ListUsers",
++                                 NULL,,
++                                 "a(uso)",
++                                 SD_BUS_PARAM(users),
++                                 method_list_users,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("ListSeats",
++                                 NULL,,
++                                 "a(so)",
++                                 SD_BUS_PARAM(seats),
++                                 method_list_seats,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("ListInhibitors",
++                                 NULL,,
++                                 "a(ssssuu)",
++                                 SD_BUS_PARAM(inhibitors),
++                                 method_list_inhibitors,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CreateSession",
++                                 "uusssssussbssa(sv)",
++                                 SD_BUS_PARAM(uid)
++                                 SD_BUS_PARAM(pid)
++                                 SD_BUS_PARAM(service)
++                                 SD_BUS_PARAM(type)
++                                 SD_BUS_PARAM(class)
++                                 SD_BUS_PARAM(desktop)
++                                 SD_BUS_PARAM(seat_id)
++                                 SD_BUS_PARAM(vtnr)
++                                 SD_BUS_PARAM(tty)
++                                 SD_BUS_PARAM(display)
++                                 SD_BUS_PARAM(remote)
++                                 SD_BUS_PARAM(remote_user)
++                                 SD_BUS_PARAM(remote_host)
++                                 SD_BUS_PARAM(properties),
++                                 "soshusub",
++                                 SD_BUS_PARAM(session_id)
++                                 SD_BUS_PARAM(object_path)
++                                 SD_BUS_PARAM(runtime_path)
++                                 SD_BUS_PARAM(fifo_fd)
++                                 SD_BUS_PARAM(uid)
++                                 SD_BUS_PARAM(seat_id)
++                                 SD_BUS_PARAM(vtnr)
++                                 SD_BUS_PARAM(existing),
++                                 method_create_session,
++                                 0),
++        SD_BUS_METHOD_WITH_NAMES("ReleaseSession",
++                                 "s",
++                                 SD_BUS_PARAM(session_id),
++                                 NULL,,
++                                 method_release_session,
++                                 0),
++        SD_BUS_METHOD_WITH_NAMES("ActivateSession",
++                                 "s",
++                                 SD_BUS_PARAM(session_id),
++                                 NULL,,
++                                 method_activate_session,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("ActivateSessionOnSeat",
++                                 "ss",
++                                 SD_BUS_PARAM(session_id)
++                                 SD_BUS_PARAM(seat_id),
++                                 NULL,,
++                                 method_activate_session_on_seat,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("LockSession",
++                                 "s",
++                                 SD_BUS_PARAM(session_id),
++                                 NULL,,
++                                 method_lock_session,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("UnlockSession",
++                                 "s",
++                                 SD_BUS_PARAM(session_id),
++                                 NULL,,
++                                 method_lock_session,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD("LockSessions",
++                      NULL,
++                      NULL,
++                      method_lock_sessions,
++                      SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD("UnlockSessions",
++                      NULL,
++                      NULL,
++                      method_lock_sessions,
++                      SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("KillSession",
++                                 "ssi",
++                                 SD_BUS_PARAM(session_id)
++                                 SD_BUS_PARAM(who)
++                                 SD_BUS_PARAM(signal_number),
++                                 NULL,,
++                                 method_kill_session,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("KillUser",
++                                 "ui",
++                                 SD_BUS_PARAM(uid)
++                                 SD_BUS_PARAM(signal_number),
++                                 NULL,,
++                                 method_kill_user,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("TerminateSession",
++                                 "s",
++                                 SD_BUS_PARAM(session_id),
++                                 NULL,,
++                                 method_terminate_session,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("TerminateUser",
++                                 "u",
++                                 SD_BUS_PARAM(uid),
++                                 NULL,,
++                                 method_terminate_user,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("TerminateSeat",
++                                 "s",
++                                 SD_BUS_PARAM(seat_id),
++                                 NULL,,
++                                 method_terminate_seat,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("SetUserLinger",
++                                 "ubb",
++                                 SD_BUS_PARAM(uid)
++                                 SD_BUS_PARAM(enable)
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_set_user_linger,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("AttachDevice",
++                                 "ssb",
++                                 SD_BUS_PARAM(seat_id)
++                                 SD_BUS_PARAM(sysfs_path)
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_attach_device,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("FlushDevices",
++                                 "b",
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_flush_devices,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("PowerOff",
++                                 "b",
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_poweroff,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("PowerOffWithFlags",
++                                 "t",
++                                 SD_BUS_PARAM(flags),
++                                 NULL,,
++                                 method_poweroff,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("Reboot",
++                                 "b",
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_reboot,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("RebootWithFlags",
++                                 "t",
++                                 SD_BUS_PARAM(flags),
++                                 NULL,,
++                                 method_reboot,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("Halt",
++                                 "b",
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_halt,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("HaltWithFlags",
++                                 "t",
++                                 SD_BUS_PARAM(flags),
++                                 NULL,,
++                                 method_halt,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("Suspend",
++                                 "b",
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_suspend,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("SuspendWithFlags",
++                                 "t",
++                                 SD_BUS_PARAM(flags),
++                                 NULL,,
++                                 method_suspend,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("Hibernate",
++                                 "b",
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_hibernate,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("HibernateWithFlags",
++                                 "t",
++                                 SD_BUS_PARAM(flags),
++                                 NULL,,
++                                 method_hibernate,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("HybridSleep",
++                                 "b",
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_hybrid_sleep,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("HybridSleepWithFlags",
++                                 "t",
++                                 SD_BUS_PARAM(flags),
++                                 NULL,,
++                                 method_hybrid_sleep,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("SuspendThenHibernate",
++                                 "b",
++                                 SD_BUS_PARAM(interactive),
++                                 NULL,,
++                                 method_suspend_then_hibernate,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("SuspendThenHibernateWithFlags",
++                                 "t",
++                                 SD_BUS_PARAM(flags),
++                                 NULL,,
++                                 method_suspend_then_hibernate,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CanPowerOff",
++                                 NULL,,
++                                 "s",
++                                 SD_BUS_PARAM(result),
++                                 method_can_poweroff,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CanReboot",
++                                 NULL,,
++                                 "s",
++                                 SD_BUS_PARAM(result),
++                                 method_can_reboot,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CanHalt",
++                                 NULL,,
++                                 "s",
++                                 SD_BUS_PARAM(result),
++                                 method_can_halt,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CanSuspend",
++                                 NULL,,
++                                 "s",
++                                 SD_BUS_PARAM(result),
++                                 method_can_suspend,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CanHibernate",
++                                 NULL,,
++                                 "s",
++                                 SD_BUS_PARAM(result),
++                                 method_can_hibernate,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CanHybridSleep",
++                                 NULL,,
++                                 "s",
++                                 SD_BUS_PARAM(result),
++                                 method_can_hybrid_sleep,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CanSuspendThenHibernate",
++                                 NULL,,
++                                 "s",
++                                 SD_BUS_PARAM(result),
++                                 method_can_suspend_then_hibernate,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("ScheduleShutdown",
++                                 "st",
++                                 SD_BUS_PARAM(type)
++                                 SD_BUS_PARAM(usec),
++                                 NULL,,
++                                 method_schedule_shutdown,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CancelScheduledShutdown",
++                                 NULL,,
++                                 "b",
++                                 SD_BUS_PARAM(cancelled),
++                                 method_cancel_scheduled_shutdown,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("Inhibit",
++                                 "ssss",
++                                 SD_BUS_PARAM(what)
++                                 SD_BUS_PARAM(who)
++                                 SD_BUS_PARAM(why)
++                                 SD_BUS_PARAM(mode),
++                                 "h",
++                                 SD_BUS_PARAM(pipe_fd),
++                                 method_inhibit,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("CanRebootToFirmwareSetup",
++                                 NULL,,
++                                 "s",
++                                 SD_BUS_PARAM(result),
++                                 method_can_reboot_to_firmware_setup,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("SetRebootToFirmwareSetup",
++                                 "b",
++                                 SD_BUS_PARAM(enable),
++                                 NULL,,
++                                 method_set_reboot_to_firmware_setup,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++        SD_BUS_METHOD_WITH_NAMES("SetWallMessage",
++                                 "sb",
++                                 SD_BUS_PARAM(wall_message)
++                                 SD_BUS_PARAM(enable),
++                                 NULL,,
++                                 method_set_wall_message,
++                                 SD_BUS_VTABLE_UNPRIVILEGED),
++
++        SD_BUS_SIGNAL_WITH_NAMES("SessionNew",
++                                 "so",
++                                 SD_BUS_PARAM(session_id)
++                                 SD_BUS_PARAM(object_path),
++                                 0),
++        SD_BUS_SIGNAL_WITH_NAMES("SessionRemoved",
++                                 "so",
++                                 SD_BUS_PARAM(session_id)
++                                 SD_BUS_PARAM(object_path),
++                                 0),
++        SD_BUS_SIGNAL_WITH_NAMES("UserNew",
++                                 "uo",
++                                 SD_BUS_PARAM(uid)
++                                 SD_BUS_PARAM(object_path),
++                                 0),
++        SD_BUS_SIGNAL_WITH_NAMES("UserRemoved",
++                                 "uo",
++                                 SD_BUS_PARAM(uid)
++                                 SD_BUS_PARAM(object_path),
++                                 0),
++        SD_BUS_SIGNAL_WITH_NAMES("SeatNew",
++                                 "so",
++                                 SD_BUS_PARAM(seat_id)
++                                 SD_BUS_PARAM(object_path),
++                                 0),
++        SD_BUS_SIGNAL_WITH_NAMES("SeatRemoved",
++                                 "so",
++                                 SD_BUS_PARAM(seat_id)
++                                 SD_BUS_PARAM(object_path),
++                                 0),
++        SD_BUS_SIGNAL_WITH_NAMES("PrepareForShutdown",
++                                 "b",
++                                 SD_BUS_PARAM(start),
++                                 0),
++        SD_BUS_SIGNAL_WITH_NAMES("PrepareForSleep",
++                                 "b",
++                                 SD_BUS_PARAM(start),
++                                 0),
+ 
+         SD_BUS_VTABLE_END
+ };
+diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
+index 8bcbf6bf4b..3dd7c1522f 100644
+--- a/src/systemctl/systemctl.c
++++ b/src/systemctl/systemctl.c
+@@ -50,6 +50,7 @@
+ #include "list.h"
+ #include "locale-util.h"
+ #include "log.h"
++#include "login-util.h"
+ #include "logs-show.h"
+ #include "macro.h"
+ #include "mkdir.h"
+@@ -3266,6 +3267,8 @@ static int logind_reboot(enum action a) {
+         };
+ 
+         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
++        const char *method_with_flags;
++        uint64_t flags = 0;
+         sd_bus *bus;
+         int r;
+ 
+@@ -3284,6 +3287,29 @@ static int logind_reboot(enum action a) {
+         if (arg_dry_run)
+                 return 0;
+ 
++        SET_FLAG(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS, arg_check_inhibitors > 0);
++
++        method_with_flags = strjoina(actions[a].method, "WithFlags");
++
++        r = sd_bus_call_method(
++                        bus,
++                        "org.freedesktop.login1",
++                        "/org/freedesktop/login1",
++                        "org.freedesktop.login1.Manager",
++                        method_with_flags,
++                        &error,
++                        NULL,
++                        "t", flags);
++        if (r >= 0)
++                return 0;
++
++        if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
++                return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
++
++        /* Fallback to original methods in case there is older version of systemd-logind */
++        log_debug("Method %s not available: %s. Falling back to %s", method_with_flags, bus_error_message(&error, r), actions[a].method);
++        sd_bus_error_free(&error);
++
+         r = sd_bus_call_method(
+                         bus,
+                         "org.freedesktop.login1",
+diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
+index 1268085498..8805e19477 100644
+--- a/src/systemd/sd-bus-vtable.h
++++ b/src/systemd/sd-bus-vtable.h
+@@ -65,10 +65,12 @@ struct sd_bus_vtable {
+                         const char *result;
+                         sd_bus_message_handler_t handler;
+                         size_t offset;
++                        const char *names;
+                 } method;
+                 struct {
+                         const char *member;
+                         const char *signature;
++                        const char *names;
+                 } signal;
+                 struct {
+                         const char *member;
+@@ -91,7 +93,10 @@ struct sd_bus_vtable {
+                 },                                                      \
+         }
+ 
+-#define SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, _offset, _flags)   \
++/* helper macro to format method and signal parameters, one at a time */
++#define SD_BUS_PARAM(x) #x "\0"
++
++#define SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, _in_names, _result, _out_names, _handler, _offset, _flags) \
+         {                                                               \
+                 .type = _SD_BUS_VTABLE_METHOD,                          \
+                 .flags = _flags,                                        \
+@@ -102,13 +107,18 @@ struct sd_bus_vtable {
+                         .result = _result,                              \
+                         .handler = _handler,                            \
+                         .offset = _offset,                              \
++                        .names = _in_names _out_names,                  \
+                     },                                                  \
+                 },                                                      \
+         }
++#define SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, _offset, _flags)   \
++        SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, "", _result, "", _handler, _offset, _flags)
++#define SD_BUS_METHOD_WITH_NAMES(_member, _signature, _in_names, _result, _out_names, _handler, _flags)   \
++        SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, _in_names, _result, _out_names, _handler, 0, _flags)
+ #define SD_BUS_METHOD(_member, _signature, _result, _handler, _flags)   \
+-        SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, 0, _flags)
++        SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, "", _result, "", _handler, 0, _flags)
+ 
+-#define SD_BUS_SIGNAL(_member, _signature, _flags)                      \
++#define SD_BUS_SIGNAL_WITH_NAMES(_member, _signature, _out_names, _flags)                      \
+         {                                                               \
+                 .type = _SD_BUS_VTABLE_SIGNAL,                          \
+                 .flags = _flags,                                        \
+@@ -116,9 +126,12 @@ struct sd_bus_vtable {
+                     .signal = {                                         \
+                         .member = _member,                              \
+                         .signature = _signature,                        \
++                        .names = _out_names,                            \
+                     },                                                  \
+                 },                                                      \
+         }
++#define SD_BUS_SIGNAL(_member, _signature, _flags)   \
++        SD_BUS_SIGNAL_WITH_NAMES(_member, _signature, "", _flags)
+ 
+ #define SD_BUS_PROPERTY(_member, _signature, _get, _offset, _flags)     \
+         {                                                               \
diff --git a/SOURCES/0613-logind-add-WithFlags-methods-to-policy.patch b/SOURCES/0613-logind-add-WithFlags-methods-to-policy.patch
new file mode 100644
index 0000000..753c9d9
--- /dev/null
+++ b/SOURCES/0613-logind-add-WithFlags-methods-to-policy.patch
@@ -0,0 +1,85 @@
+From e1b18ab36b2457a4896e531f03713b198725c919 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 9 Mar 2021 09:03:58 +0100
+Subject: [PATCH] =?UTF-8?q?logind:=20add=20=E2=80=A6WithFlags=20methods=20?=
+ =?UTF-8?q?to=20policy?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Without this, privilege escalation through polkit does not work, because all
+methods fail with permission errors.
+
+Forgotten in 8885fed4e3a52cf1bf105e42043203c485ed9d92.
+Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1933335.
+
+(cherry picked from commit 2280db756eaff795091871feee8e47d4f6989a58)
+
+Related: #1269726
+---
+ src/login/org.freedesktop.login1.conf | 28 +++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
+index f880f3e2da..dcde0c22c6 100644
+--- a/src/login/org.freedesktop.login1.conf
++++ b/src/login/org.freedesktop.login1.conf
+@@ -130,30 +130,58 @@
+                        send_interface="org.freedesktop.login1.Manager"
+                        send_member="PowerOff"/>
+ 
++                <allow send_destination="org.freedesktop.login1"
++                       send_interface="org.freedesktop.login1.Manager"
++                       send_member="PowerOffWithFlags"/>
++
+                 <allow send_destination="org.freedesktop.login1"
+                        send_interface="org.freedesktop.login1.Manager"
+                        send_member="Reboot"/>
+ 
++                <allow send_destination="org.freedesktop.login1"
++                       send_interface="org.freedesktop.login1.Manager"
++                       send_member="RebootWithFlags"/>
++
+                 <allow send_destination="org.freedesktop.login1"
+                        send_interface="org.freedesktop.login1.Manager"
+                        send_member="Halt"/>
+ 
++                <allow send_destination="org.freedesktop.login1"
++                       send_interface="org.freedesktop.login1.Manager"
++                       send_member="HaltWithFlags"/>
++
+                 <allow send_destination="org.freedesktop.login1"
+                        send_interface="org.freedesktop.login1.Manager"
+                        send_member="Suspend"/>
+ 
++                <allow send_destination="org.freedesktop.login1"
++                       send_interface="org.freedesktop.login1.Manager"
++                       send_member="SuspendWithFlags"/>
++
+                 <allow send_destination="org.freedesktop.login1"
+                        send_interface="org.freedesktop.login1.Manager"
+                        send_member="Hibernate"/>
+ 
++                <allow send_destination="org.freedesktop.login1"
++                       send_interface="org.freedesktop.login1.Manager"
++                       send_member="HibernateWithFlags"/>
++
+                 <allow send_destination="org.freedesktop.login1"
+                        send_interface="org.freedesktop.login1.Manager"
+                        send_member="HybridSleep"/>
+ 
++                <allow send_destination="org.freedesktop.login1"
++                       send_interface="org.freedesktop.login1.Manager"
++                       send_member="HybridSleepWithFlags"/>
++
+                 <allow send_destination="org.freedesktop.login1"
+                        send_interface="org.freedesktop.login1.Manager"
+                        send_member="SuspendThenHibernate"/>
+ 
++                <allow send_destination="org.freedesktop.login1"
++                       send_interface="org.freedesktop.login1.Manager"
++                       send_member="SuspendThenHibernateWithFlags"/>
++
+                 <allow send_destination="org.freedesktop.login1"
+                        send_interface="org.freedesktop.login1.Manager"
+                        send_member="CanPowerOff"/>
diff --git a/SOURCES/0614-logind-simplify-flags-handling-a-bit.patch b/SOURCES/0614-logind-simplify-flags-handling-a-bit.patch
new file mode 100644
index 0000000..fb61d3c
--- /dev/null
+++ b/SOURCES/0614-logind-simplify-flags-handling-a-bit.patch
@@ -0,0 +1,72 @@
+From 6751217a032dd1a8e8ee324332f29786265f0ebe Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 2 Feb 2021 15:27:30 +0100
+Subject: [PATCH] logind: simplify flags handling a bit
+
+Let's split out the two codepaths a bit, and emphasize which ones it the
+new-style and which the old-style codepath, and let's clearly convert
+the params of the old-stye into the new style for further processing, so
+that the old style path is brief and isolated.
+
+No change in behaviour.
+
+Follow-up for: 8885fed4e3a52cf1bf105e42043203c485ed9d92
+
+(cherry picked from commit d3e99bc0c7f785dcf4e73cfed12f74002e73be5f)
+
+Related: #1269726
+---
+ src/login/logind-dbus.c | 30 ++++++++++++++++++------------
+ 1 file changed, 18 insertions(+), 12 deletions(-)
+
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index 0c43fbb3e0..ae9abc9bce 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -1776,8 +1776,8 @@ static int method_do_shutdown_or_sleep(
+                 bool with_flags,
+                 sd_bus_error *error) {
+ 
+-        int interactive = false, r;
+-        uint64_t flags = 0;
++        uint64_t flags;
++        int r;
+ 
+         assert(m);
+         assert(message);
+@@ -1785,19 +1785,25 @@ static int method_do_shutdown_or_sleep(
+         assert(w >= 0);
+         assert(w <= _INHIBIT_WHAT_MAX);
+ 
+-        if (with_flags)
++        if (with_flags) {
++                /* New style method: with flags parameter (and interactive bool in the bus message header) */
+                 r = sd_bus_message_read(message, "t", &flags);
+-        else
+-                r = sd_bus_message_read(message, "b", &interactive);
+-
+-        if (r < 0)
+-                return r;
++                if (r < 0)
++                        return r;
++                if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
++        } else {
++                /* Old style method: no flags parameter, but interactive bool passed as boolean in
++                 * payload. Let's convert this argument to the new-style flags parameter for our internal
++                 * use. */
++                int interactive;
+ 
+-        if (with_flags && (flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC))
+-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+-                                         "Invalid flags parameter");
++                r = sd_bus_message_read(message, "b", &interactive);
++                if (r < 0)
++                        return r;
+ 
+-        SET_FLAG(flags, SD_LOGIND_INTERACTIVE, interactive);
++                flags = interactive ? SD_LOGIND_INTERACTIVE : 0;
++        }
+ 
+         /* Don't allow multiple jobs being executed at the same time */
+         if (m->action_what)
diff --git a/SOURCES/0615-Update-link-to-RHEL-documentation.patch b/SOURCES/0615-Update-link-to-RHEL-documentation.patch
new file mode 100644
index 0000000..922b826
--- /dev/null
+++ b/SOURCES/0615-Update-link-to-RHEL-documentation.patch
@@ -0,0 +1,25 @@
+From 48b893c770aed3214586d529ddaba14267818c33 Mon Sep 17 00:00:00 2001
+From: David Tardon <dtardon@redhat.com>
+Date: Thu, 15 Jul 2021 10:35:08 +0200
+Subject: [PATCH] Update link to RHEL documentation
+
+RHEL-only
+
+Resolves: #1982584
+---
+ man/systemctl.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/man/systemctl.xml b/man/systemctl.xml
+index 9f0f4d46ea..a71e6c7c4f 100644
+--- a/man/systemctl.xml
++++ b/man/systemctl.xml
+@@ -2017,7 +2017,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
+     <para>
+             For examples how to use systemctl in comparsion
+             with old service and chkconfig command please see:
+-            <ulink url="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/managing-services-with-systemd_configuring-basic-system-settings">
++            <ulink url="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/managing-system-services-with-systemctl_configuring-basic-system-settings">
+                     Managing System Services
+             </ulink>
+     </para>
diff --git a/SOURCES/0616-Set-default-core-ulimit-to-0-but-keep-the-hard-limit.patch b/SOURCES/0616-Set-default-core-ulimit-to-0-but-keep-the-hard-limit.patch
new file mode 100644
index 0000000..a1893a2
--- /dev/null
+++ b/SOURCES/0616-Set-default-core-ulimit-to-0-but-keep-the-hard-limit.patch
@@ -0,0 +1,29 @@
+From e2f5e8ccb27f48717b50339f58582d70ad5f59b1 Mon Sep 17 00:00:00 2001
+From: Frantisek Sumsal <fsumsal@redhat.com>
+Date: Tue, 3 Aug 2021 11:52:36 +0200
+Subject: [PATCH] Set default core ulimit to 0, but keep the hard limit
+ ulimited
+
+so users can change it later.
+
+Follow-up to 830bd662276ee117e65a4b3d541f77e8b172eafd.
+
+rhel-only
+Resolves: #1905582
+---
+ src/core/system.conf.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/system.conf.in b/src/core/system.conf.in
+index b4d6dfa15a..84246c0e36 100644
+--- a/src/core/system.conf.in
++++ b/src/core/system.conf.in
+@@ -52,7 +52,7 @@
+ #DefaultLimitFSIZE=
+ #DefaultLimitDATA=
+ #DefaultLimitSTACK=
+-DefaultLimitCORE=0
++DefaultLimitCORE=0:infinity
+ #DefaultLimitRSS=
+ #DefaultLimitNOFILE=
+ #DefaultLimitAS=
diff --git a/SOURCES/0617-shared-seccomp-util-address-family-filtering-is-brok.patch b/SOURCES/0617-shared-seccomp-util-address-family-filtering-is-brok.patch
new file mode 100644
index 0000000..f3f13ad
--- /dev/null
+++ b/SOURCES/0617-shared-seccomp-util-address-family-filtering-is-brok.patch
@@ -0,0 +1,76 @@
+From 3cf73fa4599116da350a0100378e749bbcbcad37 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Thu, 26 Nov 2020 11:23:54 +0100
+Subject: [PATCH] shared/seccomp-util: address family filtering is broken on
+ ppc
+
+This reverts the gist of da1921a5c396547261c8c7fcd94173346eb3b718 and
+0d9fca76bb69e162265b2d25cb79f1890c0da31b (for ppc).
+
+Quoting #17559:
+> libseccomp 2.5 added socket syscall multiplexing on ppc64(el):
+> https://github.com/seccomp/libseccomp/pull/229
+>
+> Like with i386, s390 and s390x this breaks socket argument filtering, so
+> RestrictAddressFamilies doesn't work.
+>
+> This causes the unit test to fail:
+> /* test_restrict_address_families */
+> Operating on architecture: ppc
+> Failed to install socket family rules for architecture ppc, skipping: Operation canceled
+> Operating on architecture: ppc64
+> Failed to add socket() rule for architecture ppc64, skipping: Invalid argument
+> Operating on architecture: ppc64-le
+> Failed to add socket() rule for architecture ppc64-le, skipping: Invalid argument
+> Assertion 'fd < 0' failed at src/test/test-seccomp.c:424, function test_restrict_address_families(). Aborting.
+>
+> The socket filters can't be added so `socket(AF_UNIX, SOCK_DGRAM, 0);` still
+> works, triggering the assertion.
+
+Fixes #17559.
+
+(cherry picked from commit d5923e38bc0e6cf9d7620ed5f1f8606fe7fe1168)
+
+Resolves: #1982650
+---
+ src/shared/seccomp-util.c | 6 +++---
+ src/test/test-seccomp.c   | 2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
+index e903512d45..c57c409433 100644
+--- a/src/shared/seccomp-util.c
++++ b/src/shared/seccomp-util.c
+@@ -1251,9 +1251,6 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
+                 case SCMP_ARCH_X32:
+                 case SCMP_ARCH_ARM:
+                 case SCMP_ARCH_AARCH64:
+-                case SCMP_ARCH_PPC:
+-                case SCMP_ARCH_PPC64:
+-                case SCMP_ARCH_PPC64LE:
+                 case SCMP_ARCH_MIPSEL64N32:
+                 case SCMP_ARCH_MIPS64N32:
+                 case SCMP_ARCH_MIPSEL64:
+@@ -1267,6 +1264,9 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
+                 case SCMP_ARCH_X86:
+                 case SCMP_ARCH_MIPSEL:
+                 case SCMP_ARCH_MIPS:
++                case SCMP_ARCH_PPC:
++                case SCMP_ARCH_PPC64:
++                case SCMP_ARCH_PPC64LE:
+                 default:
+                         /* These we either know we don't support (i.e. are the ones that do use socketcall()), or we
+                          * don't know */
+diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
+index 009a2e1922..5eb1c78b8b 100644
+--- a/src/test/test-seccomp.c
++++ b/src/test/test-seccomp.c
+@@ -25,7 +25,7 @@
+ #include "util.h"
+ #include "virt.h"
+ 
+-#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__)
++#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) || defined(__powerpc64__) || defined(__powerpc__)
+ /* On these archs, socket() is implemented via the socketcall() syscall multiplexer,
+  * and we can't restrict it hence via seccomp. */
+ #  define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1
diff --git a/SOURCES/0618-logind-rework-Seat-Session-User-object-allocation-an.patch b/SOURCES/0618-logind-rework-Seat-Session-User-object-allocation-an.patch
new file mode 100644
index 0000000..bddc651
--- /dev/null
+++ b/SOURCES/0618-logind-rework-Seat-Session-User-object-allocation-an.patch
@@ -0,0 +1,341 @@
+From 019b3a5d7530c51aa8f7f1e5f5cb5eb81113d4db Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 3 Aug 2018 18:53:09 +0200
+Subject: [PATCH] logind: rework Seat/Session/User object allocation and
+ freeing a bit
+
+Let's update things a bit to follow current practices:
+
+- User structure initialization rather than zero-initialized allocation
+
+- Always propagate proper errors from allocation functions
+
+- Use _cleanup_ for freeing objects when allocation fails half-way
+
+- Make destructors return NULL
+
+(cherry picked from commit 8c29a4570993105fecc12288596d2ee77c7f82b8)
+
+Related: #1642460
+---
+ src/login/logind-core.c    | 14 ++++++----
+ src/login/logind-seat.c    | 38 +++++++++++++++----------
+ src/login/logind-seat.h    |  6 ++--
+ src/login/logind-session.c | 57 +++++++++++++++++++++-----------------
+ src/login/logind-session.h |  7 +++--
+ src/login/logind-user.c    | 21 +++++++-------
+ 6 files changed, 83 insertions(+), 60 deletions(-)
+
+diff --git a/src/login/logind-core.c b/src/login/logind-core.c
+index cff5536ac0..f598bbaa1c 100644
+--- a/src/login/logind-core.c
++++ b/src/login/logind-core.c
+@@ -88,15 +88,16 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_dev
+ 
+ int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
+         Seat *s;
++        int r;
+ 
+         assert(m);
+         assert(id);
+ 
+         s = hashmap_get(m->seats, id);
+         if (!s) {
+-                s = seat_new(m, id);
+-                if (!s)
+-                        return -ENOMEM;
++                r = seat_new(&s, m, id);
++                if (r < 0)
++                        return r;
+         }
+ 
+         if (_seat)
+@@ -107,15 +108,16 @@ int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
+ 
+ int manager_add_session(Manager *m, const char *id, Session **_session) {
+         Session *s;
++        int r;
+ 
+         assert(m);
+         assert(id);
+ 
+         s = hashmap_get(m->sessions, id);
+         if (!s) {
+-                s = session_new(m, id);
+-                if (!s)
+-                        return -ENOMEM;
++                r = session_new(&s, m, id);
++                if (r < 0)
++                        return r;
+         }
+ 
+         if (_session)
+diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
+index 63253db5bf..f68fc0ceaa 100644
+--- a/src/login/logind-seat.c
++++ b/src/login/logind-seat.c
+@@ -21,33 +21,42 @@
+ #include "terminal-util.h"
+ #include "util.h"
+ 
+-Seat *seat_new(Manager *m, const char *id) {
+-        Seat *s;
++int seat_new(Seat** ret, Manager *m, const char *id) {
++        _cleanup_(seat_freep) Seat *s = NULL;
++        int r;
+ 
++        assert(ret);
+         assert(m);
+         assert(id);
+ 
+-        s = new0(Seat, 1);
++        if (!seat_name_is_valid(id))
++                return -EINVAL;
++
++        s = new(Seat, 1);
+         if (!s)
+-                return NULL;
++                return -ENOMEM;
++
++        *s = (Seat) {
++                .manager = m,
++        };
+ 
+         s->state_file = strappend("/run/systemd/seats/", id);
+         if (!s->state_file)
+-                return mfree(s);
++                return -ENOMEM;
+ 
+         s->id = basename(s->state_file);
+-        s->manager = m;
+ 
+-        if (hashmap_put(m->seats, s->id, s) < 0) {
+-                free(s->state_file);
+-                return mfree(s);
+-        }
++        r = hashmap_put(m->seats, s->id, s);
++        if (r < 0)
++                return r;
+ 
+-        return s;
++        *ret = TAKE_PTR(s);
++        return 0;
+ }
+ 
+-void seat_free(Seat *s) {
+-        assert(s);
++Seat* seat_free(Seat *s) {
++        if (!s)
++                return NULL;
+ 
+         if (s->in_gc_queue)
+                 LIST_REMOVE(gc_queue, s->manager->seat_gc_queue, s);
+@@ -64,7 +73,8 @@ void seat_free(Seat *s) {
+ 
+         free(s->positions);
+         free(s->state_file);
+-        free(s);
++
++        return mfree(s);
+ }
+ 
+ int seat_save(Seat *s) {
+diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h
+index 70878bbe52..51cd468e26 100644
+--- a/src/login/logind-seat.h
++++ b/src/login/logind-seat.h
+@@ -27,8 +27,10 @@ struct Seat {
+         LIST_FIELDS(Seat, gc_queue);
+ };
+ 
+-Seat *seat_new(Manager *m, const char *id);
+-void seat_free(Seat *s);
++int seat_new(Seat **ret, Manager *m, const char *id);
++Seat* seat_free(Seat *s);
++
++DEFINE_TRIVIAL_CLEANUP_FUNC(Seat *, seat_free);
+ 
+ int seat_save(Seat *s);
+ int seat_load(Seat *s);
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index 69d5a10319..5621d59a41 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -24,57 +24,61 @@
+ #include "mkdir.h"
+ #include "parse-util.h"
+ #include "path-util.h"
++#include "process-util.h"
+ #include "string-table.h"
+ #include "terminal-util.h"
+ #include "user-util.h"
+ #include "util.h"
+-#include "process-util.h"
+ 
+ #define RELEASE_USEC (20*USEC_PER_SEC)
+ 
+ static void session_remove_fifo(Session *s);
+ 
+-Session* session_new(Manager *m, const char *id) {
+-        Session *s;
++int session_new(Session **ret, Manager *m, const char *id) {
++        _cleanup_(session_freep) Session *s = NULL;
++        int r;
+ 
++        assert(ret);
+         assert(m);
+         assert(id);
+-        assert(session_id_valid(id));
+ 
+-        s = new0(Session, 1);
++        if (!session_id_valid(id))
++                return -EINVAL;
++
++        s = new(Session, 1);
+         if (!s)
+-                return NULL;
++                return -ENOMEM;
++
++        *s = (Session) {
++                .manager = m,
++                .fifo_fd = -1,
++                .vtfd = -1,
++                .audit_id = AUDIT_SESSION_INVALID,
++        };
+ 
+         s->state_file = strappend("/run/systemd/sessions/", id);
+         if (!s->state_file)
+-                return mfree(s);
+-
+-        s->devices = hashmap_new(&devt_hash_ops);
+-        if (!s->devices) {
+-                free(s->state_file);
+-                return mfree(s);
+-        }
++                return -ENOMEM;
+ 
+         s->id = basename(s->state_file);
+ 
+-        if (hashmap_put(m->sessions, s->id, s) < 0) {
+-                hashmap_free(s->devices);
+-                free(s->state_file);
+-                return mfree(s);
+-        }
++        s->devices = hashmap_new(&devt_hash_ops);
++        if (!s->devices)
++                return -ENOMEM;
+ 
+-        s->manager = m;
+-        s->fifo_fd = -1;
+-        s->vtfd = -1;
+-        s->audit_id = AUDIT_SESSION_INVALID;
++        r = hashmap_put(m->sessions, s->id, s);
++        if (r < 0)
++                return r;
+ 
+-        return s;
++        *ret = TAKE_PTR(s);
++        return 0;
+ }
+ 
+-void session_free(Session *s) {
++Session* session_free(Session *s) {
+         SessionDevice *sd;
+ 
+-        assert(s);
++        if (!s)
++                return NULL;
+ 
+         if (s->in_gc_queue)
+                 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
+@@ -126,7 +130,8 @@ void session_free(Session *s) {
+         hashmap_remove(s->manager->sessions, s->id);
+ 
+         free(s->state_file);
+-        free(s);
++
++        return mfree(s);
+ }
+ 
+ void session_set_user(Session *s, User *u) {
+diff --git a/src/login/logind-session.h b/src/login/logind-session.h
+index 29ca399daf..572f2545c1 100644
+--- a/src/login/logind-session.h
++++ b/src/login/logind-session.h
+@@ -109,8 +109,11 @@ struct Session {
+         LIST_FIELDS(Session, gc_queue);
+ };
+ 
+-Session *session_new(Manager *m, const char *id);
+-void session_free(Session *s);
++int session_new(Session **ret, Manager *m, const char *id);
++Session* session_free(Session *s);
++
++DEFINE_TRIVIAL_CLEANUP_FUNC(Session *, session_free);
++
+ void session_set_user(Session *s, User *u);
+ bool session_may_gc(Session *s, bool drop_not_started);
+ void session_add_to_gc_queue(Session *s);
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 56b8066f12..60ccd62abb 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -30,23 +30,24 @@
+ #include "user-util.h"
+ #include "util.h"
+ 
+-int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
++int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
+         _cleanup_(user_freep) User *u = NULL;
+         char lu[DECIMAL_STR_MAX(uid_t) + 1];
+         int r;
+ 
+-        assert(out);
++        assert(ret);
+         assert(m);
+         assert(name);
+ 
+-        u = new0(User, 1);
++        u = new(User, 1);
+         if (!u)
+                 return -ENOMEM;
+ 
+-        u->manager = m;
+-        u->uid = uid;
+-        u->gid = gid;
+-        xsprintf(lu, UID_FMT, uid);
++        *u = (User) {
++                .manager = m,
++                .uid = uid,
++                .gid = gid,
++        };
+ 
+         u->name = strdup(name);
+         if (!u->name)
+@@ -58,6 +59,7 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
+         if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0)
+                 return -ENOMEM;
+ 
++        xsprintf(lu, UID_FMT, uid);
+         r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
+         if (r < 0)
+                 return r;
+@@ -78,8 +80,7 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
+         if (r < 0)
+                 return r;
+ 
+-        *out = TAKE_PTR(u);
+-
++        *ret = TAKE_PTR(u);
+         return 0;
+ }
+ 
+@@ -272,7 +273,7 @@ int user_save(User *u) {
+         if (!u->started)
+                 return 0;
+ 
+-        return user_save_internal (u);
++        return user_save_internal(u);
+ }
+ 
+ int user_load(User *u) {
diff --git a/SOURCES/0619-logind-fix-serialization-deserialization-of-user-s-d.patch b/SOURCES/0619-logind-fix-serialization-deserialization-of-user-s-d.patch
new file mode 100644
index 0000000..7639b30
--- /dev/null
+++ b/SOURCES/0619-logind-fix-serialization-deserialization-of-user-s-d.patch
@@ -0,0 +1,116 @@
+From 0314e68fe961cec941b1b0eb1cbcca4546cfdfdb Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 3 Aug 2018 19:04:35 +0200
+Subject: [PATCH] logind: fix serialization/deserialization of user's "display
+ session"
+
+Previously this was serialized as part of the user object. This didn't
+work however, as we load users first, and sessions seconds and hence
+referencing a session from the user load logic cannot work.
+
+Fix this by storing an IS_DISPLAY property along with each session, and
+make the session with this set display session when it is loaded.
+
+(cherry picked from commit 1c8280fd47b6561d35b15b3b6d49bdeacf891bfd)
+
+Related: #1642460
+---
+ src/login/logind-session.c | 18 +++++++++++++++++-
+ src/login/logind-user.c    | 18 ++++--------------
+ 2 files changed, 21 insertions(+), 15 deletions(-)
+
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index 5621d59a41..0afb065b2b 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -184,11 +184,13 @@ int session_save(Session *s) {
+                 "UID="UID_FMT"\n"
+                 "USER=%s\n"
+                 "ACTIVE=%i\n"
++                "IS_DISPLAY=%i\n"
+                 "STATE=%s\n"
+                 "REMOTE=%i\n",
+                 s->user->uid,
+                 s->user->name,
+                 session_is_active(s),
++                s->user->display == s,
+                 session_state_to_string(session_get_state(s)),
+                 s->remote);
+ 
+@@ -359,7 +361,8 @@ int session_load(Session *s) {
+                 *monotonic = NULL,
+                 *controller = NULL,
+                 *active = NULL,
+-                *devices = NULL;
++                *devices = NULL,
++                *is_display = NULL;
+ 
+         int k, r;
+ 
+@@ -389,6 +392,7 @@ int session_load(Session *s) {
+                            "CONTROLLER",     &controller,
+                            "ACTIVE",         &active,
+                            "DEVICES",        &devices,
++                           "IS_DISPLAY",     &is_display,
+                            NULL);
+ 
+         if (r < 0)
+@@ -496,6 +500,18 @@ int session_load(Session *s) {
+                         s->was_active = k;
+         }
+ 
++        if (is_display) {
++                /* Note that when enumerating users are loaded before sessions, hence the display session to use is
++                 * something we have to store along with the session and not the user, as in that case we couldn't
++                 * apply it at the time we load the user. */
++
++                k = parse_boolean(is_display);
++                if (k < 0)
++                        log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m");
++                else if (k > 0)
++                        s->user->display = s;
++        }
++
+         if (controller) {
+                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
+                         session_set_controller(s, controller, false, false);
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 60ccd62abb..17ed361411 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -277,8 +277,7 @@ int user_save(User *u) {
+ }
+ 
+ int user_load(User *u) {
+-        _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
+-        Session *s = NULL;
++        _cleanup_free_ char *realtime = NULL, *monotonic = NULL;
+         int r;
+ 
+         assert(u);
+@@ -286,22 +285,13 @@ int user_load(User *u) {
+         r = parse_env_file(NULL, u->state_file, NEWLINE,
+                            "SERVICE_JOB", &u->service_job,
+                            "SLICE_JOB",   &u->slice_job,
+-                           "DISPLAY",     &display,
+                            "REALTIME",    &realtime,
+                            "MONOTONIC",   &monotonic,
+                            NULL);
+-        if (r < 0) {
+-                if (r == -ENOENT)
+-                        return 0;
+-
++        if (r == -ENOENT)
++                return 0;
++        if (r < 0)
+                 return log_error_errno(r, "Failed to read %s: %m", u->state_file);
+-        }
+-
+-        if (display)
+-                s = hashmap_get(u->manager->sessions, display);
+-
+-        if (s && s->display && display_is_local(s->display))
+-                u->display = s;
+ 
+         if (realtime)
+                 timestamp_deserialize(realtime, &u->timestamp.realtime);
diff --git a/SOURCES/0620-logind-turn-of-stdio-locking-when-writing-session-fi.patch b/SOURCES/0620-logind-turn-of-stdio-locking-when-writing-session-fi.patch
new file mode 100644
index 0000000..93c7244
--- /dev/null
+++ b/SOURCES/0620-logind-turn-of-stdio-locking-when-writing-session-fi.patch
@@ -0,0 +1,39 @@
+From 3eab0f1b64477792bd01ca52c3eb26ce64c5c7ba Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 3 Aug 2018 20:18:55 +0200
+Subject: [PATCH] logind: turn of stdio locking when writing session files too
+
+This just copies what we already do for user and seat files to session
+files.
+
+(cherry picked from commit 44176400138e18d9087e0864ca97041416a90d47)
+
+Related: #1642460
+---
+ src/login/logind-session.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index 0afb065b2b..960a24d1a7 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -5,6 +5,7 @@
+ #include <linux/kd.h>
+ #include <linux/vt.h>
+ #include <signal.h>
++#include <stdio_ext.h>
+ #include <string.h>
+ #include <sys/ioctl.h>
+ #include <unistd.h>
+@@ -175,9 +176,8 @@ int session_save(Session *s) {
+         if (r < 0)
+                 goto fail;
+ 
+-        assert(s->user);
+-
+-        fchmod(fileno(f), 0644);
++        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
++        (void) fchmod(fileno(f), 0644);
+ 
+         fprintf(f,
+                 "# This is private data. Do not parse.\n"
diff --git a/SOURCES/0621-units-set-StopWhenUnneeded-for-the-user-slice-units-.patch b/SOURCES/0621-units-set-StopWhenUnneeded-for-the-user-slice-units-.patch
new file mode 100644
index 0000000..4b9bb79
--- /dev/null
+++ b/SOURCES/0621-units-set-StopWhenUnneeded-for-the-user-slice-units-.patch
@@ -0,0 +1,27 @@
+From f94c1bbec9e2c3efcbafd61ea1fdf8dbc3245d1b Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 3 Aug 2018 20:19:38 +0200
+Subject: [PATCH] units: set StopWhenUnneeded= for the user slice units too
+
+We'd like them to go away, just like the user-runtime-dir@.service when
+they aren't needed anymore.
+
+(cherry picked from commit 1007473b49b5aaeef0e53cd4a15f4ed8cf721926)
+
+Related: #1642460
+---
+ units/user-.slice.d/10-defaults.conf | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/units/user-.slice.d/10-defaults.conf b/units/user-.slice.d/10-defaults.conf
+index efc9d37c8e..1147e7aed9 100644
+--- a/units/user-.slice.d/10-defaults.conf
++++ b/units/user-.slice.d/10-defaults.conf
+@@ -10,6 +10,7 @@
+ [Unit]
+ Description=User Slice of UID %j
+ After=systemd-user-sessions.service
++StopWhenUnneeded=yes
+ 
+ [Slice]
+ TasksMax=80%
diff --git a/SOURCES/0622-units-improve-Description-string-a-bit.patch b/SOURCES/0622-units-improve-Description-string-a-bit.patch
new file mode 100644
index 0000000..dff8053
--- /dev/null
+++ b/SOURCES/0622-units-improve-Description-string-a-bit.patch
@@ -0,0 +1,29 @@
+From 50a4e03d2da89df32f2f63eb56051d789508ae75 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 6 Aug 2018 18:15:07 +0200
+Subject: [PATCH] units: improve Description= string a bit
+
+Let's not use the word "wrapper", as it's not clear what that is, and in
+some way any unit file is a "wrapper"... let's simply say that it's
+about the runtime directory.
+
+(cherry picked from commit 14df094a51e87013d96ac697ae4f14593cbcad39)
+
+Related: #1642460
+---
+ units/user-runtime-dir@.service.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/units/user-runtime-dir@.service.in b/units/user-runtime-dir@.service.in
+index bfd6488d61..63db1cca6a 100644
+--- a/units/user-runtime-dir@.service.in
++++ b/units/user-runtime-dir@.service.in
+@@ -8,7 +8,7 @@
+ #  (at your option) any later version.
+ 
+ [Unit]
+-Description=/run/user/%i mount wrapper
++Description=User runtime directory /run/user/%i
+ After=systemd-user-sessions.service
+ StopWhenUnneeded=yes
+ 
diff --git a/SOURCES/0623-logind-improve-logging-in-manager_connect_console.patch b/SOURCES/0623-logind-improve-logging-in-manager_connect_console.patch
new file mode 100644
index 0000000..6a30f47
--- /dev/null
+++ b/SOURCES/0623-logind-improve-logging-in-manager_connect_console.patch
@@ -0,0 +1,77 @@
+From 9e9c6cbbdd60f4538cee041ffe3f9cd831c5de17 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 3 Aug 2018 20:21:27 +0200
+Subject: [PATCH] logind: improve logging in manager_connect_console()
+
+let's make sure we log about every failure
+
+Also, complain about systems where /dev/tty0 exists but
+/sys/class/tty/tty0/active does not. Such systems (usually container
+environments) are pretty broken as they mount something that is not a VC
+to /dev/tty0 and they really shouldn't.
+
+Systems should either have a VC or not, but not badly fake one by
+mounting things wildly.
+
+This just adds a warning message, as before we'll simply turn off VC
+handling in this case.
+
+(cherry picked from commit 0b6d55cae9b8adc507fbea95d1b2874729a77386)
+
+Related: #1642460
+---
+ src/login/logind.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/src/login/logind.c b/src/login/logind.c
+index 52fcee933c..1b366cd55f 100644
+--- a/src/login/logind.c
++++ b/src/login/logind.c
+@@ -815,28 +815,28 @@ static int manager_connect_console(Manager *m) {
+         assert(m);
+         assert(m->console_active_fd < 0);
+ 
+-        /* On certain architectures (S390 and Xen, and containers),
+-           /dev/tty0 does not exist, so don't fail if we can't open
+-           it. */
++        /* On certain systems (such as S390, Xen, and containers) /dev/tty0 does not exist (as there is no VC), so
++         * don't fail if we can't open it. */
++
+         if (access("/dev/tty0", F_OK) < 0)
+                 return 0;
+ 
+         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
+         if (m->console_active_fd < 0) {
+ 
+-                /* On some systems the device node /dev/tty0 may exist
+-                 * even though /sys/class/tty/tty0 does not. */
+-                if (errno == ENOENT)
++                /* On some systems /dev/tty0 may exist even though /sys/class/tty/tty0 does not. These are broken, but
++                 * common. Let's complain but continue anyway. */
++                if (errno == ENOENT) {
++                        log_warning_errno(errno, "System has /dev/tty0 but not /sys/class/tty/tty0/active which is broken, ignoring: %m");
+                         return 0;
++                }
+ 
+                 return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
+         }
+ 
+         r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
+-        if (r < 0) {
+-                log_error("Failed to watch foreground console");
+-                return r;
+-        }
++        if (r < 0)
++                return log_error_errno(r, "Failed to watch foreground console: %m");
+ 
+         /*
+          * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
+@@ -855,7 +855,7 @@ static int manager_connect_console(Manager *m) {
+ 
+         r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
+         if (r < 0)
+-                return r;
++                return log_error_errno(r, "Failed to subscribe to signal: %m");
+ 
+         return 0;
+ }
diff --git a/SOURCES/0624-logind-save-restore-User-object-s-stopping-field-dur.patch b/SOURCES/0624-logind-save-restore-User-object-s-stopping-field-dur.patch
new file mode 100644
index 0000000..d640d09
--- /dev/null
+++ b/SOURCES/0624-logind-save-restore-User-object-s-stopping-field-dur.patch
@@ -0,0 +1,90 @@
+From 4703c08fe3a8bfa1bc9b893e8bde365b1cbeffd9 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 6 Aug 2018 18:14:11 +0200
+Subject: [PATCH] logind: save/restore User object's "stopping" field during
+ restarts
+
+Whether we are stopping or not is highly relevant, hence don't forget it
+across restarts.
+
+(cherry picked from commit d865bc024bf28c17120d7322a81e9a99997a59f6)
+
+Related: #1642460
+---
+ src/login/logind-user.c | 20 +++++++++++++++-----
+ src/login/logind-user.h |  5 +++--
+ 2 files changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 17ed361411..35b2ca5489 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -136,9 +136,11 @@ static int user_save_internal(User *u) {
+         fprintf(f,
+                 "# This is private data. Do not parse.\n"
+                 "NAME=%s\n"
+-                "STATE=%s\n",
++                "STATE=%s\n"         /* friendly user-facing state */
++                "STOPPING=%s\n",     /* low-level state */
+                 u->name,
+-                user_state_to_string(user_get_state(u)));
++                user_state_to_string(user_get_state(u)),
++                yes_no(u->stopping));
+ 
+         /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
+         if (u->runtime_path)
+@@ -277,14 +279,14 @@ int user_save(User *u) {
+ }
+ 
+ int user_load(User *u) {
+-        _cleanup_free_ char *realtime = NULL, *monotonic = NULL;
++        _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL;
+         int r;
+ 
+         assert(u);
+ 
+         r = parse_env_file(NULL, u->state_file, NEWLINE,
+                            "SERVICE_JOB", &u->service_job,
+-                           "SLICE_JOB",   &u->slice_job,
++                           "STOPPING",    &stopping,
+                            "REALTIME",    &realtime,
+                            "MONOTONIC",   &monotonic,
+                            NULL);
+@@ -293,12 +295,20 @@ int user_load(User *u) {
+         if (r < 0)
+                 return log_error_errno(r, "Failed to read %s: %m", u->state_file);
+ 
++        if (stopping) {
++                r = parse_boolean(stopping);
++                if (r < 0)
++                        log_debug_errno(r, "Failed to parse 'STOPPING' boolean: %s", stopping);
++                else
++                        u->stopping = r;
++        }
++
+         if (realtime)
+                 timestamp_deserialize(realtime, &u->timestamp.realtime);
+         if (monotonic)
+                 timestamp_deserialize(monotonic, &u->timestamp.monotonic);
+ 
+-        return r;
++        return 0;
+ }
+ 
+ static int user_start_service(User *u) {
+diff --git a/src/login/logind-user.h b/src/login/logind-user.h
+index eba2325284..03e020b870 100644
+--- a/src/login/logind-user.h
++++ b/src/login/logind-user.h
+@@ -36,8 +36,9 @@ struct User {
+         dual_timestamp timestamp;
+ 
+         bool in_gc_queue:1;
+-        bool started:1;
+-        bool stopping:1;
++
++        bool started:1;       /* Whenever the user being started, has been started or is being stopped again. */
++        bool stopping:1;      /* Whenever the user is being stopped or has been stopped. */
+ 
+         LIST_HEAD(Session, sessions);
+         LIST_FIELDS(User, gc_queue);
diff --git a/SOURCES/0625-logind-correct-bad-clean-up-path.patch b/SOURCES/0625-logind-correct-bad-clean-up-path.patch
new file mode 100644
index 0000000..90740cc
--- /dev/null
+++ b/SOURCES/0625-logind-correct-bad-clean-up-path.patch
@@ -0,0 +1,25 @@
+From eebbeada76b0fa4e252ecf4e25b088733636fe89 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 6 Aug 2018 18:19:45 +0200
+Subject: [PATCH] logind: correct bad clean-up path
+
+(cherry picked from commit d88ffeeeefda4c3447223fd36f8e30f23c931e48)
+
+Related: #1642460
+---
+ src/login/logind-dbus.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index ae9abc9bce..4b2c418453 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -845,7 +845,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
+ 
+         r = sd_bus_message_enter_container(message, 'a', "(sv)");
+         if (r < 0)
+-                return r;
++                goto fail;
+ 
+         r = session_start(session, message);
+         if (r < 0)
diff --git a/SOURCES/0626-logind-fix-bad-error-propagation.patch b/SOURCES/0626-logind-fix-bad-error-propagation.patch
new file mode 100644
index 0000000..1a07e78
--- /dev/null
+++ b/SOURCES/0626-logind-fix-bad-error-propagation.patch
@@ -0,0 +1,25 @@
+From 7662d7c86d1fbb01693d4eb008fa27bf1e0030a9 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 6 Aug 2018 18:21:37 +0200
+Subject: [PATCH] logind: fix bad error propagation
+
+(cherry picked from commit cce08496e7353e3e9903b42695aba3f9d259b90a)
+
+Related: #1642460
+---
+ src/login/logind-seat.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
+index f68fc0ceaa..9e4f009643 100644
+--- a/src/login/logind-seat.c
++++ b/src/login/logind-seat.c
+@@ -175,7 +175,7 @@ static int vt_allocate(unsigned int vtnr) {
+         xsprintf(p, "/dev/tty%u", vtnr);
+         fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
+         if (fd < 0)
+-                return -errno;
++                return fd;
+ 
+         return 0;
+ }
diff --git a/SOURCES/0627-logind-never-elect-a-session-that-is-stopping-as-dis.patch b/SOURCES/0627-logind-never-elect-a-session-that-is-stopping-as-dis.patch
new file mode 100644
index 0000000..145c425
--- /dev/null
+++ b/SOURCES/0627-logind-never-elect-a-session-that-is-stopping-as-dis.patch
@@ -0,0 +1,42 @@
+From 35f9a7f8f4e8917725349fe764706658c02537ca Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 6 Aug 2018 19:02:29 +0200
+Subject: [PATCH] logind: never elect a session that is stopping as display
+
+(cherry picked from commit 04857cd801022d9f9933efb484c6253572f09870)
+
+Related: #1642460
+---
+ src/login/logind-user.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 35b2ca5489..3e4c99bdbd 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -613,11 +613,10 @@ int user_kill(User *u, int signo) {
+ }
+ 
+ static bool elect_display_filter(Session *s) {
+-        /* Return true if the session is a candidate for the user’s ‘primary
+-         * session’ or ‘display’. */
++        /* Return true if the session is a candidate for the user’s ‘primary session’ or ‘display’. */
+         assert(s);
+ 
+-        return (s->class == SESSION_USER && !s->stopping);
++        return s->class == SESSION_USER && s->started && !s->stopping;
+ }
+ 
+ static int elect_display_compare(Session *s1, Session *s2) {
+@@ -663,9 +662,8 @@ void user_elect_display(User *u) {
+ 
+         assert(u);
+ 
+-        /* This elects a primary session for each user, which we call
+-         * the "display". We try to keep the assignment stable, but we
+-         * "upgrade" to better choices. */
++        /* This elects a primary session for each user, which we call the "display". We try to keep the assignment
++         * stable, but we "upgrade" to better choices. */
+         log_debug("Electing new display for user %s", u->name);
+ 
+         LIST_FOREACH(sessions_by_user, s, u->sessions) {
diff --git a/SOURCES/0628-logind-introduce-little-helper-that-checks-whether-a.patch b/SOURCES/0628-logind-introduce-little-helper-that-checks-whether-a.patch
new file mode 100644
index 0000000..d50750b
--- /dev/null
+++ b/SOURCES/0628-logind-introduce-little-helper-that-checks-whether-a.patch
@@ -0,0 +1,60 @@
+From 83c49a5e54dffc3dfa85b79f6375cd0a42a4ff76 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 6 Aug 2018 19:34:39 +0200
+Subject: [PATCH] logind: introduce little helper that checks whether a session
+ is ready
+
+(cherry picked from commit b1951bc83ffbbb92ba4de7b9cba845421c2f35b1)
+
+Related: #1642460
+---
+ src/login/logind-session-dbus.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
+index 88a2d33dc8..03585b7f8e 100644
+--- a/src/login/logind-session-dbus.c
++++ b/src/login/logind-session-dbus.c
+@@ -704,6 +704,15 @@ int session_send_lock_all(Manager *m, bool lock) {
+         return r;
+ }
+ 
++static bool session_ready(Session *s) {
++        assert(s);
++
++        /* Returns true when the session is ready, i.e. all jobs we enqueued for it are done (regardless if successful or not) */
++
++        return !s->scope_job &&
++                !s->user->service_job;
++}
++
+ int session_send_create_reply(Session *s, sd_bus_error *error) {
+         _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
+         _cleanup_close_ int fifo_fd = -1;
+@@ -711,14 +720,13 @@ int session_send_create_reply(Session *s, sd_bus_error *error) {
+ 
+         assert(s);
+ 
+-        /* This is called after the session scope and the user service
+-         * were successfully created, and finishes where
++        /* This is called after the session scope and the user service were successfully created, and finishes where
+          * bus_manager_create_session() left off. */
+ 
+         if (!s->create_message)
+                 return 0;
+ 
+-        if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
++        if (!sd_bus_error_is_set(error) && !session_ready(s))
+                 return 0;
+ 
+         c = s->create_message;
+@@ -731,8 +739,7 @@ int session_send_create_reply(Session *s, sd_bus_error *error) {
+         if (fifo_fd < 0)
+                 return fifo_fd;
+ 
+-        /* Update the session state file before we notify the client
+-         * about the result. */
++        /* Update the session state file before we notify the client about the result. */
+         session_save(s);
+ 
+         p = session_bus_path(s);
diff --git a/SOURCES/0629-logind-propagate-session-stop-errors.patch b/SOURCES/0629-logind-propagate-session-stop-errors.patch
new file mode 100644
index 0000000..feed8cb
--- /dev/null
+++ b/SOURCES/0629-logind-propagate-session-stop-errors.patch
@@ -0,0 +1,40 @@
+From 31aa21a13f9b91486b1a95c5b73fa088af77fcb4 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 6 Aug 2018 19:35:44 +0200
+Subject: [PATCH] logind: propagate session stop errors
+
+Let's propagate errors from stopping sessions via seat_stop(). This is
+similar to how we propagate such errors in user_stop() for all sessions
+associated with a user.
+
+Note that we propagate these errors, but we don't abort the function.
+
+(cherry picked from commit e6958b7ea33813b085966ac25817a957c0dad7f9)
+
+Related: #1642460
+---
+ src/login/logind-seat.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
+index 9e4f009643..96c34a6c9e 100644
+--- a/src/login/logind-seat.c
++++ b/src/login/logind-seat.c
+@@ -431,7 +431,7 @@ int seat_start(Seat *s) {
+ }
+ 
+ int seat_stop(Seat *s, bool force) {
+-        int r = 0;
++        int r;
+ 
+         assert(s);
+ 
+@@ -441,7 +441,7 @@ int seat_stop(Seat *s, bool force) {
+                            "SEAT_ID=%s", s->id,
+                            LOG_MESSAGE("Removed seat %s.", s->id));
+ 
+-        seat_stop_sessions(s, force);
++        r = seat_stop_sessions(s, force);
+ 
+         unlink(s->state_file);
+         seat_add_to_gc_queue(s);
diff --git a/SOURCES/0630-logind-rework-how-we-manage-the-slice-and-user-runti.patch b/SOURCES/0630-logind-rework-how-we-manage-the-slice-and-user-runti.patch
new file mode 100644
index 0000000..7880086
--- /dev/null
+++ b/SOURCES/0630-logind-rework-how-we-manage-the-slice-and-user-runti.patch
@@ -0,0 +1,618 @@
+From a05c1077911652954c8b9e82cfdc0fc643eca782 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Mon, 6 Aug 2018 21:44:45 +0200
+Subject: [PATCH] logind: rework how we manage the slice and
+ user-runtime-dir@.service unit for each user
+
+Instead of managing it explicitly, let's simplify things and rely on
+regular Wants=/Requires= dependencies to pull in these units from
+user@.service and the session scope, and StopWhenUneeded= to stop these
+auxiliary units again. This way, they can be pulled in easily by
+unrelated units too.
+
+This simplifies things quite a bit: for each session we now only need to
+manage the session scope, and for each user the user@.service, the other
+units are not something we need to manage anymore.
+
+This patch also makes sure that if user@.service of a user is masked we
+will continue to work, and user-runtime-dir@.service will still be
+correctly pulled in, as it is now a dependency of the scope unit.
+
+Fixes: #9461
+Replaces: #5546
+(cherry picked from commit 25a1ab4ed48b72e974f77a68dcbe3521014787bb)
+
+Related: #1642460
+---
+ src/login/logind-dbus.c    |  58 ++++++++--------
+ src/login/logind-session.c |  64 ++++++++++--------
+ src/login/logind-session.h |   2 +-
+ src/login/logind-user.c    | 134 ++++++++++++++-----------------------
+ src/login/logind-user.h    |   7 +-
+ src/login/logind.c         |   2 +-
+ src/login/logind.h         |   2 +-
+ 7 files changed, 123 insertions(+), 146 deletions(-)
+
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index 4b2c418453..7eba617fff 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -847,7 +847,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
+         if (r < 0)
+                 goto fail;
+ 
+-        r = session_start(session, message);
++        r = session_start(session, message, error);
+         if (r < 0)
+                 goto fail;
+ 
+@@ -3110,24 +3110,20 @@ const sd_bus_vtable manager_vtable[] = {
+ };
+ 
+ static int session_jobs_reply(Session *s, const char *unit, const char *result) {
+-        int r = 0;
+-
+         assert(s);
+         assert(unit);
+ 
+         if (!s->started)
+-                return r;
++                return 0;
+ 
+-        if (streq(result, "done"))
+-                r = session_send_create_reply(s, NULL);
+-        else {
++        if (result && !streq(result, "done")) {
+                 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
+ 
+-                sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
+-                r = session_send_create_reply(s, &e);
++                sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit '%s' failed with '%s'", unit, result);
++                return session_send_create_reply(s, &e);
+         }
+ 
+-        return r;
++        return session_send_create_reply(s, NULL);
+ }
+ 
+ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+@@ -3160,30 +3156,29 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
+         }
+ 
+         session = hashmap_get(m->session_units, unit);
+-        if (session && streq_ptr(path, session->scope_job)) {
+-                session->scope_job = mfree(session->scope_job);
+-                session_jobs_reply(session, unit, result);
++        if (session) {
++                if (streq_ptr(path, session->scope_job)) {
++                        session->scope_job = mfree(session->scope_job);
++                        (void) session_jobs_reply(session, unit, result);
++
++                        session_save(session);
++                        user_save(session->user);
++                }
+ 
+-                session_save(session);
+-                user_save(session->user);
+                 session_add_to_gc_queue(session);
+         }
+ 
+         user = hashmap_get(m->user_units, unit);
+-        if (user &&
+-            (streq_ptr(path, user->service_job) ||
+-             streq_ptr(path, user->slice_job))) {
+-
+-                if (streq_ptr(path, user->service_job))
++        if (user) {
++                if (streq_ptr(path, user->service_job)) {
+                         user->service_job = mfree(user->service_job);
+ 
+-                if (streq_ptr(path, user->slice_job))
+-                        user->slice_job = mfree(user->slice_job);
++                        LIST_FOREACH(sessions_by_user, session, user->sessions)
++                                (void) session_jobs_reply(session, unit, NULL /* don't propagate user service failures to the client */);
+ 
+-                LIST_FOREACH(sessions_by_user, session, user->sessions)
+-                        session_jobs_reply(session, unit, result);
++                        user_save(user);
++                }
+ 
+-                user_save(user);
+                 user_add_to_gc_queue(user);
+         }
+ 
+@@ -3315,13 +3310,14 @@ int manager_start_scope(
+                 pid_t pid,
+                 const char *slice,
+                 const char *description,
+-                const char *after,
+-                const char *after2,
++                char **wants,
++                char **after,
+                 sd_bus_message *more_properties,
+                 sd_bus_error *error,
+                 char **job) {
+ 
+         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
++        char **i;
+         int r;
+ 
+         assert(manager);
+@@ -3359,14 +3355,14 @@ int manager_start_scope(
+                         return r;
+         }
+ 
+-        if (!isempty(after)) {
+-                r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
++        STRV_FOREACH(i, wants) {
++                r = sd_bus_message_append(m, "(sv)", "Wants", "as", 1, *i);
+                 if (r < 0)
+                         return r;
+         }
+ 
+-        if (!isempty(after2)) {
+-                r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
++        STRV_FOREACH(i, after) {
++                r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i);
+                 if (r < 0)
+                         return r;
+         }
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index 960a24d1a7..d56b48a732 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -27,6 +27,7 @@
+ #include "path-util.h"
+ #include "process-util.h"
+ #include "string-table.h"
++#include "strv.h"
+ #include "terminal-util.h"
+ #include "user-util.h"
+ #include "util.h"
+@@ -560,17 +561,18 @@ int session_activate(Session *s) {
+         return 0;
+ }
+ 
+-static int session_start_scope(Session *s, sd_bus_message *properties) {
++static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_error *error) {
+         int r;
+ 
+         assert(s);
+         assert(s->user);
+ 
+         if (!s->scope) {
+-                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+-                char *scope, *job = NULL;
++                _cleanup_free_ char *scope = NULL;
+                 const char *description;
+ 
++                s->scope_job = mfree(s->scope_job);
++
+                 scope = strjoin("session-", s->id, ".scope");
+                 if (!scope)
+                         return log_oom();
+@@ -583,21 +585,15 @@ static int session_start_scope(Session *s, sd_bus_message *properties) {
+                                 s->leader,
+                                 s->user->slice,
+                                 description,
+-                                "systemd-logind.service",
+-                                "systemd-user-sessions.service",
++                                STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */
++                                STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */
+                                 properties,
+-                                &error,
+-                                &job);
+-                if (r < 0) {
+-                        log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r));
+-                        free(scope);
+-                        return r;
+-                } else {
+-                        s->scope = scope;
++                                error,
++                                &s->scope_job);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(error, r));
+ 
+-                        free(s->scope_job);
+-                        s->scope_job = job;
+-                }
++                s->scope = TAKE_PTR(scope);
+         }
+ 
+         if (s->scope)
+@@ -606,7 +602,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties) {
+         return 0;
+ }
+ 
+-int session_start(Session *s, sd_bus_message *properties) {
++int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
+         int r;
+ 
+         assert(s);
+@@ -614,6 +610,9 @@ int session_start(Session *s, sd_bus_message *properties) {
+         if (!s->user)
+                 return -ESTALE;
+ 
++        if (s->stopping)
++                return -EINVAL;
++
+         if (s->started)
+                 return 0;
+ 
+@@ -621,8 +620,7 @@ int session_start(Session *s, sd_bus_message *properties) {
+         if (r < 0)
+                 return r;
+ 
+-        /* Create cgroup */
+-        r = session_start_scope(s, properties);
++        r = session_start_scope(s, properties, error);
+         if (r < 0)
+                 return r;
+ 
+@@ -673,21 +671,24 @@ static int session_stop_scope(Session *s, bool force) {
+          * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
+          * when killing any processes left after this point. */
+         r = manager_abandon_scope(s->manager, s->scope, &error);
+-        if (r < 0)
++        if (r < 0) {
+                 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
++                sd_bus_error_free(&error);
++        }
++
++        s->scope_job = mfree(s->scope_job);
+ 
+         /* Optionally, let's kill everything that's left now. */
+         if (force || manager_shall_kill(s->manager, s->user->name)) {
+-                char *job = NULL;
+ 
+-                r = manager_stop_unit(s->manager, s->scope, &error, &job);
+-                if (r < 0)
+-                        return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
++                r = manager_stop_unit(s->manager, s->scope, &error, &s->scope_job);
++                if (r < 0) {
++                        if (force)
++                                return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
+ 
+-                free(s->scope_job);
+-                s->scope_job = job;
++                        log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r));
++                }
+         } else {
+-                s->scope_job = mfree(s->scope_job);
+ 
+                 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
+                  * Therefore session stop and session removal may be two distinct events.
+@@ -707,8 +708,17 @@ int session_stop(Session *s, bool force) {
+ 
+         assert(s);
+ 
++        /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API
++         * request via the bus (either directly for the session object or for the seat or user object this session
++         * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the
++         * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */
++
+         if (!s->user)
+                 return -ESTALE;
++        if (!s->started)
++                return 0;
++        if (s->stopping)
++                return 0;
+ 
+         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+ 
+diff --git a/src/login/logind-session.h b/src/login/logind-session.h
+index 572f2545c1..7d17d9a25f 100644
+--- a/src/login/logind-session.h
++++ b/src/login/logind-session.h
+@@ -124,7 +124,7 @@ void session_set_idle_hint(Session *s, bool b);
+ int session_get_locked_hint(Session *s);
+ void session_set_locked_hint(Session *s, bool b);
+ int session_create_fifo(Session *s);
+-int session_start(Session *s, sd_bus_message *properties);
++int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error);
+ int session_stop(Session *s, bool force);
+ int session_finalize(Session *s);
+ int session_release(Session *s);
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 3e4c99bdbd..39fc76f4dc 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -68,6 +68,10 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
+         if (r < 0)
+                 return r;
+ 
++        r = unit_name_build("user-runtime-dir", lu, ".service", &u->runtime_dir_service);
++        if (r < 0)
++                return r;
++
+         r = hashmap_put(m->users, UID_TO_PTR(uid), u);
+         if (r < 0)
+                 return r;
+@@ -80,6 +84,10 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
+         if (r < 0)
+                 return r;
+ 
++        r = hashmap_put(m->user_units, u->runtime_dir_service, u);
++        if (r < 0)
++                return r;
++
+         *ret = TAKE_PTR(u);
+         return 0;
+ }
+@@ -97,15 +105,18 @@ User *user_free(User *u) {
+         if (u->service)
+                 hashmap_remove_value(u->manager->user_units, u->service, u);
+ 
++        if (u->runtime_dir_service)
++                hashmap_remove_value(u->manager->user_units, u->runtime_dir_service, u);
++
+         if (u->slice)
+                 hashmap_remove_value(u->manager->user_units, u->slice, u);
+ 
+         hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u);
+ 
+-        u->slice_job = mfree(u->slice_job);
+         u->service_job = mfree(u->service_job);
+ 
+         u->service = mfree(u->service);
++        u->runtime_dir_service = mfree(u->runtime_dir_service);
+         u->slice = mfree(u->slice);
+         u->runtime_path = mfree(u->runtime_path);
+         u->state_file = mfree(u->state_file);
+@@ -149,9 +160,6 @@ static int user_save_internal(User *u) {
+         if (u->service_job)
+                 fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
+ 
+-        if (u->slice_job)
+-                fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
+-
+         if (u->display)
+                 fprintf(f, "DISPLAY=%s\n", u->display->id);
+ 
+@@ -311,66 +319,46 @@ int user_load(User *u) {
+         return 0;
+ }
+ 
+-static int user_start_service(User *u) {
++static void user_start_service(User *u) {
+         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+-        char *job;
+         int r;
+ 
+         assert(u);
+ 
++        /* Start the service containing the "systemd --user" instance (user@.service). Note that we don't explicitly
++         * start the per-user slice or the systemd-runtime-dir@.service instance, as those are pulled in both by
++         * user@.service and the session scopes as dependencies. */
++
+         u->service_job = mfree(u->service_job);
+ 
+-        r = manager_start_unit(
+-                        u->manager,
+-                        u->service,
+-                        &error,
+-                        &job);
++        r = manager_start_unit(u->manager, u->service, &error, &u->service_job);
+         if (r < 0)
+                 /* we don't fail due to this, let's try to continue */
+                 log_full_errno(sd_bus_error_has_name(&error, BUS_ERROR_UNIT_MASKED) ? LOG_DEBUG : LOG_WARNING, r,
+                                "Failed to start user service '%s', ignoring: %s", u->service, bus_error_message(&error, r));
+-        else
+-                u->service_job = job;
+-
+-        return 0;
+ }
+ 
+ int user_start(User *u) {
+-        int r;
+-
+         assert(u);
+ 
+         if (u->started && !u->stopping)
+                 return 0;
+ 
+-        /*
+-         * If u->stopping is set, the user is marked for removal and the slice
+-         * and service stop-jobs are queued. We have to clear that flag before
+-         * queing the start-jobs again. If they succeed, the user object can be
+-         * re-used just fine (pid1 takes care of job-ordering and proper
+-         * restart), but if they fail, we want to force another user_stop() so
+-         * possibly pending units are stopped.
+-         * Note that we don't clear u->started, as we have no clue what state
+-         * the user is in on failure here. Hence, we pretend the user is
+-         * running so it will be properly taken down by GC. However, we clearly
+-         * return an error from user_start() in that case, so no further
+-         * reference to the user is taken.
+-         */
++        /* If u->stopping is set, the user is marked for removal and service stop-jobs are queued. We have to clear
++         * that flag before queing the start-jobs again. If they succeed, the user object can be re-used just fine
++         * (pid1 takes care of job-ordering and proper restart), but if they fail, we want to force another user_stop()
++         * so possibly pending units are stopped. */
+         u->stopping = false;
+ 
+         if (!u->started)
+                 log_debug("Starting services for new user %s.", u->name);
+ 
+-        /* Save the user data so far, because pam_systemd will read the
+-         * XDG_RUNTIME_DIR out of it while starting up systemd --user.
+-         * We need to do user_save_internal() because we have not
+-         * "officially" started yet. */
++        /* Save the user data so far, because pam_systemd will read the XDG_RUNTIME_DIR out of it while starting up
++         * systemd --user.  We need to do user_save_internal() because we have not "officially" started yet. */
+         user_save_internal(u);
+ 
+-        /* Spawn user systemd */
+-        r = user_start_service(u);
+-        if (r < 0)
+-                return r;
++        /* Start user@UID.service */
++        user_start_service(u);
+ 
+         if (!u->started) {
+                 if (!dual_timestamp_is_set(&u->timestamp))
+@@ -385,68 +373,50 @@ int user_start(User *u) {
+         return 0;
+ }
+ 
+-static int user_stop_slice(User *u) {
++static void user_stop_service(User *u) {
+         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+-        char *job;
+         int r;
+ 
+         assert(u);
++        assert(u->service);
+ 
+-        r = manager_stop_unit(u->manager, u->slice, &error, &job);
+-        if (r < 0) {
+-                log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
+-                return r;
+-        }
++        /* The reverse of user_start_service(). Note that we only stop user@UID.service here, and let StopWhenUnneeded=
++         * deal with the slice and the user-runtime-dir@.service instance. */
+ 
+-        free(u->slice_job);
+-        u->slice_job = job;
+-
+-        return r;
+-}
+-
+-static int user_stop_service(User *u) {
+-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+-        char *job;
+-        int r;
+-
+-        assert(u);
+-
+-        r = manager_stop_unit(u->manager, u->service, &error, &job);
+-        if (r < 0) {
+-                log_error("Failed to stop user service: %s", bus_error_message(&error, r));
+-                return r;
+-        }
++        u->service_job = mfree(u->service_job);
+ 
+-        free_and_replace(u->service_job, job);
+-        return r;
++        r = manager_stop_unit(u->manager, u->service, &error, &u->service_job);
++        if (r < 0)
++                log_warning_errno(r, "Failed to stop user service '%s', ignoring: %s", u->service, bus_error_message(&error, r));
+ }
+ 
+ int user_stop(User *u, bool force) {
+         Session *s;
+-        int r = 0, k;
++        int r = 0;
+         assert(u);
+ 
+-        /* Stop jobs have already been queued */
+-        if (u->stopping) {
++        /* This is called whenever we begin with tearing down a user record. It's called in two cases: explicit API
++         * request to do so via the bus (in which case 'force' is true) and automatically due to GC, if there's no
++         * session left pinning it (in which case 'force' is false). Note that this just initiates tearing down of the
++         * user, the User object will remain in memory until user_finalize() is called, see below. */
++
++        if (!u->started)
++                return 0;
++
++        if (u->stopping) { /* Stop jobs have already been queued */
+                 user_save(u);
+-                return r;
++                return 0;
+         }
+ 
+         LIST_FOREACH(sessions_by_user, s, u->sessions) {
++                int k;
++
+                 k = session_stop(s, force);
+                 if (k < 0)
+                         r = k;
+         }
+ 
+-        /* Kill systemd */
+-        k = user_stop_service(u);
+-        if (k < 0)
+-                r = k;
+-
+-        /* Kill cgroup */
+-        k = user_stop_slice(u);
+-        if (k < 0)
+-                r = k;
++        user_stop_service(u);
+ 
+         u->stopping = true;
+ 
+@@ -461,6 +431,9 @@ int user_finalize(User *u) {
+ 
+         assert(u);
+ 
++        /* Called when the user is really ready to be freed, i.e. when all unit stop jobs and suchlike for it are
++         * done. This is called as a result of an earlier user_done() when all jobs are completed. */
++
+         if (u->started)
+                 log_debug("User %s logged out.", u->name);
+ 
+@@ -554,9 +527,6 @@ bool user_may_gc(User *u, bool drop_not_started) {
+         if (user_check_linger_file(u) > 0)
+                 return false;
+ 
+-        if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
+-                return false;
+-
+         if (u->service_job && manager_job_is_active(u->manager, u->service_job))
+                 return false;
+ 
+@@ -581,7 +551,7 @@ UserState user_get_state(User *u) {
+         if (u->stopping)
+                 return USER_CLOSING;
+ 
+-        if (!u->started || u->slice_job || u->service_job)
++        if (!u->started || u->service_job)
+                 return USER_OPENING;
+ 
+         if (u->sessions) {
+diff --git a/src/login/logind-user.h b/src/login/logind-user.h
+index 03e020b870..5e1f7b813a 100644
+--- a/src/login/logind-user.h
++++ b/src/login/logind-user.h
+@@ -25,11 +25,12 @@ struct User {
+         char *name;
+         char *state_file;
+         char *runtime_path;
+-        char *slice;
+-        char *service;
++
++        char *slice;                     /* user-UID.slice */
++        char *service;                   /* user@UID.service */
++        char *runtime_dir_service;       /* user-runtime-dir@UID.service */
+ 
+         char *service_job;
+-        char *slice_job;
+ 
+         Session *display;
+ 
+diff --git a/src/login/logind.c b/src/login/logind.c
+index 1b366cd55f..6c208c8e89 100644
+--- a/src/login/logind.c
++++ b/src/login/logind.c
+@@ -1158,7 +1158,7 @@ static int manager_startup(Manager *m) {
+                 user_start(user);
+ 
+         HASHMAP_FOREACH(session, m->sessions, i)
+-                session_start(session, NULL);
++                (void) session_start(session, NULL, NULL);
+ 
+         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
+                 inhibitor_start(inhibitor);
+diff --git a/src/login/logind.h b/src/login/logind.h
+index a6ebc9e152..ae4d74076b 100644
+--- a/src/login/logind.h
++++ b/src/login/logind.h
+@@ -161,7 +161,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
+ 
+ int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
+ 
+-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_message *more_properties, sd_bus_error *error, char **job);
++int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, sd_bus_message *more_properties, sd_bus_error *error, char **job);
+ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
+ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
+ int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
diff --git a/SOURCES/0631-logind-optionally-keep-the-user-.service-instance-fo.patch b/SOURCES/0631-logind-optionally-keep-the-user-.service-instance-fo.patch
new file mode 100644
index 0000000..63f6a56
--- /dev/null
+++ b/SOURCES/0631-logind-optionally-keep-the-user-.service-instance-fo.patch
@@ -0,0 +1,291 @@
+From 35455408393cb29a5e49fd769c4823b6a6f886b4 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 7 Aug 2018 11:02:00 +0200
+Subject: [PATCH] logind: optionally, keep the user@.service instance for
+ eached logged in user around for a while
+
+This should speed up rapid logout/login cycles a bit.
+
+By default this timeout is now set to 10s.
+
+Fixes: #8410
+Replaces: #4434
+(cherry picked from commit 9afe9efb9340588db553950727a2a9672dc3db24)
+
+Resolves: #1642460
+---
+ man/logind.conf.xml          | 11 +++++
+ src/login/logind-core.c      |  2 +
+ src/login/logind-dbus.c      |  1 +
+ src/login/logind-gperf.gperf |  1 +
+ src/login/logind-session.c   |  4 ++
+ src/login/logind-user.c      | 88 +++++++++++++++++++++++++++++++++---
+ src/login/logind-user.h      |  7 ++-
+ src/login/logind.h           |  1 +
+ 8 files changed, 107 insertions(+), 8 deletions(-)
+
+diff --git a/man/logind.conf.xml b/man/logind.conf.xml
+index 7d7e869a26..0cf8a7d1f2 100644
+--- a/man/logind.conf.xml
++++ b/man/logind.conf.xml
+@@ -184,6 +184,17 @@
+         5.</para></listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++        <term><varname>UserStopDelaySec=</varname></term>
++
++        <listitem><para>Specifies how long to keep the user record and per-user service
++        <filename>user@.service</filename> around for a user after they logged out fully. If set to zero, the per-user
++        service is terminated immediately when the last session of the user has ended. If this option is configured to
++        non-zero rapid logout/login cycles are sped up, as the user's service manager is not constantly restarted. If
++        set to <literal>infinity</literal> the per-user service for a user is never terminated again after first login,
++        and continues to run until system shutdown. Defaults to 10s.</para></listitem>
++      </varlistentry>
++
+       <varlistentry>
+         <term><varname>HandlePowerKey=</varname></term>
+         <term><varname>HandleSuspendKey=</varname></term>
+diff --git a/src/login/logind-core.c b/src/login/logind-core.c
+index f598bbaa1c..678c708df1 100644
+--- a/src/login/logind-core.c
++++ b/src/login/logind-core.c
+@@ -27,6 +27,8 @@ void manager_reset_config(Manager *m) {
+         m->reserve_vt = 6;
+         m->remove_ipc = false;
+         m->inhibit_delay_max = 5 * USEC_PER_SEC;
++        m->user_stop_delay = 10 * USEC_PER_SEC;
++
+         m->handle_power_key = HANDLE_POWEROFF;
+         m->handle_suspend_key = HANDLE_SUSPEND;
+         m->handle_hibernate_key = HANDLE_HIBERNATE;
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index 7eba617fff..6586280269 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -2695,6 +2695,7 @@ const sd_bus_vtable manager_vtable[] = {
+         SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
++        SD_BUS_PROPERTY("UserStopDelayUSec", "t", NULL, offsetof(Manager, user_stop_delay), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
+diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
+index c85339dcd3..8829ce7d85 100644
+--- a/src/login/logind-gperf.gperf
++++ b/src/login/logind-gperf.gperf
+@@ -23,6 +23,7 @@ Login.KillUserProcesses,            config_parse_bool,                  0, offse
+ Login.KillOnlyUsers,                config_parse_strv,                  0, offsetof(Manager, kill_only_users)
+ Login.KillExcludeUsers,             config_parse_strv,                  0, offsetof(Manager, kill_exclude_users)
+ Login.InhibitDelayMaxSec,           config_parse_sec,                   0, offsetof(Manager, inhibit_delay_max)
++Login.UserStopDelaySec,             config_parse_sec,                   0, offsetof(Manager, user_stop_delay)
+ Login.HandlePowerKey,               config_parse_handle_action,         0, offsetof(Manager, handle_power_key)
+ Login.HandleSuspendKey,             config_parse_handle_action,         0, offsetof(Manager, handle_suspend_key)
+ Login.HandleHibernateKey,           config_parse_handle_action,         0, offsetof(Manager, handle_hibernate_key)
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index d56b48a732..dd4ac9482a 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -101,6 +101,8 @@ Session* session_free(Session *s) {
+ 
+                 if (s->user->display == s)
+                         s->user->display = NULL;
++
++                user_update_last_session_timer(s->user);
+         }
+ 
+         if (s->seat) {
+@@ -142,6 +144,8 @@ void session_set_user(Session *s, User *u) {
+ 
+         s->user = u;
+         LIST_PREPEND(sessions_by_user, u->sessions, s);
++
++        user_update_last_session_timer(u);
+ }
+ 
+ static void session_save_devices(Session *s, FILE *f) {
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 39fc76f4dc..f23fcbe674 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -47,6 +47,7 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
+                 .manager = m,
+                 .uid = uid,
+                 .gid = gid,
++                .last_session_timestamp = USEC_INFINITY,
+         };
+ 
+         u->name = strdup(name);
+@@ -113,6 +114,8 @@ User *user_free(User *u) {
+ 
+         hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u);
+ 
++        (void) sd_event_source_unref(u->timer_event_source);
++
+         u->service_job = mfree(u->service_job);
+ 
+         u->service = mfree(u->service);
+@@ -170,6 +173,10 @@ static int user_save_internal(User *u) {
+                         u->timestamp.realtime,
+                         u->timestamp.monotonic);
+ 
++        if (u->last_session_timestamp != USEC_INFINITY)
++                fprintf(f, "LAST_SESSION_TIMESTAMP=" USEC_FMT "\n",
++                        u->last_session_timestamp);
++
+         if (u->sessions) {
+                 Session *i;
+                 bool first;
+@@ -287,16 +294,17 @@ int user_save(User *u) {
+ }
+ 
+ int user_load(User *u) {
+-        _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL;
++        _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL, *last_session_timestamp = NULL;
+         int r;
+ 
+         assert(u);
+ 
+         r = parse_env_file(NULL, u->state_file, NEWLINE,
+-                           "SERVICE_JOB", &u->service_job,
+-                           "STOPPING",    &stopping,
+-                           "REALTIME",    &realtime,
+-                           "MONOTONIC",   &monotonic,
++                           "SERVICE_JOB",            &u->service_job,
++                           "STOPPING",               &stopping,
++                           "REALTIME",               &realtime,
++                           "MONOTONIC",              &monotonic,
++                           "LAST_SESSION_TIMESTAMP", &last_session_timestamp,
+                            NULL);
+         if (r == -ENOENT)
+                 return 0;
+@@ -312,9 +320,11 @@ int user_load(User *u) {
+         }
+ 
+         if (realtime)
+-                timestamp_deserialize(realtime, &u->timestamp.realtime);
++                (void) timestamp_deserialize(realtime, &u->timestamp.realtime);
+         if (monotonic)
+-                timestamp_deserialize(monotonic, &u->timestamp.monotonic);
++                (void) timestamp_deserialize(monotonic, &u->timestamp.monotonic);
++        if (last_session_timestamp)
++                (void) timestamp_deserialize(last_session_timestamp, &u->last_session_timestamp);
+ 
+         return 0;
+ }
+@@ -524,6 +534,17 @@ bool user_may_gc(User *u, bool drop_not_started) {
+         if (u->sessions)
+                 return false;
+ 
++        if (u->last_session_timestamp != USEC_INFINITY) {
++                /* All sessions have been closed. Let's see if we shall leave the user record around for a bit */
++
++                if (u->manager->user_stop_delay == USEC_INFINITY)
++                        return false; /* Leave it around forever! */
++                if (u->manager->user_stop_delay > 0 &&
++                    now(CLOCK_MONOTONIC) < usec_add(u->last_session_timestamp, u->manager->user_stop_delay))
++                        return false; /* Leave it around for a bit longer. */
++        }
++
++        /* Is this a user that shall stay around forever? */
+         if (user_check_linger_file(u) > 0)
+                 return false;
+ 
+@@ -649,6 +670,59 @@ void user_elect_display(User *u) {
+         }
+ }
+ 
++static int user_stop_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
++        User *u = userdata;
++
++        assert(u);
++        user_add_to_gc_queue(u);
++
++        return 0;
++}
++
++void user_update_last_session_timer(User *u) {
++        int r;
++
++        assert(u);
++
++        if (u->sessions) {
++                /* There are sessions, turn off the timer */
++                u->last_session_timestamp = USEC_INFINITY;
++                u->timer_event_source = sd_event_source_unref(u->timer_event_source);
++                return;
++        }
++
++        if (u->last_session_timestamp != USEC_INFINITY)
++                return; /* Timer already started */
++
++        u->last_session_timestamp = now(CLOCK_MONOTONIC);
++
++        assert(!u->timer_event_source);
++
++        if (u->manager->user_stop_delay == 0 || u->manager->user_stop_delay == USEC_INFINITY)
++                return;
++
++        if (sd_event_get_state(u->manager->event) == SD_EVENT_FINISHED) {
++                log_debug("Not allocating user stop timeout, since we are already exiting.");
++                return;
++        }
++
++        r = sd_event_add_time(u->manager->event,
++                              &u->timer_event_source,
++                              CLOCK_MONOTONIC,
++                              usec_add(u->last_session_timestamp, u->manager->user_stop_delay), 0,
++                              user_stop_timeout_callback, u);
++        if (r < 0)
++                log_warning_errno(r, "Failed to enqueue user stop event source, ignoring: %m");
++
++        if (DEBUG_LOGGING) {
++                char s[FORMAT_TIMESPAN_MAX];
++
++                log_debug("Last session of user '%s' logged out, terminating user context in %s.",
++                          u->name,
++                          format_timespan(s, sizeof(s), u->manager->user_stop_delay, USEC_PER_MSEC));
++        }
++}
++
+ static const char* const user_state_table[_USER_STATE_MAX] = {
+         [USER_OFFLINE] = "offline",
+         [USER_OPENING] = "opening",
+diff --git a/src/login/logind-user.h b/src/login/logind-user.h
+index 5e1f7b813a..e05646adc9 100644
+--- a/src/login/logind-user.h
++++ b/src/login/logind-user.h
+@@ -34,7 +34,11 @@ struct User {
+ 
+         Session *display;
+ 
+-        dual_timestamp timestamp;
++        dual_timestamp timestamp;      /* When this User object was 'started' the first time */
++        usec_t last_session_timestamp; /* When the number of sessions of this user went from 1 to 0 the last time */
++
++        /* Set up when the last session of the user logs out */
++        sd_event_source *timer_event_source;
+ 
+         bool in_gc_queue:1;
+ 
+@@ -62,6 +66,7 @@ int user_load(User *u);
+ int user_kill(User *u, int signo);
+ int user_check_linger_file(User *u);
+ void user_elect_display(User *u);
++void user_update_last_session_timer(User *u);
+ 
+ extern const sd_bus_vtable user_vtable[];
+ int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
+diff --git a/src/login/logind.h b/src/login/logind.h
+index ae4d74076b..7288dd7445 100644
+--- a/src/login/logind.h
++++ b/src/login/logind.h
+@@ -62,6 +62,7 @@ struct Manager {
+         Hashmap *user_units;
+ 
+         usec_t inhibit_delay_max;
++        usec_t user_stop_delay;
+ 
+         /* If an action is currently being executed or is delayed,
+          * this is != 0 and encodes what is being done */
diff --git a/SOURCES/0632-logind-add-a-RequiresMountsFor-dependency-from-the-s.patch b/SOURCES/0632-logind-add-a-RequiresMountsFor-dependency-from-the-s.patch
new file mode 100644
index 0000000..93f6a2c
--- /dev/null
+++ b/SOURCES/0632-logind-add-a-RequiresMountsFor-dependency-from-the-s.patch
@@ -0,0 +1,210 @@
+From e9a187ea6abf1e7034ee3113355b282743a98f39 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 8 Aug 2018 15:27:49 +0200
+Subject: [PATCH] logind: add a RequiresMountsFor= dependency from the session
+ scope unit to the home directory of the user
+
+This is useful so that during shutdown scope units are always terminated
+before the mounts necessary for the home directory.
+
+(Ideally we'd also add a similar dependency from the user@.service
+instance to the home directory, but this isn't as easy as that service
+is defined statically and not dynamically, and hence not easy to modify
+dynamically, in particular when it comes to deps)
+
+(cherry picked from commit d5ac9d060267820aabdf9af509a54a1830b27b7d)
+
+Related: #1642460
+---
+ src/login/logind-core.c    | 24 ++++++++++++++++++------
+ src/login/logind-dbus.c    |  7 +++++++
+ src/login/logind-session.c |  1 +
+ src/login/logind-user.c    | 13 ++++++++++++-
+ src/login/logind-user.h    |  3 ++-
+ src/login/logind.h         |  4 ++--
+ 6 files changed, 42 insertions(+), 10 deletions(-)
+
+diff --git a/src/login/logind-core.c b/src/login/logind-core.c
+index 678c708df1..0ed812a2c8 100644
+--- a/src/login/logind-core.c
++++ b/src/login/logind-core.c
+@@ -128,7 +128,14 @@ int manager_add_session(Manager *m, const char *id, Session **_session) {
+         return 0;
+ }
+ 
+-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
++int manager_add_user(
++                Manager *m,
++                uid_t uid,
++                gid_t gid,
++                const char *name,
++                const char *home,
++                User **_user) {
++
+         User *u;
+         int r;
+ 
+@@ -137,7 +144,7 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **
+ 
+         u = hashmap_get(m->users, UID_TO_PTR(uid));
+         if (!u) {
+-                r = user_new(&u, m, uid, gid, name);
++                r = user_new(&u, m, uid, gid, name, home);
+                 if (r < 0)
+                         return r;
+         }
+@@ -148,7 +155,12 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **
+         return 0;
+ }
+ 
+-int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
++int manager_add_user_by_name(
++                Manager *m,
++                const char *name,
++                User **_user) {
++
++        const char *home = NULL;
+         uid_t uid;
+         gid_t gid;
+         int r;
+@@ -156,11 +168,11 @@ int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
+         assert(m);
+         assert(name);
+ 
+-        r = get_user_creds(&name, &uid, &gid, NULL, NULL);
++        r = get_user_creds(&name, &uid, &gid, &home, NULL);
+         if (r < 0)
+                 return r;
+ 
+-        return manager_add_user(m, uid, gid, name, _user);
++        return manager_add_user(m, uid, gid, name, home, _user);
+ }
+ 
+ int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
+@@ -173,7 +185,7 @@ int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
+         if (!p)
+                 return errno > 0 ? -errno : -ENOENT;
+ 
+-        return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
++        return manager_add_user(m, uid, p->pw_gid, p->pw_name, p->pw_dir, _user);
+ }
+ 
+ int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index 6586280269..1bb152bc20 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -3313,6 +3313,7 @@ int manager_start_scope(
+                 const char *description,
+                 char **wants,
+                 char **after,
++                const char *requires_mounts_for,
+                 sd_bus_message *more_properties,
+                 sd_bus_error *error,
+                 char **job) {
+@@ -3368,6 +3369,12 @@ int manager_start_scope(
+                         return r;
+         }
+ 
++        if (!empty_or_root(requires_mounts_for)) {
++                r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for);
++                if (r < 0)
++                        return r;
++        }
++
+         /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
+          * SIGTERM */
+         r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
+diff --git a/src/login/logind-session.c b/src/login/logind-session.c
+index dd4ac9482a..e4c8bb36f6 100644
+--- a/src/login/logind-session.c
++++ b/src/login/logind-session.c
+@@ -591,6 +591,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er
+                                 description,
+                                 STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */
+                                 STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */
++                                s->user->home,
+                                 properties,
+                                 error,
+                                 &s->scope_job);
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index f23fcbe674..70f5eb9d59 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -30,7 +30,13 @@
+ #include "user-util.h"
+ #include "util.h"
+ 
+-int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
++int user_new(User **ret,
++             Manager *m,
++             uid_t uid,
++             gid_t gid,
++             const char *name,
++             const char *home) {
++
+         _cleanup_(user_freep) User *u = NULL;
+         char lu[DECIMAL_STR_MAX(uid_t) + 1];
+         int r;
+@@ -54,6 +60,10 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
+         if (!u->name)
+                 return -ENOMEM;
+ 
++        u->home = strdup(home);
++        if (!u->home)
++                return -ENOMEM;
++
+         if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
+                 return -ENOMEM;
+ 
+@@ -124,6 +134,7 @@ User *user_free(User *u) {
+         u->runtime_path = mfree(u->runtime_path);
+         u->state_file = mfree(u->state_file);
+         u->name = mfree(u->name);
++        u->home = mfree(u->home);
+ 
+         return mfree(u);
+ }
+diff --git a/src/login/logind-user.h b/src/login/logind-user.h
+index e05646adc9..c41973e27d 100644
+--- a/src/login/logind-user.h
++++ b/src/login/logind-user.h
+@@ -23,6 +23,7 @@ struct User {
+         uid_t uid;
+         gid_t gid;
+         char *name;
++        char *home;
+         char *state_file;
+         char *runtime_path;
+ 
+@@ -49,7 +50,7 @@ struct User {
+         LIST_FIELDS(User, gc_queue);
+ };
+ 
+-int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name);
++int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name, const char *home);
+ User *user_free(User *u);
+ 
+ DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free);
+diff --git a/src/login/logind.h b/src/login/logind.h
+index 7288dd7445..d29b01c75b 100644
+--- a/src/login/logind.h
++++ b/src/login/logind.h
+@@ -129,7 +129,7 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_dev
+ int manager_add_button(Manager *m, const char *name, Button **_button);
+ int manager_add_seat(Manager *m, const char *id, Seat **_seat);
+ int manager_add_session(Manager *m, const char *id, Session **_session);
+-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user);
++int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, const char *home, User **_user);
+ int manager_add_user_by_name(Manager *m, const char *name, User **_user);
+ int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user);
+ int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor);
+@@ -162,7 +162,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
+ 
+ int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
+ 
+-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, sd_bus_message *more_properties, sd_bus_error *error, char **job);
++int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job);
+ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
+ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
+ int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
diff --git a/SOURCES/0633-logind-improve-error-propagation-of-user_check_linge.patch b/SOURCES/0633-logind-improve-error-propagation-of-user_check_linge.patch
new file mode 100644
index 0000000..9552207
--- /dev/null
+++ b/SOURCES/0633-logind-improve-error-propagation-of-user_check_linge.patch
@@ -0,0 +1,39 @@
+From 117ed6bd7aa71fc79599e1d37bdb4a94b3505a38 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 8 Aug 2018 16:03:11 +0200
+Subject: [PATCH] logind: improve error propagation of user_check_linger_file()
+
+Let's make this a bit prettier, and propagate unexpected access() errors
+correctly.
+
+(The callers of this function will suppress them, but it's nicer of they
+do that, rather than us doing that twice in both the callers and the
+callees)
+
+(cherry picked from commit 6996df9b864981980f5b713dc5c7d506a7a4b9bf)
+
+Related: #1642460
+---
+ src/login/logind-user.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 70f5eb9d59..3fd28fc66c 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -532,8 +532,14 @@ int user_check_linger_file(User *u) {
+                 return -ENOMEM;
+ 
+         p = strjoina("/var/lib/systemd/linger/", cc);
++        if (access(p, F_OK) < 0) {
++                if (errno != ENOENT)
++                        return -errno;
+ 
+-        return access(p, F_OK) >= 0;
++                return false;
++        }
++
++        return true;
+ }
+ 
+ bool user_may_gc(User *u, bool drop_not_started) {
diff --git a/SOURCES/0634-logind-automatically-GC-lingering-users-for-who-now-.patch b/SOURCES/0634-logind-automatically-GC-lingering-users-for-who-now-.patch
new file mode 100644
index 0000000..e299007
--- /dev/null
+++ b/SOURCES/0634-logind-automatically-GC-lingering-users-for-who-now-.patch
@@ -0,0 +1,82 @@
+From 89dd5e016a50da082e51129eecb3c5e04b8f0cf5 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 8 Aug 2018 16:04:40 +0200
+Subject: [PATCH] logind: automatically GC lingering users for who now
+ user@.service (nor slice, not runtime dir service) is running anymore
+
+This heavily borrows from @intelfx' PR #5546, but watches all three
+units that are associated with a user now: the slice, the user@.service
+and user-runtime-dir@.service.
+
+The logic and reasoning behind it is the same though: there's no value
+in keeping lingering users around if all their three services are gone.
+
+Replaces: #5546
+Fixes: #4162
+(cherry picked from commit 4e5b605af202c770dfc8e3562d0f8d0440b2fe14)
+
+Related: #1642460
+---
+ src/login/logind-user.c | 28 +++++++++++++++++++++++++---
+ 1 file changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/src/login/logind-user.c b/src/login/logind-user.c
+index 3fd28fc66c..bba3158d1a 100644
+--- a/src/login/logind-user.c
++++ b/src/login/logind-user.c
+@@ -26,6 +26,7 @@
+ #include "special.h"
+ #include "stdio-util.h"
+ #include "string-table.h"
++#include "strv.h"
+ #include "unit-name.h"
+ #include "user-util.h"
+ #include "util.h"
+@@ -542,6 +543,25 @@ int user_check_linger_file(User *u) {
+         return true;
+ }
+ 
++static bool user_unit_active(User *u) {
++        const char *i;
++        int r;
++
++        assert(u->service);
++        assert(u->runtime_dir_service);
++        assert(u->slice);
++
++        FOREACH_STRING(i, u->service, u->runtime_dir_service, u->slice) {
++                r = manager_unit_is_active(u->manager, i);
++                if (r < 0)
++                        log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring", u->service);
++                if (r != 0)
++                        return true;
++        }
++
++        return false;
++}
++
+ bool user_may_gc(User *u, bool drop_not_started) {
+         assert(u);
+ 
+@@ -561,8 +581,10 @@ bool user_may_gc(User *u, bool drop_not_started) {
+                         return false; /* Leave it around for a bit longer. */
+         }
+ 
+-        /* Is this a user that shall stay around forever? */
+-        if (user_check_linger_file(u) > 0)
++        /* Is this a user that shall stay around forever ("linger")? Before we say "no" to GC'ing for lingering users, let's check
++         * if any of the three units that we maintain for this user is still around. If none of them is,
++         * there's no need to keep this user around even if lingering is enabled. */
++        if (user_check_linger_file(u) > 0 && user_unit_active(u))
+                 return false;
+ 
+         if (u->service_job && manager_job_is_active(u->manager, u->service_job))
+@@ -608,7 +630,7 @@ UserState user_get_state(User *u) {
+                 return all_closing ? USER_CLOSING : USER_ONLINE;
+         }
+ 
+-        if (user_check_linger_file(u) > 0)
++        if (user_check_linger_file(u) > 0 && user_unit_active(u))
+                 return USER_LINGERING;
+ 
+         return USER_CLOSING;
diff --git a/SOURCES/0635-pam_systemd-simplify-code-which-with-we-set-environm.patch b/SOURCES/0635-pam_systemd-simplify-code-which-with-we-set-environm.patch
new file mode 100644
index 0000000..9eaff4c
--- /dev/null
+++ b/SOURCES/0635-pam_systemd-simplify-code-which-with-we-set-environm.patch
@@ -0,0 +1,101 @@
+From 96887ddecd1e4c36d8a32411ed515ddaf0f3a0e3 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Fri, 20 Jul 2018 11:27:55 +0200
+Subject: [PATCH] pam_systemd: simplify code which with we set environment
+ variables
+
+Let's shorten things a bit by splitting out common code in a new
+function.
+
+(cherry picked from commit d6baaa6978d3eb5b8e8497021c4ba576aee936a3)
+
+Related: #1642460
+---
+ src/login/pam_systemd.c | 46 ++++++++++++++++++++++++-----------------
+ 1 file changed, 27 insertions(+), 19 deletions(-)
+
+diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
+index 78ddb7d398..b2b62540bb 100644
+--- a/src/login/pam_systemd.c
++++ b/src/login/pam_systemd.c
+@@ -301,6 +301,24 @@ static const char* getenv_harder(pam_handle_t *handle, const char *key, const ch
+         return fallback;
+ }
+ 
++static int update_environment(pam_handle_t *handle, const char *key, const char *value) {
++        int r;
++
++        assert(handle);
++        assert(key);
++
++        /* Updates the environment, but only if there's actually a value set. Also, log about errors */
++
++        if (isempty(value))
++                return PAM_SUCCESS;
++
++        r = pam_misc_setenv(handle, key, value, 0);
++        if (r != PAM_SUCCESS)
++                pam_syslog(handle, LOG_ERR, "Failed to set environment variable %s.", key);
++
++        return r;
++}
++
+ _public_ PAM_EXTERN int pam_sm_open_session(
+                 pam_handle_t *handle,
+                 int flags,
+@@ -555,11 +573,9 @@ _public_ PAM_EXTERN int pam_sm_open_session(
+                            "id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u original_uid=%u",
+                            id, object_path, runtime_path, session_fd, seat, vtnr, original_uid);
+ 
+-        r = pam_misc_setenv(handle, "XDG_SESSION_ID", id, 0);
+-        if (r != PAM_SUCCESS) {
+-                pam_syslog(handle, LOG_ERR, "Failed to set session id.");
++        r = update_environment(handle, "XDG_SESSION_ID", id);
++        if (r != PAM_SUCCESS)
+                 return r;
+-        }
+ 
+         if (original_uid == pw->pw_uid) {
+                 /* Don't set $XDG_RUNTIME_DIR if the user we now
+@@ -568,34 +584,26 @@ _public_ PAM_EXTERN int pam_sm_open_session(
+                  * in privileged apps clobbering the runtime directory
+                  * unnecessarily. */
+ 
+-                r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0);
+-                if (r != PAM_SUCCESS) {
+-                        pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
++                r = update_environment(handle, "XDG_RUNTIME_DIR", runtime_path);
++                if (r != PAM_SUCCESS)
+                         return r;
+-                }
+ 
+                 r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path);
+                 if (r != PAM_SUCCESS)
+                         return r;
+         }
+ 
+-        if (!isempty(seat)) {
+-                r = pam_misc_setenv(handle, "XDG_SEAT", seat, 0);
+-                if (r != PAM_SUCCESS) {
+-                        pam_syslog(handle, LOG_ERR, "Failed to set seat.");
+-                        return r;
+-                }
+-        }
++        r = update_environment(handle, "XDG_SEAT", seat);
++        if (r != PAM_SUCCESS)
++                return r;
+ 
+         if (vtnr > 0) {
+                 char buf[DECIMAL_STR_MAX(vtnr)];
+                 sprintf(buf, "%u", vtnr);
+ 
+-                r = pam_misc_setenv(handle, "XDG_VTNR", buf, 0);
+-                if (r != PAM_SUCCESS) {
+-                        pam_syslog(handle, LOG_ERR, "Failed to set virtual terminal number.");
++                r = update_environment(handle, "XDG_VTNR", buf);
++                if (r != PAM_SUCCESS)
+                         return r;
+-                }
+         }
+ 
+         r = pam_set_data(handle, "systemd.existing", INT_TO_PTR(!!existing), NULL);
diff --git a/SOURCES/0636-logind-validate-run-user-1000-before-we-set-it.patch b/SOURCES/0636-logind-validate-run-user-1000-before-we-set-it.patch
new file mode 100644
index 0000000..e485042
--- /dev/null
+++ b/SOURCES/0636-logind-validate-run-user-1000-before-we-set-it.patch
@@ -0,0 +1,89 @@
+From c8b74ac5cf508c7bcec92d197880043af1d2bad7 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart@poettering.net>
+Date: Tue, 9 Oct 2018 22:23:41 +0200
+Subject: [PATCH] logind: validate /run/user/1000 before we set it
+
+Let's be safe than sorry, in particular as logind doesn't set it up
+anymore, but user-runtime-dir@.service does, and logind doesn't really
+track success of that.
+
+(cherry picked from commit b92171124819305985ed292cc472f6668a027425)
+
+Related: #1642460
+---
+ src/login/pam_systemd.c | 48 +++++++++++++++++++++++++++++++++++------
+ 1 file changed, 41 insertions(+), 7 deletions(-)
+
+diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
+index b2b62540bb..64e1b4d1bf 100644
+--- a/src/login/pam_systemd.c
++++ b/src/login/pam_systemd.c
+@@ -319,6 +319,36 @@ static int update_environment(pam_handle_t *handle, const char *key, const char
+         return r;
+ }
+ 
++static bool validate_runtime_directory(pam_handle_t *handle, const char *path, uid_t uid) {
++        struct stat st;
++
++        assert(path);
++
++        /* Just some extra paranoia: let's not set $XDG_RUNTIME_DIR if the directory we'd set it to isn't actually set
++         * up properly for us. */
++
++        if (lstat(path, &st) < 0) {
++                pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror(errno));
++                goto fail;
++        }
++
++        if (!S_ISDIR(st.st_mode)) {
++                pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not actually a directory.", path);
++                goto fail;
++        }
++
++        if (st.st_uid != uid) {
++                pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not owned by UID " UID_FMT ", as it should.", path, uid);
++                goto fail;
++        }
++
++        return true;
++
++fail:
++        pam_syslog(handle, LOG_WARNING, "Not setting $XDG_RUNTIME_DIR, as the directory is not in order.");
++        return false;
++}
++
+ _public_ PAM_EXTERN int pam_sm_open_session(
+                 pam_handle_t *handle,
+                 int flags,
+@@ -377,10 +407,12 @@ _public_ PAM_EXTERN int pam_sm_open_session(
+                 if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0)
+                         return PAM_BUF_ERR;
+ 
+-                r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
+-                if (r != PAM_SUCCESS) {
+-                        pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
+-                        return r;
++                if (validate_runtime_directory(handle, rt, pw->pw_uid)) {
++                        r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
++                        if (r != PAM_SUCCESS) {
++                                pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
++                                return r;
++                        }
+                 }
+ 
+                 r = export_legacy_dbus_address(handle, pw->pw_uid, rt);
+@@ -584,9 +616,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
+                  * in privileged apps clobbering the runtime directory
+                  * unnecessarily. */
+ 
+-                r = update_environment(handle, "XDG_RUNTIME_DIR", runtime_path);
+-                if (r != PAM_SUCCESS)
+-                        return r;
++                if (validate_runtime_directory(handle, runtime_path, pw->pw_uid)) {
++                        r = update_environment(handle, "XDG_RUNTIME_DIR", runtime_path);
++                        if (r != PAM_SUCCESS)
++                                return r;
++                }
+ 
+                 r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path);
+                 if (r != PAM_SUCCESS)
diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec
index b0a2787..bb99bcf 100644
--- a/SPECS/systemd.spec
+++ b/SPECS/systemd.spec
@@ -13,7 +13,7 @@
 Name:           systemd
 Url:            http://www.freedesktop.org/wiki/Software/systemd
 Version:        239
-Release:        49%{?dist}
+Release:        50%{?dist}
 # For a breakdown of the licensing, see README
 License:        LGPLv2+ and MIT and GPLv2+
 Summary:        System and Service Manager
@@ -660,6 +660,32 @@ Patch0607: 0607-ci-drop-forgotten-Travis-references.patch
 Patch0608: 0608-ci-run-unit-tests-on-CentOS-8-Stream-as-well.patch
 Patch0609: 0609-ci-add-missing-test-dependencies.patch
 Patch0610: 0610-meson-bump-timeout-for-test-udev-to-180s.patch
+Patch0611: 0611-Added-option-check-inhibitors-for-non-tty-usage.patch
+Patch0612: 0612-logind-Introduce-RebootWithFlags-and-others.patch
+Patch0613: 0613-logind-add-WithFlags-methods-to-policy.patch
+Patch0614: 0614-logind-simplify-flags-handling-a-bit.patch
+Patch0615: 0615-Update-link-to-RHEL-documentation.patch
+Patch0616: 0616-Set-default-core-ulimit-to-0-but-keep-the-hard-limit.patch
+Patch0617: 0617-shared-seccomp-util-address-family-filtering-is-brok.patch
+Patch0618: 0618-logind-rework-Seat-Session-User-object-allocation-an.patch
+Patch0619: 0619-logind-fix-serialization-deserialization-of-user-s-d.patch
+Patch0620: 0620-logind-turn-of-stdio-locking-when-writing-session-fi.patch
+Patch0621: 0621-units-set-StopWhenUnneeded-for-the-user-slice-units-.patch
+Patch0622: 0622-units-improve-Description-string-a-bit.patch
+Patch0623: 0623-logind-improve-logging-in-manager_connect_console.patch
+Patch0624: 0624-logind-save-restore-User-object-s-stopping-field-dur.patch
+Patch0625: 0625-logind-correct-bad-clean-up-path.patch
+Patch0626: 0626-logind-fix-bad-error-propagation.patch
+Patch0627: 0627-logind-never-elect-a-session-that-is-stopping-as-dis.patch
+Patch0628: 0628-logind-introduce-little-helper-that-checks-whether-a.patch
+Patch0629: 0629-logind-propagate-session-stop-errors.patch
+Patch0630: 0630-logind-rework-how-we-manage-the-slice-and-user-runti.patch
+Patch0631: 0631-logind-optionally-keep-the-user-.service-instance-fo.patch
+Patch0632: 0632-logind-add-a-RequiresMountsFor-dependency-from-the-s.patch
+Patch0633: 0633-logind-improve-error-propagation-of-user_check_linge.patch
+Patch0634: 0634-logind-automatically-GC-lingering-users-for-who-now-.patch
+Patch0635: 0635-pam_systemd-simplify-code-which-with-we-set-environm.patch
+Patch0636: 0636-logind-validate-run-user-1000-before-we-set-it.patch
 
 
 %ifarch %{ix86} x86_64 aarch64
@@ -1287,6 +1313,34 @@ fi
 %files tests -f .file-list-tests
 
 %changelog
+* Fri Aug 27 2021 systemd maintenance team <systemd-maint@redhat.com> - 239-50
+- Added option --check-inhibitors for non-tty usage (#1269726)
+- logind: Introduce RebootWithFlags and others (#1269726)
+- logind: add …WithFlags methods to policy (#1269726)
+- logind: simplify flags handling a bit (#1269726)
+- Update link to RHEL documentation (#1982584)
+- Set default core ulimit to 0, but keep the hard limit ulimited (#1905582)
+- shared/seccomp-util: address family filtering is broken on ppc (#1982650)
+- logind: rework Seat/Session/User object allocation and freeing a bit (#1642460)
+- logind: fix serialization/deserialization of user's "display session" (#1642460)
+- logind: turn of stdio locking when writing session files too (#1642460)
+- units: set StopWhenUnneeded= for the user slice units too (#1642460)
+- units: improve Description= string a bit (#1642460)
+- logind: improve logging in manager_connect_console() (#1642460)
+- logind: save/restore User object's "stopping" field during restarts (#1642460)
+- logind: correct bad clean-up path (#1642460)
+- logind: fix bad error propagation (#1642460)
+- logind: never elect a session that is stopping as display (#1642460)
+- logind: introduce little helper that checks whether a session is ready (#1642460)
+- logind: propagate session stop errors (#1642460)
+- logind: rework how we manage the slice and user-runtime-dir@.service unit for each user (#1642460)
+- logind: optionally, keep the user@.service instance for eached logged in user around for a while (#1642460)
+- logind: add a RequiresMountsFor= dependency from the session scope unit to the home directory of the user (#1642460)
+- logind: improve error propagation of user_check_linger_file() (#1642460)
+- logind: automatically GC lingering users for who now user@.service (nor slice, not runtime dir service) is running anymore (#1642460)
+- pam_systemd: simplify code which with we set environment variables (#1642460)
+- logind: validate /run/user/1000 before we set it (#1642460)
+
 * Fri Jul 23 2021 systemd maintenance team <systemd-maint@redhat.com> - 239-49
 - remove a left-over break (#1970860)
 - basic/unit-name: do not use strdupa() on a path (#1974700)