From 428b296a599d010531c4577d55e1dea007511613 Mon Sep 17 00:00:00 2001 From: Vesa Jääskeläinen Date: Sat, 9 Mar 2019 22:30:58 +0200 Subject: logind: Add support for RebootParameter This adds support for user to set & get reboot parameter for reboot. As callee would be next issuing Reboot call same policy checks are being used. If unit file issuing the reboot action defines RebootArgument (or similar) that setting takes precedence. --- src/login/logind-dbus.c | 96 +++++++++++++++++++++++++++++++++ src/login/org.freedesktop.login1.conf | 8 +++ src/login/org.freedesktop.login1.policy | 11 ++++ src/shared/reboot-util.c | 12 +++++ src/shared/reboot-util.h | 1 + 5 files changed, 128 insertions(+) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 795fc3b645b..5f82b219956 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -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) { @@ -2408,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, @@ -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), diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf index 5677c15b8a9..f3c13ad89a0 100644 --- a/src/login/org.freedesktop.login1.conf +++ b/src/login/org.freedesktop.login1.conf @@ -190,6 +190,14 @@ send_interface="org.freedesktop.login1.Manager" send_member="CancelScheduledShutdown"/> + + + + diff --git a/src/login/org.freedesktop.login1.policy b/src/login/org.freedesktop.login1.policy index 671384d34e8..6ad6512f5a3 100644 --- a/src/login/org.freedesktop.login1.policy +++ b/src/login/org.freedesktop.login1.policy @@ -337,6 +337,17 @@ + + Configure reboot parameter for kernel's reboot reason driver + Authentication is required to configure reboot parameter for kernel's reboot reason driver. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.reboot + + Indicate to the firmware to boot to setup interface Authentication is required to indicate to the firmware to boot to setup interface. diff --git a/src/shared/reboot-util.c b/src/shared/reboot-util.c index 6d5eee03173..08569e8bf34 100644 --- a/src/shared/reboot-util.c +++ b/src/shared/reboot-util.c @@ -39,6 +39,18 @@ int update_reboot_parameter_and_warn(const char *parameter, bool keep) { 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; diff --git a/src/shared/reboot-util.h b/src/shared/reboot-util.h index ac59b7d79c6..7bddc91ea60 100644 --- a/src/shared/reboot-util.h +++ b/src/shared/reboot-util.h @@ -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); -- cgit v1.2.3-59-g8ed1b