1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-09 12:58:26 +03:00

Merge pull request #11602 from vesajaaskelainen/dbus-reboot-with-parameters

dbus-manager: Add RebootWithParameters d-bus method
This commit is contained in:
Lennart Poettering 2019-03-22 21:07:47 +01:00 committed by GitHub
commit 16b4623620
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 163 additions and 32 deletions

View File

@ -47,7 +47,7 @@ void emergency_action(
case EMERGENCY_ACTION_REBOOT: case EMERGENCY_ACTION_REBOOT:
log_and_status(m, warn, "Rebooting", reason); 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); (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
break; break;
@ -55,7 +55,7 @@ void emergency_action(
case EMERGENCY_ACTION_REBOOT_FORCE: case EMERGENCY_ACTION_REBOOT_FORCE:
log_and_status(m, warn, "Forcibly rebooting", reason); 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; m->objective = MANAGER_REBOOT;
break; break;

View File

@ -32,6 +32,7 @@
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
#include "reboot-util.h"
#include "selinux-util.h" #include "selinux-util.h"
#include "sleep-config.h" #include "sleep-config.h"
#include "special.h" #include "special.h"
@ -42,6 +43,7 @@
#include "unit-name.h" #include "unit-name.h"
#include "user-util.h" #include "user-util.h"
#include "utmp-wtmp.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) { 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; 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( static int property_get_idle_hint(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,
@ -2382,6 +2410,97 @@ static int method_can_suspend_then_hibernate(sd_bus_message *message, void *user
error); 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(&parameter);
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( static int property_get_reboot_to_firmware_setup(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,
@ -2488,32 +2607,6 @@ static int method_set_reboot_to_firmware_setup(
return sd_bus_reply_method_return(message, NULL); 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( static int method_can_reboot_to_firmware_setup(
sd_bus_message *message, sd_bus_message *message,
void *userdata, 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("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("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("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("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("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), 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("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("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("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("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("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), SD_BUS_METHOD("CanRebootToBootLoaderMenu", NULL, "s", method_can_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),

View File

@ -190,6 +190,14 @@
send_interface="org.freedesktop.login1.Manager" send_interface="org.freedesktop.login1.Manager"
send_member="CancelScheduledShutdown"/> 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" <allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager" send_interface="org.freedesktop.login1.Manager"
send_member="CanRebootToFirmwareSetup"/> send_member="CanRebootToFirmwareSetup"/>

View File

@ -337,6 +337,17 @@
</defaults> </defaults>
</action> </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"> <action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
<description gettext-domain="systemd">Indicate to the firmware to boot to setup interface</description> <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> <message gettext-domain="systemd">Authentication is required to indicate to the firmware to boot to setup interface.</message>

View File

@ -12,10 +12,13 @@
#include "umask-util.h" #include "umask-util.h"
#include "virt.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; int r;
if (isempty(parameter)) { if (isempty(parameter)) {
if (keep)
return 0;
if (unlink("/run/systemd/reboot-param") < 0) { if (unlink("/run/systemd/reboot-param") < 0) {
if (errno == ENOENT) if (errno == ENOENT)
return 0; return 0;
@ -36,6 +39,18 @@ int update_reboot_parameter_and_warn(const char *parameter) {
return 0; 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 reboot_with_parameter(RebootFlags flags) {
int r; int r;

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #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 { typedef enum RebootFlags {
REBOOT_LOG = 1 << 0, /* log about what we are going to do and all errors */ 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 */ REBOOT_FALLBACK = 1 << 2, /* fallback to plain reboot() if argument-based reboot doesn't work, isn't configured or doesn't apply otherwise */
} RebootFlags; } RebootFlags;
int read_reboot_parameter(char **parameter);
int reboot_with_parameter(RebootFlags flags); int reboot_with_parameter(RebootFlags flags);

View File

@ -3734,7 +3734,7 @@ static int start_special(int argc, char *argv[], void *userdata) {
return r; return r;
if (a == ACTION_REBOOT && argc > 1) { 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) if (r < 0)
return r; 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)) { 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) if (r < 0)
return r; return r;
} else if (optind < argc) } else if (optind < argc)