X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Flogind-dbus.c;h=8c1748b15b5473d18387e64d07db7dc7f378ea8f;hb=40547399945b02a1537c83437f5e76c65568fa3c;hp=859ad3b58ca19651c1595fb2c5910918df54868a;hpb=caa7531f137aeb260fbda53e89a22f516836e89b;p=elogind.git diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 859ad3b58..8c1748b15 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) { @@ -801,8 +802,6 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use if (r < 0) goto fail; - session_save(session); - return 1; fail: @@ -837,6 +836,8 @@ static int method_release_session(sd_bus *bus, sd_bus_message *message, void *us if (r < 0) return r; + session_add_to_gc_queue(session); + return sd_bus_reply_method_return(message, NULL); } @@ -1417,6 +1418,28 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until) { return r; } +static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { + + static const char * const signal_name[_INHIBIT_WHAT_MAX] = { + [INHIBIT_SHUTDOWN] = "PrepareForShutdown", + [INHIBIT_SLEEP] = "PrepareForSleep" + }; + + int active = _active; + + assert(m); + assert(w >= 0); + assert(w < _INHIBIT_WHAT_MAX); + assert(signal_name[w]); + + return sd_bus_emit_signal(m->bus, + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + signal_name[w], + "b", + active); +} + static int execute_shutdown_or_sleep( Manager *m, InhibitWhat w, @@ -1434,6 +1457,12 @@ static int execute_shutdown_or_sleep( if (r < 0) return r; + if (w == INHIBIT_SLEEP) + /* And we're back. */ + send_prepare_for(m, w, false); + + m->action_what = 0; + /* Make sure the lid switch is ignored for a while (?) */ manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec); @@ -1456,28 +1485,6 @@ static int delay_shutdown_or_sleep( return 0; } -static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { - - static const char * const signal_name[_INHIBIT_WHAT_MAX] = { - [INHIBIT_SHUTDOWN] = "PrepareForShutdown", - [INHIBIT_SLEEP] = "PrepareForSleep" - }; - - int active = _active; - - assert(m); - assert(w >= 0); - assert(w < _INHIBIT_WHAT_MAX); - assert(signal_name[w]); - - return sd_bus_emit_signal(m->bus, - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - signal_name[w], - "b", - active); -} - int bus_manager_shutdown_or_sleep_now_or_later( Manager *m, HandleAction action, @@ -1722,7 +1729,7 @@ static int method_can_shutdown_or_sleep( blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); if (multiple_sessions) { - r = bus_verify_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, false, UID_INVALID, &challenge, error); + r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error); if (r < 0) return r; @@ -1735,7 +1742,7 @@ static int method_can_shutdown_or_sleep( } if (blocked) { - r = bus_verify_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, false, UID_INVALID, &challenge, error); + r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error); if (r < 0) return r; @@ -1751,7 +1758,7 @@ static int method_can_shutdown_or_sleep( /* If neither inhibit nor multiple sessions * apply then just check the normal policy */ - r = bus_verify_polkit(message, CAP_SYS_BOOT, action, false, UID_INVALID, &challenge, error); + r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error); if (r < 0) return r; @@ -1831,6 +1838,103 @@ 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; + Manager *m = userdata; + + assert(bus); + assert(message); + assert(m); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-to-firmware-setup", + 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 = 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; @@ -1950,6 +2054,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), @@ -2003,6 +2108,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", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("SessionNew", "so", 0), SD_BUS_SIGNAL("SessionRemoved", "so", 0),