summaryrefslogtreecommitdiff
path: root/src/login
diff options
context:
space:
mode:
authorJan Janssen <medhefgo@web.de>2015-04-03 18:03:06 +0200
committerLennart Poettering <lennart@poettering.net>2015-04-07 18:51:45 +0200
commit5bdf22430e367799dfa66c724144b624c5479518 (patch)
treef26c8dbe3b4395e1b1b5d33ad185c8b7e4fed0e3 /src/login
parent3d1137ac2b196cee345ac70fcdac675af142c8dc (diff)
logind,systemctl: add reboot to EFI firmware support
Diffstat (limited to 'src/login')
-rw-r--r--src/login/logind-dbus.c102
-rw-r--r--src/login/org.freedesktop.login1.conf8
-rw-r--r--src/login/org.freedesktop.login1.policy.in10
3 files changed, 120 insertions, 0 deletions
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 1571dd0a8a..46185f40a3 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -38,6 +38,7 @@
#include "bus-common-errors.h"
#include "udev-util.h"
#include "selinux-util.h"
+#include "efivars.h"
#include "logind.h"
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
@@ -1850,6 +1851,104 @@ static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *u
error);
}
+static int property_get_reboot_to_firmware_setup(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(userdata);
+
+ r = efi_get_reboot_to_firmware();
+ if (r < 0 && r != -EOPNOTSUPP)
+ return r;
+
+ return sd_bus_message_append(reply, "b", r > 0);
+}
+
+static int method_set_reboot_to_firmware_setup(
+ sd_bus *bus,
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ int b, r;
+ int interactive;
+ Manager *m = userdata;
+
+ assert(bus);
+ assert(message);
+ assert(m);
+
+ r = sd_bus_message_read(message, "bb", &b, &interactive);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_polkit_async(message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-firmware-setup",
+ interactive,
+ 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 = efi_set_reboot_to_firmware(b);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_can_reboot_to_firmware_setup(
+ sd_bus *bus,
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ int r;
+ bool challenge;
+ const char *result;
+ Manager *m = userdata;
+
+ assert(bus);
+ assert(message);
+ assert(m);
+
+ r = efi_reboot_to_firmware_supported();
+ if (r == -EOPNOTSUPP)
+ return sd_bus_reply_method_return(message, "s", "na");
+ else if (r < 0)
+ return r;
+
+ r = bus_test_polkit(message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-firmware-setup",
+ UID_INVALID,
+ &challenge,
+ error);
+ 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_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
const char *who, *why, *what, *mode;
@@ -1970,6 +2069,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("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -2023,6 +2123,8 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetRebootToFirmwareSetup", "bb", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("SessionNew", "so", 0),
SD_BUS_SIGNAL("SessionRemoved", "so", 0),
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index 1318328aa0..0ad78802dd 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -130,6 +130,14 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="CanRebootToFirmwareSetup"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="SetRebootToFirmwareSetup"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="AttachDevice"/>
<allow send_destination="org.freedesktop.login1"
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index c45491be13..83e7183323 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -290,4 +290,14 @@
</defaults>
</action>
+ <action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
+ <_description>Allow indication to the firmware to boot to setup interface</_description>
+ <_message>Authentication is required to indicate to the firmware to boot to setup interface.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>