diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 47408e8..4047450 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -1123,8 +1123,8 @@ int register_efivars(struct efivars *efivars, struct kobject *parent_kobj) { efi_status_t status = EFI_NOT_FOUND; - efi_guid_t vendor_guid; - efi_char16_t *variable_name; + efi_guid_t vendor_guid, prev_guid; + efi_char16_t *variable_name, *prev_name; unsigned long variable_name_size = 1024; int error = 0; @@ -1134,6 +1134,14 @@ int register_efivars(struct efivars *efivars, return -ENOMEM; } + prev_name = kzalloc(variable_name_size, GFP_KERNEL); + if (!prev_name) { + printk(KERN_ERR "efivars: Memory allocation failed.\n"); + return -ENOMEM; + } + + memset(&prev_guid, 0, sizeof(prev_guid)); + spin_lock_init(&efivars->lock); INIT_LIST_HEAD(&efivars->list); efivars->ops = ops; @@ -1158,6 +1166,21 @@ int register_efivars(struct efivars *efivars, &vendor_guid); switch (status) { case EFI_SUCCESS: + /* + * Check for bugs in the firmware where + * GetNextVariableName() always returns the same + * variable. + */ + if (!memcmp(prev_name, variable_name, variable_name_size) && + !(memcmp(&prev_guid, &vendor_guid, sizeof(vendor_guid)))) { + printk(KERN_WARNING "efivars: Duplicate variable name detected\n"); + status = EFI_NOT_FOUND; + break; + } + + memcpy(prev_name, variable_name, variable_name_size); + memcpy(&prev_guid, &vendor_guid, sizeof(vendor_guid)); + efivar_create_sysfs_entry(efivars, variable_name_size, variable_name,