Commit b67775e1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'efi-urgent-2020-03-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull EFI fixes from Thomas Gleixner:
 "Two EFI fixes:

   - Prevent a race and buffer overflow in the sysfs efivars interface
     which causes kernel memory corruption.

   - Add the missing NULL pointer checks in efivar_store_raw()"

* tag 'efi-urgent-2020-03-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  efi: Add a sanity check to efivar_store_raw()
  efi: Fix a race and a buffer overflow while reading efivars via sysfs
parents de28a65c d6c066fd
Loading
Loading
Loading
Loading
+23 −9
Original line number Diff line number Diff line
@@ -83,13 +83,16 @@ static ssize_t
efivar_attr_read(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	unsigned long size = sizeof(var->Data);
	char *str = buf;
	int ret;

	if (!entry || !buf)
		return -EINVAL;

	var->DataSize = 1024;
	if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
	var->DataSize = size;
	if (ret)
		return -EIO;

	if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
@@ -116,13 +119,16 @@ static ssize_t
efivar_size_read(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	unsigned long size = sizeof(var->Data);
	char *str = buf;
	int ret;

	if (!entry || !buf)
		return -EINVAL;

	var->DataSize = 1024;
	if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
	var->DataSize = size;
	if (ret)
		return -EIO;

	str += sprintf(str, "0x%lx\n", var->DataSize);
@@ -133,12 +139,15 @@ static ssize_t
efivar_data_read(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	unsigned long size = sizeof(var->Data);
	int ret;

	if (!entry || !buf)
		return -EINVAL;

	var->DataSize = 1024;
	if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
	var->DataSize = size;
	if (ret)
		return -EIO;

	memcpy(buf, var->Data, var->DataSize);
@@ -199,6 +208,9 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
	u8 *data;
	int err;

	if (!entry || !buf)
		return -EINVAL;

	if (in_compat_syscall()) {
		struct compat_efi_variable *compat;

@@ -250,14 +262,16 @@ efivar_show_raw(struct efivar_entry *entry, char *buf)
{
	struct efi_variable *var = &entry->var;
	struct compat_efi_variable *compat;
	unsigned long datasize = sizeof(var->Data);
	size_t size;
	int ret;

	if (!entry || !buf)
		return 0;

	var->DataSize = 1024;
	if (efivar_entry_get(entry, &entry->var.Attributes,
			     &entry->var.DataSize, entry->var.Data))
	ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data);
	var->DataSize = datasize;
	if (ret)
		return -EIO;

	if (in_compat_syscall()) {