diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 795fc3b645..5f82b21995 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 5677c15b8a..f3c13ad89a 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 671384d34e..6ad6512f5a 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 6d5eee0317..08569e8bf3 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 ac59b7d79c..7bddc91ea6 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);