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: Michel Lespinasse <walken@google.com> Tested-by: Michel 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: Matt Fleming <matt.fleming@intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
37b7f3c765
commit
f464246d85
|
@ -1628,10 +1628,11 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
|
|||
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 efivars *efivars = &__efivars;
|
||||
unsigned long strsize1, strsize2;
|
||||
bool found = false;
|
||||
|
||||
|
@ -1703,8 +1704,8 @@ static void efivar_update_sysfs_entries(struct work_struct *work)
|
|||
if (status != EFI_SUCCESS) {
|
||||
break;
|
||||
} else {
|
||||
if (!variable_is_present(variable_name,
|
||||
&vendor)) {
|
||||
if (!variable_is_present(efivars,
|
||||
variable_name, &vendor)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -2008,7 +2009,8 @@ int register_efivars(struct efivars *efivars,
|
|||
* we'll ever see a different variable name,
|
||||
* 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,
|
||||
variable_name_size);
|
||||
status = EFI_NOT_FOUND;
|
||||
|
|
Loading…
Reference in New Issue