Commit a74e2a9e authored by Peter Jones's avatar Peter Jones Committed by Greg Kroah-Hartman

efi: Make our variable validation list include the guid

commit 8282f5d9 upstream.

All the variables in this list so far are defined to be in the global
namespace in the UEFI spec, so this just further ensures we're
validating the variables we think we are.

Including the guid for entries will become more important in future
patches when we decide whether or not to allow deletion of variables
based on presence in this list.
Signed-off-by: default avatarPeter Jones <pjones@redhat.com>
Tested-by: default avatarLee, Chun-Yi <jlee@suse.com>
Acked-by: default avatarMatthew Garrett <mjg59@coreos.com>
Signed-off-by: default avatarMatt Fleming <matt@codeblueprint.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3285d6ab
...@@ -219,7 +219,8 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) ...@@ -219,7 +219,8 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
} }
if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
efivar_validate(new_var->VariableName, new_var->Data, new_var->DataSize) == false) { efivar_validate(new_var->VendorGuid, new_var->VariableName,
new_var->Data, new_var->DataSize) == false) {
printk(KERN_ERR "efivars: Malformed variable content\n"); printk(KERN_ERR "efivars: Malformed variable content\n");
return -EINVAL; return -EINVAL;
} }
...@@ -334,7 +335,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, ...@@ -334,7 +335,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
return -EACCES; return -EACCES;
if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
efivar_validate(new_var->VariableName, new_var->Data, new_var->DataSize) == false) { efivar_validate(new_var->VendorGuid, new_var->VariableName,
new_var->Data, new_var->DataSize) == false) {
printk(KERN_ERR "efivars: Malformed variable content\n"); printk(KERN_ERR "efivars: Malformed variable content\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -165,31 +165,42 @@ validate_ascii_string(efi_char16_t *var_name, int match, u8 *buffer, ...@@ -165,31 +165,42 @@ validate_ascii_string(efi_char16_t *var_name, int match, u8 *buffer,
} }
struct variable_validate { struct variable_validate {
efi_guid_t vendor;
char *name; char *name;
bool (*validate)(efi_char16_t *var_name, int match, u8 *data, bool (*validate)(efi_char16_t *var_name, int match, u8 *data,
unsigned long len); unsigned long len);
}; };
/*
* This is the list of variables we need to validate.
*
* If it has a validate() method that's not NULL, it'll go into the
* validation routine. If not, it is assumed valid.
*
* Note that it's sorted by {vendor,name}, but globbed names must come after
* any other name with the same prefix.
*/
static const struct variable_validate variable_validate[] = { static const struct variable_validate variable_validate[] = {
{ "BootNext", validate_uint16 }, { EFI_GLOBAL_VARIABLE_GUID, "BootNext", validate_uint16 },
{ "BootOrder", validate_boot_order }, { EFI_GLOBAL_VARIABLE_GUID, "BootOrder", validate_boot_order },
{ "DriverOrder", validate_boot_order }, { EFI_GLOBAL_VARIABLE_GUID, "Boot*", validate_load_option },
{ "Boot*", validate_load_option }, { EFI_GLOBAL_VARIABLE_GUID, "DriverOrder", validate_boot_order },
{ "Driver*", validate_load_option }, { EFI_GLOBAL_VARIABLE_GUID, "Driver*", validate_load_option },
{ "ConIn", validate_device_path }, { EFI_GLOBAL_VARIABLE_GUID, "ConIn", validate_device_path },
{ "ConInDev", validate_device_path }, { EFI_GLOBAL_VARIABLE_GUID, "ConInDev", validate_device_path },
{ "ConOut", validate_device_path }, { EFI_GLOBAL_VARIABLE_GUID, "ConOut", validate_device_path },
{ "ConOutDev", validate_device_path }, { EFI_GLOBAL_VARIABLE_GUID, "ConOutDev", validate_device_path },
{ "ErrOut", validate_device_path }, { EFI_GLOBAL_VARIABLE_GUID, "ErrOut", validate_device_path },
{ "ErrOutDev", validate_device_path }, { EFI_GLOBAL_VARIABLE_GUID, "ErrOutDev", validate_device_path },
{ "Timeout", validate_uint16 }, { EFI_GLOBAL_VARIABLE_GUID, "Lang", validate_ascii_string },
{ "Lang", validate_ascii_string }, { EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
{ "PlatformLang", validate_ascii_string }, { EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
{ "", NULL }, { NULL_GUID, "", NULL },
}; };
bool bool
efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long data_size) efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
unsigned long data_size)
{ {
int i; int i;
unsigned long utf8_size; unsigned long utf8_size;
...@@ -203,9 +214,12 @@ efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long data_size) ...@@ -203,9 +214,12 @@ efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long data_size)
ucs2_as_utf8(utf8_name, var_name, utf8_size); ucs2_as_utf8(utf8_name, var_name, utf8_size);
utf8_name[utf8_size] = '\0'; utf8_name[utf8_size] = '\0';
for (i = 0; variable_validate[i].validate != NULL; i++) { for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
const char *name = variable_validate[i].name; const char *name = variable_validate[i].name;
int match; int match = 0;
if (efi_guidcmp(vendor, variable_validate[i].vendor))
continue;
for (match = 0; ; match++) { for (match = 0; ; match++) {
char c = name[match]; char c = name[match];
...@@ -815,7 +829,7 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes, ...@@ -815,7 +829,7 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
*set = false; *set = false;
if (efivar_validate(name, data, *size) == false) if (efivar_validate(*vendor, name, data, *size) == false)
return -EINVAL; return -EINVAL;
/* /*
......
...@@ -866,7 +866,8 @@ int efivar_entry_iter(int (*func)(struct efivar_entry *, void *), ...@@ -866,7 +866,8 @@ int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid, struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
struct list_head *head, bool remove); struct list_head *head, bool remove);
bool efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len); bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
unsigned long data_size);
extern struct work_struct efivar_work; extern struct work_struct efivar_work;
void efivar_run_worker(void); void efivar_run_worker(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment