Commit f464246d authored by Matt Fleming's avatar Matt Fleming Committed by Linus Torvalds

efivars: only check for duplicates on the registered list

variable_is_present() accesses '__efivars' directly, but when called via
gsmi_init() Michel reports observing the following crash,

  BUG: unable to handle kernel NULL pointer dereference at (null)
  IP: variable_is_present+0x55/0x170
  Call Trace:
    register_efivars+0x106/0x370
    gsmi_init+0x2ad/0x3da
    do_one_initcall+0x3f/0x170

The reason for the crash is that '__efivars' hasn't been initialised nor
has it been registered with register_efivars() by the time the google
EFI SMI driver runs.  The gsmi code uses its own struct efivars, and
therefore, a different variable list.  Fix the above crash by passing
the registered struct efivars to variable_is_present(), so that we
traverse the correct list.
Reported-by: default avatarMichel Lespinasse <walken@google.com>
Tested-by: default avatarMichel Lespinasse <walken@google.com>
Cc: Mike Waychison <mikew@google.com>
Cc: Matthew Garrett <matthew.garrett@nebula.com>
Cc: Seiji Aguchi <seiji.aguchi@hds.com>
Signed-off-by: default avatarMatt Fleming <matt.fleming@intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 37b7f3c7
...@@ -1628,10 +1628,11 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, ...@@ -1628,10 +1628,11 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
return count; return count;
} }
static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor) static bool variable_is_present(struct efivars *efivars,
efi_char16_t *variable_name,
efi_guid_t *vendor)
{ {
struct efivar_entry *entry, *n; struct efivar_entry *entry, *n;
struct efivars *efivars = &__efivars;
unsigned long strsize1, strsize2; unsigned long strsize1, strsize2;
bool found = false; bool found = false;
...@@ -1703,8 +1704,8 @@ static void efivar_update_sysfs_entries(struct work_struct *work) ...@@ -1703,8 +1704,8 @@ static void efivar_update_sysfs_entries(struct work_struct *work)
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
break; break;
} else { } else {
if (!variable_is_present(variable_name, if (!variable_is_present(efivars,
&vendor)) { variable_name, &vendor)) {
found = true; found = true;
break; break;
} }
...@@ -2008,7 +2009,8 @@ int register_efivars(struct efivars *efivars, ...@@ -2008,7 +2009,8 @@ int register_efivars(struct efivars *efivars,
* we'll ever see a different variable name, * we'll ever see a different variable name,
* and may end up looping here forever. * and may end up looping here forever.
*/ */
if (variable_is_present(variable_name, &vendor_guid)) { if (variable_is_present(efivars, variable_name,
&vendor_guid)) {
dup_variable_bug(variable_name, &vendor_guid, dup_variable_bug(variable_name, &vendor_guid,
variable_name_size); variable_name_size);
status = EFI_NOT_FOUND; status = EFI_NOT_FOUND;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment