From 9b9c23daf4b97e4b25ede3179df1cf7d7b27f304 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 12:41:34 +0200 Subject: [PATCH 01/13] logind: expose a boolean on the bus explaining whether logind thinks the lid is closed This copies how we already expose a "Docked" boolean the reflects whether we are in a docking station or not. --- src/login/logind-core.c | 11 +++++++++++ src/login/logind-dbus.c | 2 ++ src/login/logind.h | 1 + 3 files changed, 14 insertions(+) diff --git a/src/login/logind-core.c b/src/login/logind-core.c index 24f7c1439f..5608486284 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -566,6 +566,17 @@ int manager_spawn_autovt(Manager *m, unsigned vtnr) { return 0; } +bool manager_is_lid_closed(Manager *m) { + Iterator i; + Button *b; + + HASHMAP_FOREACH(b, m->buttons, i) + if (b->lid_closed) + return true; + + return false; +} + static bool manager_is_docked(Manager *m) { Iterator i; Button *b; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 927e304a0c..e3fc9a050e 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -274,6 +274,7 @@ static int property_get_scheduled_shutdown( static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction); static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays); +static BUS_DEFINE_PROPERTY_GET(property_get_lid_closed, "b", Manager, manager_is_lid_closed); static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX); static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size); @@ -2666,6 +2667,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0), SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0), SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0), + SD_BUS_PROPERTY("LidClosed", "b", property_get_lid_closed, 0, 0), SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/login/logind.h b/src/login/logind.h index 5398cca8c4..7b774f49e0 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -146,6 +146,7 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t); int manager_get_user_by_pid(Manager *m, pid_t pid, User **user); int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session); +bool manager_is_lid_closed(Manager *m); bool manager_is_docked_or_external_displays(Manager *m); bool manager_is_on_external_power(void); bool manager_all_buttons_ignored(Manager *m); From c30e0d7b6a57d9587ad596b69852256e4e3bf7fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 12:47:44 +0200 Subject: [PATCH 02/13] logind: don't claim that RebootToFirmwareSetup was constant It's not, after all, that's what SetRebootToFirmware() is about. (I was wondering for a moment whether to make this EMITS_CHANGES, but decided against it, given that the flag actually can be changed externally to logind too, and we couldn't send out notifications for that.) --- src/login/logind-dbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index e3fc9a050e..273736290f 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2646,7 +2646,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("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, 0), 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), From e455380b187aab1d02424d342d72c7cebb2d3bfb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 13:02:07 +0200 Subject: [PATCH 03/13] logind: make sure that if we can't figure out whether we are on AC we presume we are It's safer to assume that we are on AC than to assume we are on battery, if we can't figure it out. --- src/login/logind-core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/login/logind-core.c b/src/login/logind-core.c index 5608486284..2bab2fd2f5 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -681,15 +681,13 @@ bool manager_is_docked_or_external_displays(Manager *m) { bool manager_is_on_external_power(void) { int r; - /* For now we only check for AC power, but 'external power' can apply - * to anything that isn't an internal battery */ + /* For now we only check for AC power, but 'external power' can apply to anything that isn't an internal + * battery */ r = on_ac_power(); if (r < 0) log_warning_errno(r, "Failed to read AC power status: %m"); - else if (r > 0) - return true; - return false; + return r != 0; /* Treat failure as 'on AC' */ } bool manager_all_buttons_ignored(Manager *m) { From 4e96eb682c187a08fb8560e89b27d46bc2b46223 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 13:02:50 +0200 Subject: [PATCH 04/13] logind: also expose bool prop on bus that declares whether we are on external power The three core variables that affect idleness handling are whether we are docked, whether we are on AC power and whether the lid is closed, hence let's also expose the third variable on the bus, to make things nicely debuggable. --- src/login/logind-dbus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 273736290f..163fe04c1d 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -275,6 +275,7 @@ static int property_get_scheduled_shutdown( static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction); static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays); static BUS_DEFINE_PROPERTY_GET(property_get_lid_closed, "b", Manager, manager_is_lid_closed); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_on_external_power, "b", manager_is_on_external_power); static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX); static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size); @@ -2668,6 +2669,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0), SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0), SD_BUS_PROPERTY("LidClosed", "b", property_get_lid_closed, 0, 0), + SD_BUS_PROPERTY("OnExternalPower", "b", property_get_on_external_power, 0, 0), SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST), From 52ecf1958d30e09551b3b7c618e4c9d652c27259 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 16:37:10 +0200 Subject: [PATCH 05/13] locale-util: add special glyph support for check marks/cross marks --- src/basic/locale-util.c | 4 ++++ src/basic/locale-util.h | 2 ++ src/test/test-locale-util.c | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c index 9ad51a1972..7e479d605a 100644 --- a/src/basic/locale-util.c +++ b/src/basic/locale-util.c @@ -369,6 +369,8 @@ const char *special_glyph(SpecialGlyph code) { [MDASH] = "-", [ELLIPSIS] = "...", [MU] = "u", + [CHECK_MARK] = "+", + [CROSS_MARK] = "-", }, /* UTF-8 */ @@ -383,6 +385,8 @@ const char *special_glyph(SpecialGlyph code) { [MDASH] = "\342\200\223", /* – */ [ELLIPSIS] = "\342\200\246", /* … */ [MU] = "\316\274", /* μ */ + [CHECK_MARK] = "\342\234\223", /* ✓ */ + [CROSS_MARK] = "\342\234\227", /* ✗ */ }, }; diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h index 14beece6d8..ea624e9908 100644 --- a/src/basic/locale-util.h +++ b/src/basic/locale-util.h @@ -49,6 +49,8 @@ typedef enum { MDASH, ELLIPSIS, MU, + CHECK_MARK, + CROSS_MARK, _SPECIAL_GLYPH_MAX } SpecialGlyph; diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c index 3634534782..6d0f24eeea 100644 --- a/src/test/test-locale-util.c +++ b/src/test/test-locale-util.c @@ -65,7 +65,7 @@ static void test_keymaps(void) { #define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x)) static void dump_special_glyphs(void) { - assert_cc(MU + 1 == _SPECIAL_GLYPH_MAX); + assert_cc(CROSS_MARK + 1 == _SPECIAL_GLYPH_MAX); log_info("/* %s */", __func__); @@ -80,6 +80,9 @@ static void dump_special_glyphs(void) { dump_glyph(ARROW); dump_glyph(MDASH); dump_glyph(ELLIPSIS); + dump_glyph(MU); + dump_glyph(CHECK_MARK); + dump_glyph(CROSS_MARK); } int main(int argc, char *argv[]) { From c027b67f53339df37cf9603cd9bf64412ecb0a60 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 16:51:29 +0200 Subject: [PATCH 06/13] util: force time multiplications to happen in longs --- src/boot/efi/util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c index fd4be681a5..b70777292e 100644 --- a/src/boot/efi/util.c +++ b/src/boot/efi/util.c @@ -39,7 +39,7 @@ UINT64 ticks_freq(VOID) { uefi_call_wrapper(BS->Stall, 1, 1000); ticks_end = ticks_read(); - return (ticks_end - ticks_start) * 1000; + return (ticks_end - ticks_start) * 1000UL; } UINT64 time_usec(VOID) { @@ -56,7 +56,7 @@ UINT64 time_usec(VOID) { return 0; } - return 1000 * 1000 * ticks / freq; + return 1000UL * 1000UL * ticks / freq; } EFI_STATUS parse_boolean(CHAR8 *v, BOOLEAN *b) { From 80641a81b60bf0c118ae4ad1720ad9ce994b9ae3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 16:52:57 +0200 Subject: [PATCH 07/13] bootctl: display loader features in a pretty way. --- src/boot/bootctl.c | 28 +++++++++++++++++++++++++ src/shared/efivars.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ src/shared/efivars.h | 12 +++++++++++ 3 files changed, 90 insertions(+) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 7a20965b6a..427faf8b24 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -968,14 +968,28 @@ static int verb_status(int argc, char *argv[], void *userdata) { (void) pager_open(arg_pager_flags); if (is_efi_boot()) { + static const struct { + uint64_t flag; + const char *name; + } flags[] = { + { EFI_LOADER_FEATURE_BOOT_COUNTING, "Boot counting" }, + { EFI_LOADER_FEATURE_CONFIG_TIMEOUT, "Menu timeout control" }, + { EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT, "One-shot menu timeout control" }, + { EFI_LOADER_FEATURE_ENTRY_DEFAULT, "Default entry control" }, + { EFI_LOADER_FEATURE_ENTRY_ONESHOT, "One-shot entry control" }, + }; + _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL; sd_id128_t loader_part_uuid = SD_ID128_NULL; + uint64_t loader_features = 0; + size_t i; read_loader_efi_var("LoaderFirmwareType", &fw_type); read_loader_efi_var("LoaderFirmwareInfo", &fw_info); read_loader_efi_var("LoaderInfo", &loader); read_loader_efi_var("StubInfo", &stub); read_loader_efi_var("LoaderImageIdentifier", &loader_path); + (void) efi_loader_get_features(&loader_features); if (loader_path) efi_tilt_backslashes(loader_path); @@ -992,6 +1006,20 @@ static int verb_status(int argc, char *argv[], void *userdata) { printf("Current Boot Loader:\n"); printf(" Product: %s%s%s\n", ansi_highlight(), strna(loader), ansi_normal()); + + for (i = 0; i < ELEMENTSOF(flags); i++) { + + if (i == 0) + printf(" Features: "); + else + printf(" "); + + if (FLAGS_SET(loader_features, flags[i].flag)) + printf("%s%s%s %s\n", ansi_highlight_green(), special_glyph(CHECK_MARK), ansi_normal(), flags[i].name); + else + printf("%s%s%s %s\n", ansi_highlight_red(), special_glyph(CROSS_MARK), ansi_normal(), flags[i].name); + } + if (stub) printf(" Stub: %s\n", stub); if (!sd_id128_is_null(loader_part_uuid)) diff --git a/src/shared/efivars.c b/src/shared/efivars.c index 7a9754096c..e536f0d94e 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -822,3 +822,53 @@ char *efi_tilt_backslashes(char *s) { return s; } + +int efi_loader_get_features(uint64_t *ret) { + _cleanup_free_ void *v = NULL; + size_t s; + int r; + + if (!is_efi_boot()) { + *ret = 0; + return 0; + } + + r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderFeatures", NULL, &v, &s); + if (r == -ENOENT) { + _cleanup_free_ char *info = NULL; + + /* The new (v240+) LoaderFeatures variable is not supported, let's see if it's systemd-boot at all */ + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &info); + if (r < 0) { + if (r != -ENOENT) + return r; + + /* Variable not set, definitely means not systemd-boot */ + + } else if (first_word(info, "systemd-boot")) { + + /* An older systemd-boot version. Let's hardcode the feature set, since it was pretty + * static in all its versions. */ + + *ret = EFI_LOADER_FEATURE_CONFIG_TIMEOUT | + EFI_LOADER_FEATURE_ENTRY_DEFAULT | + EFI_LOADER_FEATURE_ENTRY_ONESHOT; + + return 0; + } + + /* No features supported */ + *ret = 0; + return 0; + } + if (r < 0) + return r; + + if (s != sizeof(uint64_t)) { + log_debug("LoaderFeatures EFI variable doesn't have the right size."); + return -EINVAL; + } + + memcpy(ret, v, sizeof(uint64_t)); + return 0; +} diff --git a/src/shared/efivars.h b/src/shared/efivars.h index 9b5ab39fee..feedbf91a6 100644 --- a/src/shared/efivars.h +++ b/src/shared/efivars.h @@ -18,6 +18,12 @@ #define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 #define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 +#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT (UINT64_C(1) << 0) +#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT (UINT64_C(1) << 1) +#define EFI_LOADER_FEATURE_ENTRY_DEFAULT (UINT64_C(1) << 2) +#define EFI_LOADER_FEATURE_ENTRY_ONESHOT (UINT64_C(1) << 3) +#define EFI_LOADER_FEATURE_BOOT_COUNTING (UINT64_C(1) << 4) + #if ENABLE_EFI bool is_efi_boot(void); @@ -43,6 +49,8 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader); int efi_loader_get_entries(char ***ret); +int efi_loader_get_features(uint64_t *ret); + #else static inline bool is_efi_boot(void) { @@ -117,6 +125,10 @@ static inline int efi_loader_get_entries(char ***ret) { return -EOPNOTSUPP; } +static inline int efi_loader_get_features(uint64_t *ret) { + return -EOPNOTSUPP; +} + #endif char *efi_tilt_backslashes(char *s); From 75100aeb9f773dbc8c4c2f2c625d9a8eaa70e475 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 18:06:06 +0200 Subject: [PATCH 08/13] logind: sort includes --- src/login/logind-dbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 163fe04c1d..5b9f2ec85a 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -14,6 +14,7 @@ #include "bus-error.h" #include "bus-unit-util.h" #include "bus-util.h" +#include "cgroup-util.h" #include "device-util.h" #include "dirent-util.h" #include "efivars.h" @@ -26,7 +27,6 @@ #include "mkdir.h" #include "path-util.h" #include "process-util.h" -#include "cgroup-util.h" #include "selinux-util.h" #include "sleep-config.h" #include "special.h" From c57ed5735fd59ac8dc643c04cb4c1cfbb311b316 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 18:06:18 +0200 Subject: [PATCH 09/13] logind: log correct error msg --- src/login/logind-dbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 5b9f2ec85a..26253eb619 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2458,7 +2458,7 @@ static int method_can_reboot_to_firmware_setup( r = efi_reboot_to_firmware_supported(); if (r < 0) { if (r != -EOPNOTSUPP) - log_warning_errno(errno, "Failed to determine whether reboot to firmware is supported: %m"); + log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m"); return sd_bus_reply_method_return(message, "s", "na"); } From cea72d53f89131e8c60679eeef6644ed5720156d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 19:58:26 +0200 Subject: [PATCH 10/13] efivars: add new helper efi_set_variable_string() Let's make it easier to parse an UTF-16 string properly. --- src/shared/efivars.c | 36 +++++++++++++++++++++++------------- src/shared/efivars.h | 9 +++++++-- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/shared/efivars.c b/src/shared/efivars.c index e536f0d94e..360ef03400 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -246,6 +246,24 @@ int efi_get_variable( return 0; } +int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { + _cleanup_free_ void *s = NULL; + size_t ss = 0; + int r; + char *x; + + r = efi_get_variable(vendor, name, NULL, &s, &ss); + if (r < 0) + return r; + + x = utf16_to_utf8(s, ss); + if (!x) + return -ENOMEM; + + *p = x; + return 0; +} + int efi_set_variable( sd_id128_t vendor, const char *name, @@ -326,22 +344,14 @@ finish: return r; } -int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { - _cleanup_free_ void *s = NULL; - size_t ss = 0; - int r; - char *x; +int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *v) { + _cleanup_free_ char16_t *u16 = NULL; - r = efi_get_variable(vendor, name, NULL, &s, &ss); - if (r < 0) - return r; - - x = utf16_to_utf8(s, ss); - if (!x) + u16 = utf8_to_utf16(v, strlen(v)); + if (!u16) return -ENOMEM; - *p = x; - return 0; + return efi_set_variable(vendor, name, u16, (char16_strlen(u16) + 1) * sizeof(char16_t)); } static size_t utf16_size(const uint16_t *s) { diff --git a/src/shared/efivars.h b/src/shared/efivars.h index feedbf91a6..51ecf6a279 100644 --- a/src/shared/efivars.h +++ b/src/shared/efivars.h @@ -34,8 +34,9 @@ int efi_get_reboot_to_firmware(void); int efi_set_reboot_to_firmware(bool value); int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size); -int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size); int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p); +int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size); +int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *p); int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active); int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path); @@ -81,11 +82,15 @@ static inline int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t return -EOPNOTSUPP; } +static inline int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { + return -EOPNOTSUPP; +} + static inline int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size) { return -EOPNOTSUPP; } -static inline int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { +static inline int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *p) { return -EOPNOTSUPP; } From 68d7c268f8b0e28ae719a8c783e3ded253563f9d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 19:59:45 +0200 Subject: [PATCH 11/13] efivars: let's add some validation of boot menu entry name syntax --- src/shared/efivars.c | 21 +++++++++++++++++---- src/shared/efivars.h | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/shared/efivars.c b/src/shared/efivars.c index 360ef03400..fbed9027c1 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -771,6 +771,16 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) { return 0; } +bool efi_loader_entry_name_valid(const char *s) { + if (isempty(s)) + return false; + + if (strlen(s) > FILENAME_MAX) /* Make sure entry names fit in filenames */ + return false; + + return in_charset(s, ALPHANUMERICAL "-"); +} + int efi_loader_get_entries(char ***ret) { _cleanup_free_ char16_t *entries = NULL; _cleanup_strv_free_ char **l = NULL; @@ -789,7 +799,7 @@ int efi_loader_get_entries(char ***ret) { /* The variable contains a series of individually NUL terminated UTF-16 strings. */ for (i = 0, start = 0;; i++) { - char *decoded; + _cleanup_free_ char *decoded = NULL; bool end; /* Is this the end of the variable's data? */ @@ -805,9 +815,12 @@ int efi_loader_get_entries(char ***ret) { if (!decoded) return -ENOMEM; - r = strv_consume(&l, decoded); - if (r < 0) - return r; + if (efi_loader_entry_name_valid(decoded)) { + r = strv_consume(&l, TAKE_PTR(decoded)); + if (r < 0) + return r; + } else + log_debug("Ignoring invalid loader entry '%s'.", decoded); /* We reached the end of the variable */ if (end) diff --git a/src/shared/efivars.h b/src/shared/efivars.h index 51ecf6a279..92670c82c7 100644 --- a/src/shared/efivars.h +++ b/src/shared/efivars.h @@ -50,6 +50,8 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader); int efi_loader_get_entries(char ***ret); +bool efi_loader_entry_name_valid(const char *s); + int efi_loader_get_features(uint64_t *ret); #else From c78e6f9e7b29656faf130e697a74e7f30ccaf6a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Oct 2018 20:00:31 +0200 Subject: [PATCH 12/13] logind: imply right to reboot when user has right to set reboot-to-firmware flag Let's reduce the number of actions the user has to acquire. --- src/login/org.freedesktop.login1.policy | 1 + 1 file changed, 1 insertion(+) diff --git a/src/login/org.freedesktop.login1.policy b/src/login/org.freedesktop.login1.policy index 78bee24b05..5ee62ab5b4 100644 --- a/src/login/org.freedesktop.login1.policy +++ b/src/login/org.freedesktop.login1.policy @@ -345,6 +345,7 @@ auth_admin_keep yes + org.freedesktop.login1.reboot From 0c093a62ef875ca4448cb9b778a2d1d7f3aec4a0 Mon Sep 17 00:00:00 2001 From: Henry Tung Date: Tue, 23 Oct 2018 14:09:13 +0200 Subject: [PATCH 13/13] logind: fix determination of CanHibernate() and other calls As suggest here: https://github.com/systemd/systemd/issues/10250#issuecomment-426788301 Fixes: #10250 (This suggested patch has been converted into a proper commit by me, Lennart, with attribution to the original author, @henryptung) --- src/login/logind-dbus.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 26253eb619..c0dafa03ef 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2267,11 +2267,13 @@ static int method_can_shutdown_or_sleep( if (r < 0) return r; - if (r > 0 && !result) - result = "yes"; - else if (challenge && (!result || streq(result, "yes"))) - result = "challenge"; - else + if (r > 0) { + if (!result) + result = "yes"; + } else if (challenge) { + if (!result || streq(result, "yes")) + result = "challenge"; + } else result = "no"; }