1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-10 05:18:17 +03:00

Merge pull request 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) { static void log_caller(sd_bus_message *message, Manager *manager, const char *method) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *comm = NULL; _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
Unit *caller;
pid_t pid;
assert(message); assert(message);
assert(manager); assert(manager);
assert(method); 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; return;
/* We need at least the PID, otherwise there's nothing to log, the rest is optional */ /* 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) if (bus_creds_get_pidref(creds, &pidref) < 0)
return; return;
const char *comm = NULL;
Unit *caller;
(void) sd_bus_creds_get_comm(creds, &comm); (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...", log_info("%s requested from client PID " PID_FMT "%s%s%s%s%s%s...",
method, pid, method, pidref.pid,
comm ? " ('" : "", strempty(comm), comm ? "')" : "", comm ? " ('" : "", strempty(comm), comm ? "')" : "",
caller ? " (unit " : "", caller ? caller->id : "", caller ? ")" : ""); 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); 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); r = mac_selinux_access_check(message, "reboot", error);
if (r < 0) if (r < 0)
return r; 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; m->objective = MANAGER_REBOOT;
return sd_bus_reply_method_return(message, NULL); return sd_bus_reply_method_return(message, NULL);
} }
static int method_soft_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) { 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); Manager *m = ASSERT_PTR(userdata);
_cleanup_free_ char *rt = NULL;
const char *root; const char *root;
int r; int r;
assert(message); 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); r = verify_run_space_permissive("soft reboot may fail", error);
if (r < 0) if (r < 0)
return r; 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, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"New root directory path '%s' is not absolute.", root); "New root directory path '%s' is not absolute.", root);
rt = strdup(root); r = path_simplify_alloc(root, &rt);
if (!rt) if (r < 0)
return -ENOMEM; return r;
} }
free_and_replace(m->switch_root, rt); 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); 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); r = mac_selinux_access_check(message, "halt", error);
if (r < 0) if (r < 0)
return r; 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; m->objective = MANAGER_POWEROFF;
return sd_bus_reply_method_return(message, NULL); 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); 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); r = mac_selinux_access_check(message, "halt", error);
if (r < 0) if (r < 0)
return r; 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; m->objective = MANAGER_HALT;
return sd_bus_reply_method_return(message, NULL); 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); 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); r = mac_selinux_access_check(message, "reboot", error);
if (r < 0) if (r < 0)
return r; 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; m->objective = MANAGER_KEXEC;
return sd_bus_reply_method_return(message, NULL); return sd_bus_reply_method_return(message, NULL);
} }
static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) { 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); Manager *m = ASSERT_PTR(userdata);
_cleanup_free_ char *ri = NULL, *rt = NULL;
const char *root, *init; const char *root, *init;
int r; int r;
assert(message); 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); r = verify_run_space_permissive("root switching may fail", error);
if (r < 0) if (r < 0)
return r; return r;
@ -1812,10 +1821,6 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
if (r < 0) if (r < 0)
return r; 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); r = sd_bus_message_read(message, "ss", &root, &init);
if (r < 0) if (r < 0)
return r; return r;
@ -1826,8 +1831,8 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
root = "/sysroot"; root = "/sysroot";
else { else {
if (!path_is_valid(root)) if (!path_is_valid(root))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
"New root directory must be a valid path."); "New root directory must be a valid path.");
if (!path_is_absolute(root)) if (!path_is_absolute(root))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, 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", "Failed to check if new root directory '%s' is the same as old root: %m",
root); root);
if (r > 0) if (r > 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
"New root directory cannot be the old root directory."); "New root directory cannot be the old root directory.");
} }
/* Safety check */ /* Safety check */
if (!in_initrd()) if (!in_initrd())
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
"Not in initrd, refusing switch-root operation."); "Not in initrd, refusing switch-root operation.");
r = path_is_os_tree(root); r = path_is_os_tree(root);
if (r < 0) 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); "Could not resolve init executable %s: %m", init);
} }
rt = strdup(root); r = path_simplify_alloc(root, &rt);
if (!rt) if (r < 0)
return -ENOMEM; return r;
if (!isempty(init)) { if (!isempty(init)) {
ri = strdup(init); r = path_simplify_alloc(init, &ri);
if (!ri) if (r < 0)
return -ENOMEM; return r;
} }
free_and_replace(m->switch_root, rt); free_and_replace(m->switch_root, rt);

View File

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

View File

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