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.
This commit is contained in:
Vesa Jääskeläinen 2019-03-09 22:30:58 +02:00
parent ce7f10707d
commit 428b296a59
5 changed files with 128 additions and 0 deletions

View File

@ -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(&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(
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),

View File

@ -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"/>

View File

@ -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>

View File

@ -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;

View File

@ -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);