aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Jones <pjones@redhat.com>2016-02-08 14:48:14 -0500
committerMatt Fleming <matt@codeblueprint.co.uk>2016-02-10 11:25:31 -0500
commit8282f5d9c17fe15a9e658c06e3f343efae1a2a2f (patch)
tree9d2adb18786fde7115c0928068e29c4e2bd5373c
parent3dcb1f55dfc7631695e69df4a0d589ce5274bd07 (diff)
efi: Make our variable validation list include the guid
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: Peter Jones <pjones@redhat.com> Tested-by: Lee, Chun-Yi <jlee@suse.com> Acked-by: Matthew Garrett <mjg59@coreos.com> Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
-rw-r--r--drivers/firmware/efi/efivars.c5
-rw-r--r--drivers/firmware/efi/vars.c52
-rw-r--r--include/linux/efi.h3
3 files changed, 38 insertions, 22 deletions
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
index f4ff8abc5f3e..10e6774ab2a2 100644
--- a/drivers/firmware/efi/efivars.c
+++ b/drivers/firmware/efi/efivars.c
@@ -221,7 +221,7 @@ sanity_check(struct efi_variable *var, efi_char16_t *name, efi_guid_t vendor,
221 } 221 }
222 222
223 if ((attributes & ~EFI_VARIABLE_MASK) != 0 || 223 if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
224 efivar_validate(name, data, size) == false) { 224 efivar_validate(vendor, name, data, size) == false) {
225 printk(KERN_ERR "efivars: Malformed variable content\n"); 225 printk(KERN_ERR "efivars: Malformed variable content\n");
226 return -EINVAL; 226 return -EINVAL;
227 } 227 }
@@ -447,7 +447,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
447 } 447 }
448 448
449 if ((attributes & ~EFI_VARIABLE_MASK) != 0 || 449 if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
450 efivar_validate(name, data, size) == false) { 450 efivar_validate(new_var->VendorGuid, name, data,
451 size) == false) {
451 printk(KERN_ERR "efivars: Malformed variable content\n"); 452 printk(KERN_ERR "efivars: Malformed variable content\n");
452 return -EINVAL; 453 return -EINVAL;
453 } 454 }
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index 5c5fde3e6c37..9a53da21e7b6 100644
--- a/drivers/firmware/efi/vars.c
+++ b/drivers/firmware/efi/vars.c
@@ -165,31 +165,42 @@ validate_ascii_string(efi_char16_t *var_name, int match, u8 *buffer,
165} 165}
166 166
167struct variable_validate { 167struct variable_validate {
168 efi_guid_t vendor;
168 char *name; 169 char *name;
169 bool (*validate)(efi_char16_t *var_name, int match, u8 *data, 170 bool (*validate)(efi_char16_t *var_name, int match, u8 *data,
170 unsigned long len); 171 unsigned long len);
171}; 172};
172 173
174/*
175 * This is the list of variables we need to validate.
176 *
177 * If it has a validate() method that's not NULL, it'll go into the
178 * validation routine. If not, it is assumed valid.
179 *
180 * Note that it's sorted by {vendor,name}, but globbed names must come after
181 * any other name with the same prefix.
182 */
173static const struct variable_validate variable_validate[] = { 183static const struct variable_validate variable_validate[] = {
174 { "BootNext", validate_uint16 }, 184 { EFI_GLOBAL_VARIABLE_GUID, "BootNext", validate_uint16 },
175 { "BootOrder", validate_boot_order }, 185 { EFI_GLOBAL_VARIABLE_GUID, "BootOrder", validate_boot_order },
176 { "DriverOrder", validate_boot_order }, 186 { EFI_GLOBAL_VARIABLE_GUID, "Boot*", validate_load_option },
177 { "Boot*", validate_load_option }, 187 { EFI_GLOBAL_VARIABLE_GUID, "DriverOrder", validate_boot_order },
178 { "Driver*", validate_load_option }, 188 { EFI_GLOBAL_VARIABLE_GUID, "Driver*", validate_load_option },
179 { "ConIn", validate_device_path }, 189 { EFI_GLOBAL_VARIABLE_GUID, "ConIn", validate_device_path },
180 { "ConInDev", validate_device_path }, 190 { EFI_GLOBAL_VARIABLE_GUID, "ConInDev", validate_device_path },
181 { "ConOut", validate_device_path }, 191 { EFI_GLOBAL_VARIABLE_GUID, "ConOut", validate_device_path },
182 { "ConOutDev", validate_device_path }, 192 { EFI_GLOBAL_VARIABLE_GUID, "ConOutDev", validate_device_path },
183 { "ErrOut", validate_device_path }, 193 { EFI_GLOBAL_VARIABLE_GUID, "ErrOut", validate_device_path },
184 { "ErrOutDev", validate_device_path }, 194 { EFI_GLOBAL_VARIABLE_GUID, "ErrOutDev", validate_device_path },
185 { "Timeout", validate_uint16 }, 195 { EFI_GLOBAL_VARIABLE_GUID, "Lang", validate_ascii_string },
186 { "Lang", validate_ascii_string }, 196 { EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
187 { "PlatformLang", validate_ascii_string }, 197 { EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
188 { "", NULL }, 198 { NULL_GUID, "", NULL },
189}; 199};
190 200
191bool 201bool
192efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long data_size) 202efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
203 unsigned long data_size)
193{ 204{
194 int i; 205 int i;
195 unsigned long utf8_size; 206 unsigned long utf8_size;
@@ -203,9 +214,12 @@ efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long data_size)
203 ucs2_as_utf8(utf8_name, var_name, utf8_size); 214 ucs2_as_utf8(utf8_name, var_name, utf8_size);
204 utf8_name[utf8_size] = '\0'; 215 utf8_name[utf8_size] = '\0';
205 216
206 for (i = 0; variable_validate[i].validate != NULL; i++) { 217 for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
207 const char *name = variable_validate[i].name; 218 const char *name = variable_validate[i].name;
208 int match; 219 int match = 0;
220
221 if (efi_guidcmp(vendor, variable_validate[i].vendor))
222 continue;
209 223
210 for (match = 0; ; match++) { 224 for (match = 0; ; match++) {
211 char c = name[match]; 225 char c = name[match];
@@ -862,7 +876,7 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
862 876
863 *set = false; 877 *set = false;
864 878
865 if (efivar_validate(name, data, *size) == false) 879 if (efivar_validate(*vendor, name, data, *size) == false)
866 return -EINVAL; 880 return -EINVAL;
867 881
868 /* 882 /*
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 569b5a866bb1..16ca611aabc8 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1199,7 +1199,8 @@ int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
1199struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid, 1199struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
1200 struct list_head *head, bool remove); 1200 struct list_head *head, bool remove);
1201 1201
1202bool efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len); 1202bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
1203 unsigned long data_size);
1203 1204
1204extern struct work_struct efivar_work; 1205extern struct work_struct efivar_work;
1205void efivar_run_worker(void); 1206void efivar_run_worker(void);