import systemd-239-50.el8
This commit is contained in:
parent
417291258a
commit
a004c9fb0a
@ -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:
|
769
SOURCES/0612-logind-Introduce-RebootWithFlags-and-others.patch
Normal file
769
SOURCES/0612-logind-Introduce-RebootWithFlags-and-others.patch
Normal file
@ -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) \
|
||||
{ \
|
85
SOURCES/0613-logind-add-WithFlags-methods-to-policy.patch
Normal file
85
SOURCES/0613-logind-add-WithFlags-methods-to-policy.patch
Normal file
@ -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"/>
|
72
SOURCES/0614-logind-simplify-flags-handling-a-bit.patch
Normal file
72
SOURCES/0614-logind-simplify-flags-handling-a-bit.patch
Normal file
@ -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)
|
25
SOURCES/0615-Update-link-to-RHEL-documentation.patch
Normal file
25
SOURCES/0615-Update-link-to-RHEL-documentation.patch
Normal file
@ -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>
|
@ -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=
|
@ -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
|
@ -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) {
|
@ -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);
|
@ -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"
|
@ -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%
|
29
SOURCES/0622-units-improve-Description-string-a-bit.patch
Normal file
29
SOURCES/0622-units-improve-Description-string-a-bit.patch
Normal file
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
25
SOURCES/0625-logind-correct-bad-clean-up-path.patch
Normal file
25
SOURCES/0625-logind-correct-bad-clean-up-path.patch
Normal file
@ -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)
|
25
SOURCES/0626-logind-fix-bad-error-propagation.patch
Normal file
25
SOURCES/0626-logind-fix-bad-error-propagation.patch
Normal file
@ -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;
|
||||
}
|
@ -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) {
|
@ -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);
|
40
SOURCES/0629-logind-propagate-session-stop-errors.patch
Normal file
40
SOURCES/0629-logind-propagate-session-stop-errors.patch
Normal file
@ -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);
|
@ -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);
|
@ -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 */
|
@ -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);
|
@ -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) {
|
@ -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;
|
@ -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);
|
@ -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)
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user