[tip:x86/efi] efi, pstore: Read data from variable store before memcpy()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit-ID:  8a415b8c05f261a52f45f2271b6c4731376fd5b5
Gitweb:     http://git.kernel.org/tip/8a415b8c05f261a52f45f2271b6c4731376fd5b5
Author:     Matt Fleming <matt.fleming@xxxxxxxxx>
AuthorDate: Mon, 29 Apr 2013 20:08:02 +0100
Committer:  Matt Fleming <matt.fleming@xxxxxxxxx>
CommitDate: Tue, 30 Apr 2013 16:03:10 +0100

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@xxxxxxx>
Tested-by: Seiji Aguchi <seiji.aguchi@xxxxxxx>
Cc: Tony Luck <tony.luck@xxxxxxxxx>
Cc: Matthew Garrett <matthew.garrett@xxxxxxxxxx>
Signed-off-by: Matt Fleming <matt.fleming@xxxxxxxxx>
---
 drivers/firmware/efi/efi-pstore.c |  6 +++++-
 drivers/firmware/efi/vars.c       | 45 ++++++++++++++++++++-------------------
 include/linux/efi.h               |  3 ++-
 3 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index af45c42..67615d6 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)
 	} else
 		return 0;
 
-	__efivar_entry_size(entry, &size);
+	entry->var.DataSize = 1024;
+	__efivar_entry_get(entry, &entry->var.Attributes,
+			   &entry->var.DataSize, entry->var.Data);
+	size = entry->var.DataSize;
+
 	*cb_data->buf = kmalloc(size, GFP_KERNEL);
 	if (*cb_data->buf == NULL)
 		return -ENOMEM;
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index 1d80c1c..96d328b 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,
 EXPORT_SYMBOL_GPL(efivar_entry_find);
 
 /**
- * __efivar_entry_size - obtain the size of a variable
+ * efivar_entry_size - obtain the size of a variable
  * @entry: entry for this variable
  * @size: location to store the variable's size
- *
- * The caller MUST call efivar_entry_iter_begin() and
- * efivar_entry_iter_end() before and after the invocation of this
- * function, respectively.
  */
-int __efivar_entry_size(struct efivar_entry *entry, unsigned long *size)
+int efivar_entry_size(struct efivar_entry *entry, unsigned long *size)
 {
 	const struct efivar_operations *ops = __efivars->ops;
 	efi_status_t status;
 
-	WARN_ON(!spin_is_locked(&__efivars->lock));
-
 	*size = 0;
+
+	spin_lock_irq(&__efivars->lock);
 	status = ops->get_variable(entry->var.VariableName,
 				   &entry->var.VendorGuid, NULL, size, NULL);
+	spin_unlock_irq(&__efivars->lock);
+
 	if (status != EFI_BUFFER_TOO_SMALL)
 		return efi_status_to_err(status);
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(__efivar_entry_size);
+EXPORT_SYMBOL_GPL(efivar_entry_size);
 
 /**
- * efivar_entry_size - obtain the size of a variable
- * @entry: entry for this variable
- * @size: location to store the variable's size
+ * __efivar_entry_get - call get_variable()
+ * @entry: read data for this variable
+ * @attributes: variable attributes
+ * @size: size of @data buffer
+ * @data: buffer to store variable data
+ *
+ * The caller MUST call efivar_entry_iter_begin() and
+ * efivar_entry_iter_end() before and after the invocation of this
+ * function, respectively.
  */
-int efivar_entry_size(struct efivar_entry *entry, unsigned long *size)
+int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
+		       unsigned long *size, void *data)
 {
 	const struct efivar_operations *ops = __efivars->ops;
 	efi_status_t status;
 
-	*size = 0;
+	WARN_ON(!spin_is_locked(&__efivars->lock));
 
-	spin_lock_irq(&__efivars->lock);
 	status = ops->get_variable(entry->var.VariableName,
-				   &entry->var.VendorGuid, NULL, size, NULL);
-	spin_unlock_irq(&__efivars->lock);
-
-	if (status != EFI_BUFFER_TOO_SMALL)
-		return efi_status_to_err(status);
+				   &entry->var.VendorGuid,
+				   attributes, size, data);
 
-	return 0;
+	return efi_status_to_err(status);
 }
-EXPORT_SYMBOL_GPL(efivar_entry_size);
+EXPORT_SYMBOL_GPL(__efivar_entry_get);
 
 /**
  * efivar_entry_get - call get_variable()
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 3f7257f..2bc0ad7 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -808,8 +808,9 @@ void efivar_entry_remove(struct efivar_entry *entry);
 int __efivar_entry_delete(struct efivar_entry *entry);
 int efivar_entry_delete(struct efivar_entry *entry);
 
-int __efivar_entry_size(struct efivar_entry *entry, unsigned long *size);
 int efivar_entry_size(struct efivar_entry *entry, unsigned long *size);
+int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
+		       unsigned long *size, void *data);
 int efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
 		     unsigned long *size, void *data);
 int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
--
To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Stable Commits]     [Linux Stable Kernel]     [Linux Kernel]     [Linux USB Devel]     [Linux Video &Media]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux