mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
run0: add explicit support for opening sessions in specific areas
This commit is contained in:
@@ -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 (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 logging into an area, imply lightweight mode */
|
||||
if (arg_lightweight < 0 && !isempty(arg_area))
|
||||
arg_lightweight = true;
|
||||
|
||||
log_debug("Setting XDG_SESSION_CLASS to '%s'.", class);
|
||||
/* 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;
|
||||
|
||||
r = strv_env_assign(&arg_environment, "XDG_SESSION_CLASS", class);
|
||||
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);
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user