efivars: Respect "block" flag in efivar_entry_set_safe()

When the "block" flag is false, the old code would sometimes still call
check_var_size(), which wrongly tells ->query_variable_store() that it can
block.

As far as I can tell, this can't really materialize as a bug at the moment,
because ->query_variable_store only does something on X86 with generic EFI,
and in that configuration we always take the efivar_entry_set_nonblocking()
path.

Fixes: ca0e30dcaa ("efi: Add nonblocking option to efi_query_variable_store()")
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220218180559.1432559-1-jannh@google.com
This commit is contained in:
Jann Horn 2022-02-18 19:05:59 +01:00 committed by Ard Biesheuvel
parent dcf0c83885
commit 258dd90202

View File

@ -742,6 +742,7 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
{ {
const struct efivar_operations *ops; const struct efivar_operations *ops;
efi_status_t status; efi_status_t status;
unsigned long varsize;
if (!__efivars) if (!__efivars)
return -EINVAL; return -EINVAL;
@ -764,15 +765,17 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
return efivar_entry_set_nonblocking(name, vendor, attributes, return efivar_entry_set_nonblocking(name, vendor, attributes,
size, data); size, data);
varsize = size + ucs2_strsize(name, 1024);
if (!block) { if (!block) {
if (down_trylock(&efivars_lock)) if (down_trylock(&efivars_lock))
return -EBUSY; return -EBUSY;
status = check_var_size_nonblocking(attributes, varsize);
} else { } else {
if (down_interruptible(&efivars_lock)) if (down_interruptible(&efivars_lock))
return -EINTR; return -EINTR;
status = check_var_size(attributes, varsize);
} }
status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
up(&efivars_lock); up(&efivars_lock);
return -ENOSPC; return -ENOSPC;