mirror of
https://github.com/systemd/systemd.git
synced 2024-10-28 03:25:31 +03:00
bootctl: print SystemdOptions from efivarfs if newer than our cache
The logic is that if the options are updated after boot, we *don't* use the new value. But we still want to print out the changed contents in bootctl as to not confuse people. Fixes #19597. Also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=988450. $ build/bootctl systemd-efi-options quiet Note: SystemdOptions EFI variable has been modified since boot. New value: debug The hint is printed to stderr, so scripts should not be confused.
This commit is contained in:
parent
c67bd42b71
commit
ad2d6880ea
@ -305,8 +305,7 @@ bool is_efi_secure_boot_setup_mode(void) {
|
||||
return cache > 0;
|
||||
}
|
||||
|
||||
int cache_efi_options_variable(void) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
static int read_efi_options_variable(char **line) {
|
||||
int r;
|
||||
|
||||
/* In SecureBoot mode this is probably not what you want. As your cmdline is cryptographically signed
|
||||
@ -326,9 +325,17 @@ int cache_efi_options_variable(void) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(SystemdOptions), &line);
|
||||
r = efi_get_variable_string(EFI_SYSTEMD_VARIABLE(SystemdOptions), line);
|
||||
if (r == -ENOENT)
|
||||
return -ENODATA;
|
||||
return r;
|
||||
}
|
||||
|
||||
int cache_efi_options_variable(void) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
int r;
|
||||
|
||||
r = read_efi_options_variable(&line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -340,6 +347,8 @@ int systemd_efi_options_variable(char **line) {
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
/* Returns the contents of the variable for current boot from the cache. */
|
||||
|
||||
assert(line);
|
||||
|
||||
/* For testing purposes it is sometimes useful to be able to override this */
|
||||
@ -360,4 +369,34 @@ int systemd_efi_options_variable(char **line) {
|
||||
return -ENODATA;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int compare_stat_mtime(const struct stat *a, const struct stat *b) {
|
||||
return CMP(timespec_load(&a->st_mtim), timespec_load(&b->st_mtim));
|
||||
}
|
||||
|
||||
int systemd_efi_options_efivarfs_if_newer(char **line) {
|
||||
struct stat a = {}, b;
|
||||
int r;
|
||||
|
||||
if (stat(EFIVAR_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), &a) < 0 && errno != ENOENT)
|
||||
return log_debug_errno(errno, "Failed to stat EFI variable SystemdOptions: %m");
|
||||
|
||||
if (stat(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), &b) < 0) {
|
||||
if (errno != -ENOENT)
|
||||
log_debug_errno(errno, "Failed to stat "EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions))": %m");
|
||||
} else if (compare_stat_mtime(&a, &b) > 0)
|
||||
log_debug("Variable SystemdOptions in evifarfs is newer than in cache.");
|
||||
else {
|
||||
log_debug("Variable SystemdOptions in cache is up to date.");
|
||||
*line = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = read_efi_options_variable(line);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read SystemdOptions EFI variable: %m");
|
||||
if (r == -ENOENT)
|
||||
return -ENODATA;
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
@ -52,6 +52,7 @@ bool is_efi_secure_boot_setup_mode(void);
|
||||
|
||||
int cache_efi_options_variable(void);
|
||||
int systemd_efi_options_variable(char **line);
|
||||
int systemd_efi_options_efivarfs_if_newer(char **line);
|
||||
|
||||
#else
|
||||
|
||||
@ -90,4 +91,8 @@ static inline int cache_efi_options_variable(void) {
|
||||
static inline int systemd_efi_options_variable(char **line) {
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
static inline int systemd_efi_options_efivarfs_if_newer(char **line) {
|
||||
return -ENODATA;
|
||||
}
|
||||
#endif
|
||||
|
@ -1860,14 +1860,25 @@ static int verb_systemd_efi_options(int argc, char *argv[], void *userdata) {
|
||||
int r;
|
||||
|
||||
if (argc == 1) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
_cleanup_free_ char *line = NULL, *new = NULL;
|
||||
|
||||
r = systemd_efi_options_variable(&line);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query SystemdOptions EFI variable: %m");
|
||||
|
||||
puts(line);
|
||||
if (r == -ENODATA)
|
||||
log_debug("No SystemdOptions EFI variable present in cache.");
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Failed to read SystemdOptions EFI variable from cache: %m");
|
||||
else
|
||||
puts(line);
|
||||
|
||||
r = systemd_efi_options_efivarfs_if_newer(&new);
|
||||
if (r == -ENODATA) {
|
||||
if (line)
|
||||
log_notice("Note: SystemdOptions EFI variable has been removed since boot.");
|
||||
} else if (r < 0)
|
||||
log_warning_errno(r, "Failed to check SystemdOptions EFI variable in efivarfs, ignoring: %m");
|
||||
else if (new && !streq_ptr(line, new))
|
||||
log_notice("Note: SystemdOptions EFI variable has been modified since boot. New value: %s",
|
||||
new);
|
||||
} else {
|
||||
r = efi_set_variable_string(EFI_SYSTEMD_VARIABLE(SystemdOptions), argv[1]);
|
||||
if (r < 0)
|
||||
|
Loading…
Reference in New Issue
Block a user