From: Lennart Poettering Date: Fri, 24 Jan 2025 09:24:09 +0000 (+0100) Subject: run0: add explicit support for opening sessions in specific areas X-Git-Tag: v258-rc1~1410^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f44e7a8c11833563d558c208c76cdcc0df7de022;p=thirdparty%2Fsystemd.git run0: add explicit support for opening sessions in specific areas --- diff --git a/src/run/run.c b/src/run/run.c index 68966ccbda2..8d1606af07c 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -91,6 +91,7 @@ static char *arg_background = NULL; static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF; static char *arg_shell_prompt_prefix = NULL; static int arg_lightweight = -1; +static char *arg_area = NULL; STATIC_DESTRUCTOR_REGISTER(arg_description, freep); STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep); @@ -103,6 +104,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_cmdline, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_exec_path, freep); STATIC_DESTRUCTOR_REGISTER(arg_background, freep); STATIC_DESTRUCTOR_REGISTER(arg_shell_prompt_prefix, freep); +STATIC_DESTRUCTOR_REGISTER(arg_area, freep); static int help(void) { _cleanup_free_ char *link = NULL; @@ -206,6 +208,7 @@ static int help_sudo_mode(void) { " --shell-prompt-prefix=PREFIX Set $SHELL_PROMPT_PREFIX\n" " --lightweight=BOOLEAN Control whether to register a session with service manager\n" " or without\n" + " -a --area=AREA Home area to log into\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), @@ -824,6 +827,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { { "pipe", no_argument, NULL, ARG_PIPE }, { "shell-prompt-prefix", required_argument, NULL, ARG_SHELL_PROMPT_PREFIX }, { "lightweight", required_argument, NULL, ARG_LIGHTWEIGHT }, + { "area", required_argument, NULL, 'a' }, {}, }; @@ -835,7 +839,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { /* Resetting to 0 forces the invocation of an internal initialization routine of getopt_long() * that checks for GNU extensions in optstring ('-' or '+' at the beginning). */ optind = 0; - while ((c = getopt_long(argc, argv, "+hVu:g:D:", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "+hVu:g:D:a:", options, NULL)) >= 0) switch (c) { @@ -942,6 +946,17 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { return r; break; + case 'a': + /* We allow an empty --area= specification to allow logging into the primary home directory */ + if (!isempty(optarg) && !filename_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid area name, refusing: %s", optarg); + + r = free_and_strdup_warn(&arg_area, optarg); + if (r < 0) + return r; + + break; + case '?': return -EINVAL; @@ -949,6 +964,14 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { assert_not_reached(); } + if (!arg_exec_user && arg_area) { + /* If the user specifies --area= but not --user= then consider this an area switch request, + * and default to logging into our own account */ + arg_exec_user = getusername_malloc(); + if (!arg_exec_user) + return log_oom(); + } + if (!arg_working_directory) { if (arg_exec_user) { /* When switching to a specific user, also switch to its home directory. */ @@ -1075,26 +1098,39 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) { return log_error_errno(r, "Failed to set $SHELL_PROMPT_PREFIX environment variable: %m"); } - /* When using run0 to acquire privileges temporarily, let's not pull in session manager by - * default. Note that pam_logind/systemd-logind doesn't distinguish between run0-style privilege - * escalation on a TTY and first class (getty-style) TTY logins (and thus gives root a per-session - * manager for interactive TTY sessions), hence let's override the logic explicitly here. We only do - * this for root though, under the assumption that if a regular user temporarily transitions into - * another regular user it's a better default that the full user environment is uniformly - * available. */ - if (arg_lightweight < 0 && !strv_env_get(arg_environment, "XDG_SESSION_CLASS") && privileged_execution()) - arg_lightweight = true; + if (!strv_env_get(arg_environment, "XDG_SESSION_CLASS")) { + + /* If logging into an area, imply lightweight mode */ + if (arg_lightweight < 0 && !isempty(arg_area)) + arg_lightweight = true; + + /* When using run0 to acquire privileges temporarily, let's not pull in session manager by + * default. Note that pam_logind/systemd-logind doesn't distinguish between run0-style privilege + * escalation on a TTY and first class (getty-style) TTY logins (and thus gives root a per-session + * manager for interactive TTY sessions), hence let's override the logic explicitly here. We only do + * this for root though, under the assumption that if a regular user temporarily transitions into + * another regular user it's a better default that the full user environment is uniformly + * available. */ + if (arg_lightweight < 0 && privileged_execution()) + arg_lightweight = true; + + if (arg_lightweight >= 0) { + const char *class = + arg_lightweight ? (arg_stdio == ARG_STDIO_PTY ? (privileged_execution() ? "user-early-light" : "user-light") : "background-light") : + (arg_stdio == ARG_STDIO_PTY ? (privileged_execution() ? "user-early" : "user") : "background"); - if (arg_lightweight >= 0) { - const char *class = - arg_lightweight ? (arg_stdio == ARG_STDIO_PTY ? (privileged_execution() ? "user-early-light" : "user-light") : "background-light") : - (arg_stdio == ARG_STDIO_PTY ? (privileged_execution() ? "user-early" : "user") : "background"); + log_debug("Setting XDG_SESSION_CLASS to '%s'.", class); - log_debug("Setting XDG_SESSION_CLASS to '%s'.", class); + r = strv_env_assign(&arg_environment, "XDG_SESSION_CLASS", class); + if (r < 0) + return log_error_errno(r, "Failed to set $XDG_SESSION_CLASS environment variable: %m"); + } + } - r = strv_env_assign(&arg_environment, "XDG_SESSION_CLASS", class); + if (arg_area) { + r = strv_env_assign(&arg_environment, "XDG_AREA", arg_area); if (r < 0) - return log_error_errno(r, "Failed to set $XDG_SESSION_CLASS environment variable: %m"); + return log_error_errno(r, "Failed to set $XDG_AREA environment variable: %m"); } return 1;