mirror of
https://github.com/systemd/systemd.git
synced 2025-03-08 08:58:27 +03:00
Merge pull request #11602 from vesajaaskelainen/dbus-reboot-with-parameters
dbus-manager: Add RebootWithParameters d-bus method
This commit is contained in:
commit
16b4623620
@ -47,7 +47,7 @@ void emergency_action(
|
||||
case EMERGENCY_ACTION_REBOOT:
|
||||
log_and_status(m, warn, "Rebooting", reason);
|
||||
|
||||
(void) update_reboot_parameter_and_warn(reboot_arg);
|
||||
(void) update_reboot_parameter_and_warn(reboot_arg, true);
|
||||
(void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
|
||||
|
||||
break;
|
||||
@ -55,7 +55,7 @@ void emergency_action(
|
||||
case EMERGENCY_ACTION_REBOOT_FORCE:
|
||||
log_and_status(m, warn, "Forcibly rebooting", reason);
|
||||
|
||||
(void) update_reboot_parameter_and_warn(reboot_arg);
|
||||
(void) update_reboot_parameter_and_warn(reboot_arg, true);
|
||||
m->objective = MANAGER_REBOOT;
|
||||
|
||||
break;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "reboot-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "sleep-config.h"
|
||||
#include "special.h"
|
||||
@ -42,6 +43,7 @@
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
#include "utmp-wtmp.h"
|
||||
#include "virt.h"
|
||||
|
||||
static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
|
||||
|
||||
@ -168,6 +170,32 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int return_test_polkit(
|
||||
sd_bus_message *message,
|
||||
int capability,
|
||||
const char *action,
|
||||
const char **details,
|
||||
uid_t good_user,
|
||||
sd_bus_error *e) {
|
||||
|
||||
const char *result;
|
||||
bool challenge;
|
||||
int r;
|
||||
|
||||
r = bus_test_polkit(message, capability, action, details, good_user, &challenge, e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (r > 0)
|
||||
result = "yes";
|
||||
else if (challenge)
|
||||
result = "challenge";
|
||||
else
|
||||
result = "no";
|
||||
|
||||
return sd_bus_reply_method_return(message, "s", result);
|
||||
}
|
||||
|
||||
static int property_get_idle_hint(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@ -2382,6 +2410,97 @@ static int method_can_suspend_then_hibernate(sd_bus_message *message, void *user
|
||||
error);
|
||||
}
|
||||
|
||||
static int property_get_reboot_parameter(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
_cleanup_free_ char *parameter = NULL;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
assert(userdata);
|
||||
|
||||
r = read_reboot_parameter(¶meter);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_message_append(reply, "s", parameter);
|
||||
}
|
||||
|
||||
static int method_set_reboot_parameter(
|
||||
sd_bus_message *message,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
const char *arg;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = sd_bus_message_read(message, "s", &arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = detect_container();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
|
||||
"Reboot parameter not supported in containers, refusing.");
|
||||
|
||||
r = bus_verify_polkit_async(message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.set-reboot-parameter",
|
||||
NULL,
|
||||
false,
|
||||
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 */
|
||||
|
||||
r = update_reboot_parameter_and_warn(arg, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
static int method_can_reboot_parameter(
|
||||
sd_bus_message *message,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = detect_container();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) /* Inside containers, specifying a reboot parameter, doesn't make much sense */
|
||||
return sd_bus_reply_method_return(message, "s", "na");
|
||||
|
||||
return return_test_polkit(
|
||||
message,
|
||||
CAP_SYS_ADMIN,
|
||||
"org.freedesktop.login1.set-reboot-parameter",
|
||||
NULL,
|
||||
UID_INVALID,
|
||||
error);
|
||||
}
|
||||
|
||||
static int property_get_reboot_to_firmware_setup(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@ -2488,32 +2607,6 @@ static int method_set_reboot_to_firmware_setup(
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
static int return_test_polkit(
|
||||
sd_bus_message *message,
|
||||
int capability,
|
||||
const char *action,
|
||||
const char **details,
|
||||
uid_t good_user,
|
||||
sd_bus_error *e) {
|
||||
|
||||
const char *result;
|
||||
bool challenge;
|
||||
int r;
|
||||
|
||||
r = bus_test_polkit(message, capability, action, details, good_user, &challenge, e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (r > 0)
|
||||
result = "yes";
|
||||
else if (challenge)
|
||||
result = "challenge";
|
||||
else
|
||||
result = "no";
|
||||
|
||||
return sd_bus_reply_method_return(message, "s", result);
|
||||
}
|
||||
|
||||
static int method_can_reboot_to_firmware_setup(
|
||||
sd_bus_message *message,
|
||||
void *userdata,
|
||||
@ -3137,6 +3230,7 @@ const sd_bus_vtable manager_vtable[] = {
|
||||
SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RebootParameter", "s", property_get_reboot_parameter, 0, 0),
|
||||
SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, 0),
|
||||
SD_BUS_PROPERTY("RebootToBootLoaderMenu", "t", property_get_reboot_to_boot_loader_menu, 0, 0),
|
||||
SD_BUS_PROPERTY("RebootToBootLoaderEntry", "s", property_get_reboot_to_boot_loader_entry, 0, 0),
|
||||
@ -3213,6 +3307,8 @@ const sd_bus_vtable manager_vtable[] = {
|
||||
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("CanRebootParameter", NULL, "s", method_can_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetRebootParameter", "s", NULL, method_set_reboot_parameter, 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("CanRebootToBootLoaderMenu", NULL, "s", method_can_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
@ -190,6 +190,14 @@
|
||||
send_interface="org.freedesktop.login1.Manager"
|
||||
send_member="CancelScheduledShutdown"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.login1"
|
||||
send_interface="org.freedesktop.login1.Manager"
|
||||
send_member="CanRebootParameter"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.login1"
|
||||
send_interface="org.freedesktop.login1.Manager"
|
||||
send_member="SetRebootParameter"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.login1"
|
||||
send_interface="org.freedesktop.login1.Manager"
|
||||
send_member="CanRebootToFirmwareSetup"/>
|
||||
|
@ -337,6 +337,17 @@
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.login1.set-reboot-parameter">
|
||||
<description gettext-domain="systemd">Configure reboot parameter for kernel's reboot reason driver</description>
|
||||
<message gettext-domain="systemd">Authentication is required to configure reboot parameter for kernel's reboot reason driver.</message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin_keep</allow_any>
|
||||
<allow_inactive>auth_admin_keep</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
|
||||
<description gettext-domain="systemd">Indicate to the firmware to boot to setup interface</description>
|
||||
<message gettext-domain="systemd">Authentication is required to indicate to the firmware to boot to setup interface.</message>
|
||||
|
@ -12,10 +12,13 @@
|
||||
#include "umask-util.h"
|
||||
#include "virt.h"
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *parameter) {
|
||||
int update_reboot_parameter_and_warn(const char *parameter, bool keep) {
|
||||
int r;
|
||||
|
||||
if (isempty(parameter)) {
|
||||
if (keep)
|
||||
return 0;
|
||||
|
||||
if (unlink("/run/systemd/reboot-param") < 0) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
@ -36,6 +39,18 @@ int update_reboot_parameter_and_warn(const char *parameter) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_reboot_parameter(char **parameter) {
|
||||
int r;
|
||||
|
||||
assert(parameter);
|
||||
|
||||
r = read_one_line_file("/run/systemd/reboot-param", parameter);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_debug_errno(r, "Failed to read /run/systemd/reboot-param: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reboot_with_parameter(RebootFlags flags) {
|
||||
int r;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *parameter);
|
||||
int update_reboot_parameter_and_warn(const char *parameter, bool keep);
|
||||
|
||||
typedef enum RebootFlags {
|
||||
REBOOT_LOG = 1 << 0, /* log about what we are going to do and all errors */
|
||||
@ -9,4 +9,5 @@ typedef enum RebootFlags {
|
||||
REBOOT_FALLBACK = 1 << 2, /* fallback to plain reboot() if argument-based reboot doesn't work, isn't configured or doesn't apply otherwise */
|
||||
} RebootFlags;
|
||||
|
||||
int read_reboot_parameter(char **parameter);
|
||||
int reboot_with_parameter(RebootFlags flags);
|
||||
|
@ -3734,7 +3734,7 @@ static int start_special(int argc, char *argv[], void *userdata) {
|
||||
return r;
|
||||
|
||||
if (a == ACTION_REBOOT && argc > 1) {
|
||||
r = update_reboot_parameter_and_warn(argv[1]);
|
||||
r = update_reboot_parameter_and_warn(argv[1], false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -8455,7 +8455,7 @@ static int halt_parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
|
||||
r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL);
|
||||
r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (optind < argc)
|
||||
|
Loading…
x
Reference in New Issue
Block a user