1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #33575 from YHNdnzj/soft-reboot-system-manager-only

core/dbus-manager: several cleanups, refuse SoftReboot() for user manager
This commit is contained in:
Luca Boccassi 2024-07-03 13:40:06 +02:00 committed by GitHub
commit 0f20f7d6fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 93 additions and 85 deletions

View File

@ -1553,26 +1553,27 @@ static int verify_run_space_permissive(const char *message, sd_bus_error *error)
static void log_caller(sd_bus_message *message, Manager *manager, const char *method) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *comm = NULL;
Unit *caller;
pid_t pid;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
assert(message);
assert(manager);
assert(method);
if (sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID|SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_COMM, &creds) < 0)
if (sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_COMM, &creds) < 0)
return;
/* We need at least the PID, otherwise there's nothing to log, the rest is optional */
if (sd_bus_creds_get_pid(creds, &pid) < 0)
/* We need at least the PID, otherwise there's nothing to log, the rest is optional. */
if (bus_creds_get_pidref(creds, &pidref) < 0)
return;
const char *comm = NULL;
Unit *caller;
(void) sd_bus_creds_get_comm(creds, &comm);
caller = manager_get_unit_by_pid(manager, pid);
caller = manager_get_unit_by_pidref(manager, &pidref);
log_info("%s requested from client PID " PID_FMT "%s%s%s%s%s%s...",
method, pid,
method, pidref.pid,
comm ? " ('" : "", strempty(comm), comm ? "')" : "",
caller ? " (unit " : "", caller ? caller->id : "", caller ? ")" : "");
}
@ -1687,27 +1688,31 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
assert(message);
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Reboot is only supported by system manager.");
r = mac_selinux_access_check(message, "reboot", error);
if (r < 0)
return r;
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Reboot is only supported for system managers.");
m->objective = MANAGER_REBOOT;
return sd_bus_reply_method_return(message, NULL);
}
static int method_soft_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *rt = NULL;
Manager *m = ASSERT_PTR(userdata);
_cleanup_free_ char *rt = NULL;
const char *root;
int r;
assert(message);
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Soft reboot is only supported by system manager.");
r = verify_run_space_permissive("soft reboot may fail", error);
if (r < 0)
return r;
@ -1728,9 +1733,9 @@ static int method_soft_reboot(sd_bus_message *message, void *userdata, sd_bus_er
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"New root directory path '%s' is not absolute.", root);
rt = strdup(root);
if (!rt)
return -ENOMEM;
r = path_simplify_alloc(root, &rt);
if (r < 0)
return r;
}
free_and_replace(m->switch_root, rt);
@ -1745,14 +1750,14 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error
assert(message);
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Powering off is only supported by system manager.");
r = mac_selinux_access_check(message, "halt", error);
if (r < 0)
return r;
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Powering off is only supported for system managers.");
m->objective = MANAGER_POWEROFF;
return sd_bus_reply_method_return(message, NULL);
@ -1764,14 +1769,14 @@ static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *er
assert(message);
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Halt is only supported by system manager.");
r = mac_selinux_access_check(message, "halt", error);
if (r < 0)
return r;
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Halt is only supported for system managers.");
m->objective = MANAGER_HALT;
return sd_bus_reply_method_return(message, NULL);
@ -1783,27 +1788,31 @@ static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *e
assert(message);
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
"KExec is only supported by system manager.");
r = mac_selinux_access_check(message, "reboot", error);
if (r < 0)
return r;
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"KExec is only supported for system managers.");
m->objective = MANAGER_KEXEC;
return sd_bus_reply_method_return(message, NULL);
}
static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *ri = NULL, *rt = NULL;
Manager *m = ASSERT_PTR(userdata);
_cleanup_free_ char *ri = NULL, *rt = NULL;
const char *root, *init;
int r;
assert(message);
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Root switching is only supported by system manager.");
r = verify_run_space_permissive("root switching may fail", error);
if (r < 0)
return r;
@ -1812,10 +1821,6 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
if (r < 0)
return r;
if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Root switching is only supported by system manager.");
r = sd_bus_message_read(message, "ss", &root, &init);
if (r < 0)
return r;
@ -1826,8 +1831,8 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
root = "/sysroot";
else {
if (!path_is_valid(root))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"New root directory must be a valid path.");
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
"New root directory must be a valid path.");
if (!path_is_absolute(root))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
@ -1839,14 +1844,14 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
"Failed to check if new root directory '%s' is the same as old root: %m",
root);
if (r > 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"New root directory cannot be the old root directory.");
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
"New root directory cannot be the old root directory.");
}
/* Safety check */
if (!in_initrd())
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Not in initrd, refusing switch-root operation.");
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
"Not in initrd, refusing switch-root operation.");
r = path_is_os_tree(root);
if (r < 0)
@ -1876,14 +1881,14 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
"Could not resolve init executable %s: %m", init);
}
rt = strdup(root);
if (!rt)
return -ENOMEM;
r = path_simplify_alloc(root, &rt);
if (r < 0)
return r;
if (!isempty(init)) {
ri = strdup(init);
if (!ri)
return -ENOMEM;
r = path_simplify_alloc(init, &ri);
if (r < 0)
return r;
}
free_and_replace(m->switch_root, rt);

View File

@ -3285,14 +3285,15 @@ int main(int argc, char *argv[]) {
&switch_root_dir,
&switch_root_init,
&error_message);
assert(r < 0 || IN_SET(r, MANAGER_EXIT, /* MANAGER_OK and MANAGER_RELOAD are not expected here. */
MANAGER_REEXECUTE,
MANAGER_REBOOT,
MANAGER_SOFT_REBOOT,
MANAGER_POWEROFF,
MANAGER_HALT,
MANAGER_KEXEC,
MANAGER_SWITCH_ROOT));
/* MANAGER_OK and MANAGER_RELOAD are not expected here. */
assert(r < 0 || IN_SET(r, MANAGER_REEXECUTE, MANAGER_EXIT) ||
(arg_runtime_scope == RUNTIME_SCOPE_SYSTEM &&
IN_SET(r, MANAGER_REBOOT,
MANAGER_SOFT_REBOOT,
MANAGER_POWEROFF,
MANAGER_HALT,
MANAGER_KEXEC,
MANAGER_SWITCH_ROOT)));
finish:
pager_close();

View File

@ -3087,41 +3087,43 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
default: {
/* Starting SIGRTMIN+0 */
static const struct {
const char *target;
JobMode mode;
} target_table[] = {
[0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE },
[1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE },
[2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE },
[3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY },
[4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY },
[5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
[6] = { SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY },
[7] = { SPECIAL_SOFT_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
};
if (MANAGER_IS_SYSTEM(m)) {
/* Starting SIGRTMIN+0 */
static const struct {
const char *target;
JobMode mode;
} target_table[] = {
[0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE },
[1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE },
[2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE },
[3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY },
[4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY },
[5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
[6] = { SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY },
[7] = { SPECIAL_SOFT_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
};
/* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
static const ManagerObjective objective_table[] = {
[0] = MANAGER_HALT,
[1] = MANAGER_POWEROFF,
[2] = MANAGER_REBOOT,
[3] = MANAGER_KEXEC,
[4] = MANAGER_SOFT_REBOOT,
};
/* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
static const ManagerObjective objective_table[] = {
[0] = MANAGER_HALT,
[1] = MANAGER_POWEROFF,
[2] = MANAGER_REBOOT,
[3] = MANAGER_KEXEC,
[4] = MANAGER_SOFT_REBOOT,
};
if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
(int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
int idx = (int) sfsi.ssi_signo - SIGRTMIN;
manager_start_special(m, target_table[idx].target, target_table[idx].mode);
break;
}
if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
(int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
int idx = (int) sfsi.ssi_signo - SIGRTMIN;
manager_start_special(m, target_table[idx].target, target_table[idx].mode);
break;
}
if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
(int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(objective_table)) {
m->objective = objective_table[sfsi.ssi_signo - SIGRTMIN - 13];
break;
if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
(int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(objective_table)) {
m->objective = objective_table[sfsi.ssi_signo - SIGRTMIN - 13];
break;
}
}
switch (sfsi.ssi_signo - SIGRTMIN) {