Merge pull request #16281 from poettering/logind-cache-more-efi

logind: cache two more EFI variables in logind
This commit is contained in:
Lennart Poettering 2020-06-26 15:12:57 +02:00 committed by GitHub
commit 10f9436c2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 103 additions and 27 deletions

View File

@ -257,7 +257,7 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
assert((flags & O_EXCL) == 0);
/* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE in
* which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
* which case "ret_path" will be returned as NULL. If not possible the temporary path name used is returned in
* "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
fd = open_parent(target, O_TMPFILE|flags, 0640);

View File

@ -2751,8 +2751,6 @@ static int property_get_reboot_to_boot_loader_menu(
r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
if (r == -ENXIO) {
_cleanup_free_ char *v = NULL;
/* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished:
*
* 1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user)
@ -2760,20 +2758,10 @@ static int property_get_reboot_to_boot_loader_menu(
* 3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds
*/
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
r = efi_loader_get_config_timeout_one_shot(&x);
if (r < 0) {
if (r != -ENOENT)
log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m");
} else {
uint64_t sec;
r = safe_atou64(v, &sec);
if (r < 0)
log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v);
else if (sec > (USEC_INFINITY / USEC_PER_SEC))
log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m");
else
x = sec * USEC_PER_SEC; /* return in µs */
log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable, ignoring: %m");
}
} else if (r < 0)
@ -2932,24 +2920,25 @@ static int property_get_reboot_to_boot_loader_entry(
sd_bus_error *error) {
_cleanup_free_ char *v = NULL;
Manager *m = userdata;
const char *x = NULL;
int r;
assert(bus);
assert(reply);
assert(userdata);
assert(m);
r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
if (r == -ENXIO) {
/* EFI case: let's read the LoaderEntryOneShot variable */
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v);
r = efi_loader_update_entry_one_shot_cache(&m->efi_loader_entry_one_shot, &m->efi_loader_entry_one_shot_stat);
if (r < 0) {
if (r != -ENOENT)
log_warning_errno(r, "Failed to read LoaderEntryOneShot variable: %m");
} else if (!efi_loader_entry_name_valid(v)) {
log_warning("LoaderEntryOneShot contains invalid entry name '%s', ignoring.", v);
v = mfree(v);
}
log_warning_errno(r, "Failed to read LoaderEntryOneShot variable, ignoring: %m");
} else
x = m->efi_loader_entry_one_shot;
} else if (r < 0)
log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
else if (r > 0) {
@ -2959,14 +2948,14 @@ static int property_get_reboot_to_boot_loader_entry(
r = read_one_line_file("/run/systemd/reboot-to-boot-loader-entry", &v);
if (r < 0) {
if (r != -ENOENT)
log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-entry: %m");
} else if (!efi_loader_entry_name_valid(v)) {
log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-entry, ignoring: %m");
} else if (!efi_loader_entry_name_valid(v))
log_warning("/run/systemd/reboot-to-boot-loader-entry is not valid, ignoring.");
v = mfree(v);
}
else
x = v;
}
return sd_bus_message_append(reply, "s", v);
return sd_bus_message_append(reply, "s", x);
}
static int boot_loader_entry_exists(Manager *m, const char *id) {

View File

@ -169,6 +169,7 @@ static Manager* manager_unref(Manager *m) {
free(m->action_job);
strv_free(m->efi_boot_loader_entries);
free(m->efi_loader_entry_one_shot);
return mfree(m);
}

View File

@ -126,6 +126,9 @@ struct Manager {
char **efi_boot_loader_entries;
bool efi_boot_loader_entries_set;
char *efi_loader_entry_one_shot;
struct stat efi_loader_entry_one_shot_stat;
};
void manager_reset_config(Manager *m);

View File

@ -734,3 +734,73 @@ char *efi_tilt_backslashes(char *s) {
return s;
}
int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
_cleanup_free_ char *v = NULL, *fn = NULL;
static struct stat cache_stat = {};
struct stat new_stat;
static usec_t cache;
uint64_t sec;
int r;
assert(ret);
fn = efi_variable_path(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot");
if (!fn)
return -ENOMEM;
/* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */
if (stat(fn, &new_stat) < 0)
return -errno;
if (stat_inode_unmodified(&new_stat, &cache_stat)) {
*ret = cache;
return 0;
}
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
if (r < 0)
return r;
r = safe_atou64(v, &sec);
if (r < 0)
return r;
if (sec > USEC_INFINITY / USEC_PER_SEC)
return -ERANGE;
cache_stat = new_stat;
*ret = cache = sec * USEC_PER_SEC; /* return in µs */
return 0;
}
int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat) {
_cleanup_free_ char *fn = NULL, *v = NULL;
struct stat new_stat;
int r;
assert(cache);
assert(cache_stat);
fn = efi_variable_path(EFI_VENDOR_LOADER, "LoaderEntryOneShot");
if (!fn)
return -ENOMEM;
/* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */
if (stat(fn, &new_stat) < 0)
return -errno;
if (stat_inode_unmodified(&new_stat, cache_stat))
return 0;
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v);
if (r < 0)
return r;
if (!efi_loader_entry_name_valid(v))
return -EINVAL;
*cache_stat = new_stat;
free_and_replace(*cache, v);
return 0;
}

View File

@ -3,6 +3,8 @@
#include "efivars.h"
#include <sys/stat.h>
#if ENABLE_EFI
int efi_reboot_to_firmware_supported(void);
@ -23,6 +25,9 @@ int efi_loader_get_entries(char ***ret);
int efi_loader_get_features(uint64_t *ret);
int efi_loader_get_config_timeout_one_shot(usec_t *ret);
int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat);
#else
static inline int efi_reboot_to_firmware_supported(void) {
@ -77,6 +82,14 @@ static inline int efi_loader_get_features(uint64_t *ret) {
return -EOPNOTSUPP;
}
static inline int efi_loader_get_config_timeout_one_shot(usec_t *ret) {
return -EOPNOTSUPP;
}
static inline int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat) {
return -EOPNOTSUPP;
}
#endif
bool efi_loader_entry_name_valid(const char *s);