diff options
author | Matt Fleming <matt.fleming@intel.com> | 2013-04-29 15:08:02 -0400 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2013-04-30 11:03:10 -0400 |
commit | 8a415b8c05f261a52f45f2271b6c4731376fd5b5 (patch) | |
tree | de233c9382c3f4a08fcdd1b26be38810fdf2ce25 /drivers/firmware | |
parent | 12abcfde1ad3ee9bed726d25fdd4eeb31026b187 (diff) |
efi, pstore: Read data from variable store before memcpy()
Seiji reported getting empty dmesg-* files, because the data was never
actually read in efi_pstore_read_func(), and so the memcpy() was copying
garbage data.
This patch necessitated adding __efivar_entry_get() which is callable
between efivar_entry_iter_{begin,end}(). We can also delete
__efivar_entry_size() because efi_pstore_read_func() was the only
caller.
Reported-by: Seiji Aguchi <seiji.aguchi@hds.com>
Tested-by: Seiji Aguchi <seiji.aguchi@hds.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Matthew Garrett <matthew.garrett@nebula.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 6 | ||||
-rw-r--r-- | drivers/firmware/efi/vars.c | 45 |
2 files changed, 28 insertions, 23 deletions
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index af45c42086e1..67615d6d038d 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c | |||
@@ -73,7 +73,11 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) | |||
73 | } else | 73 | } else |
74 | return 0; | 74 | return 0; |
75 | 75 | ||
76 | __efivar_entry_size(entry, &size); | 76 | entry->var.DataSize = 1024; |
77 | __efivar_entry_get(entry, &entry->var.Attributes, | ||
78 | &entry->var.DataSize, entry->var.Data); | ||
79 | size = entry->var.DataSize; | ||
80 | |||
77 | *cb_data->buf = kmalloc(size, GFP_KERNEL); | 81 | *cb_data->buf = kmalloc(size, GFP_KERNEL); |
78 | if (*cb_data->buf == NULL) | 82 | if (*cb_data->buf == NULL) |
79 | return -ENOMEM; | 83 | return -ENOMEM; |
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index 1d80c1ca39c5..96d328b21c3e 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c | |||
@@ -689,54 +689,55 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid, | |||
689 | EXPORT_SYMBOL_GPL(efivar_entry_find); | 689 | EXPORT_SYMBOL_GPL(efivar_entry_find); |
690 | 690 | ||
691 | /** | 691 | /** |
692 | * __efivar_entry_size - obtain the size of a variable | 692 | * efivar_entry_size - obtain the size of a variable |
693 | * @entry: entry for this variable | 693 | * @entry: entry for this variable |
694 | * @size: location to store the variable's size | 694 | * @size: location to store the variable's size |
695 | * | ||
696 | * The caller MUST call efivar_entry_iter_begin() and | ||
697 | * efivar_entry_iter_end() before and after the invocation of this | ||
698 | * function, respectively. | ||
699 | */ | 695 | */ |
700 | int __efivar_entry_size(struct efivar_entry *entry, unsigned long *size) | 696 | int efivar_entry_size(struct efivar_entry *entry, unsigned long *size) |
701 | { | 697 | { |
702 | const struct efivar_operations *ops = __efivars->ops; | 698 | const struct efivar_operations *ops = __efivars->ops; |
703 | efi_status_t status; | 699 | efi_status_t status; |
704 | 700 | ||
705 | WARN_ON(!spin_is_locked(&__efivars->lock)); | ||
706 | |||
707 | *size = 0; | 701 | *size = 0; |
702 | |||
703 | spin_lock_irq(&__efivars->lock); | ||
708 | status = ops->get_variable(entry->var.VariableName, | 704 | status = ops->get_variable(entry->var.VariableName, |
709 | &entry->var.VendorGuid, NULL, size, NULL); | 705 | &entry->var.VendorGuid, NULL, size, NULL); |
706 | spin_unlock_irq(&__efivars->lock); | ||
707 | |||
710 | if (status != EFI_BUFFER_TOO_SMALL) | 708 | if (status != EFI_BUFFER_TOO_SMALL) |
711 | return efi_status_to_err(status); | 709 | return efi_status_to_err(status); |
712 | 710 | ||
713 | return 0; | 711 | return 0; |
714 | } | 712 | } |
715 | EXPORT_SYMBOL_GPL(__efivar_entry_size); | 713 | EXPORT_SYMBOL_GPL(efivar_entry_size); |
716 | 714 | ||
717 | /** | 715 | /** |
718 | * efivar_entry_size - obtain the size of a variable | 716 | * __efivar_entry_get - call get_variable() |
719 | * @entry: entry for this variable | 717 | * @entry: read data for this variable |
720 | * @size: location to store the variable's size | 718 | * @attributes: variable attributes |
719 | * @size: size of @data buffer | ||
720 | * @data: buffer to store variable data | ||
721 | * | ||
722 | * The caller MUST call efivar_entry_iter_begin() and | ||
723 | * efivar_entry_iter_end() before and after the invocation of this | ||
724 | * function, respectively. | ||
721 | */ | 725 | */ |
722 | int efivar_entry_size(struct efivar_entry *entry, unsigned long *size) | 726 | int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes, |
727 | unsigned long *size, void *data) | ||
723 | { | 728 | { |
724 | const struct efivar_operations *ops = __efivars->ops; | 729 | const struct efivar_operations *ops = __efivars->ops; |
725 | efi_status_t status; | 730 | efi_status_t status; |
726 | 731 | ||
727 | *size = 0; | 732 | WARN_ON(!spin_is_locked(&__efivars->lock)); |
728 | 733 | ||
729 | spin_lock_irq(&__efivars->lock); | ||
730 | status = ops->get_variable(entry->var.VariableName, | 734 | status = ops->get_variable(entry->var.VariableName, |
731 | &entry->var.VendorGuid, NULL, size, NULL); | 735 | &entry->var.VendorGuid, |
732 | spin_unlock_irq(&__efivars->lock); | 736 | attributes, size, data); |
733 | |||
734 | if (status != EFI_BUFFER_TOO_SMALL) | ||
735 | return efi_status_to_err(status); | ||
736 | 737 | ||
737 | return 0; | 738 | return efi_status_to_err(status); |
738 | } | 739 | } |
739 | EXPORT_SYMBOL_GPL(efivar_entry_size); | 740 | EXPORT_SYMBOL_GPL(__efivar_entry_get); |
740 | 741 | ||
741 | /** | 742 | /** |
742 | * efivar_entry_get - call get_variable() | 743 | * efivar_entry_get - call get_variable() |