aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/login/logind-dbus.c96
-rw-r--r--src/login/org.freedesktop.login1.conf8
-rw-r--r--src/login/org.freedesktop.login1.policy11
-rw-r--r--src/shared/reboot-util.c12
-rw-r--r--src/shared/reboot-util.h1
5 files changed, 128 insertions, 0 deletions
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(&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),
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
@@ -192,6 +192,14 @@
<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"/>
<allow send_destination="org.freedesktop.login1"
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 @@
</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>
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);