diff options
Diffstat (limited to 'drivers/firmware/efi/efivars.c')
-rw-r--r-- | drivers/firmware/efi/efivars.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 50ea412a25e6..06ec6ee1c58a 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c | |||
@@ -197,37 +197,48 @@ static ssize_t | |||
197 | efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) | 197 | efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) |
198 | { | 198 | { |
199 | struct efi_variable *new_var, *var = &entry->var; | 199 | struct efi_variable *new_var, *var = &entry->var; |
200 | efi_char16_t *name; | ||
201 | unsigned long size; | ||
202 | efi_guid_t vendor; | ||
203 | u32 attributes; | ||
204 | u8 *data; | ||
200 | int err; | 205 | int err; |
201 | 206 | ||
202 | if (count != sizeof(struct efi_variable)) | 207 | if (count != sizeof(struct efi_variable)) |
203 | return -EINVAL; | 208 | return -EINVAL; |
204 | 209 | ||
205 | new_var = (struct efi_variable *)buf; | 210 | new_var = (struct efi_variable *)buf; |
211 | |||
212 | attributes = new_var->Attributes; | ||
213 | vendor = new_var->VendorGuid; | ||
214 | name = new_var->VariableName; | ||
215 | size = new_var->DataSize; | ||
216 | data = new_var->Data; | ||
217 | |||
206 | /* | 218 | /* |
207 | * If only updating the variable data, then the name | 219 | * If only updating the variable data, then the name |
208 | * and guid should remain the same | 220 | * and guid should remain the same |
209 | */ | 221 | */ |
210 | if (memcmp(new_var->VariableName, var->VariableName, sizeof(var->VariableName)) || | 222 | if (memcmp(name, var->VariableName, sizeof(var->VariableName)) || |
211 | efi_guidcmp(new_var->VendorGuid, var->VendorGuid)) { | 223 | efi_guidcmp(vendor, var->VendorGuid)) { |
212 | printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n"); | 224 | printk(KERN_ERR "efivars: Cannot edit the wrong variable!\n"); |
213 | return -EINVAL; | 225 | return -EINVAL; |
214 | } | 226 | } |
215 | 227 | ||
216 | if ((new_var->DataSize <= 0) || (new_var->Attributes == 0)){ | 228 | if ((size <= 0) || (attributes == 0)){ |
217 | printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n"); | 229 | printk(KERN_ERR "efivars: DataSize & Attributes must be valid!\n"); |
218 | return -EINVAL; | 230 | return -EINVAL; |
219 | } | 231 | } |
220 | 232 | ||
221 | if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || | 233 | if ((attributes & ~EFI_VARIABLE_MASK) != 0 || |
222 | efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) { | 234 | efivar_validate(new_var, data, size) == false) { |
223 | printk(KERN_ERR "efivars: Malformed variable content\n"); | 235 | printk(KERN_ERR "efivars: Malformed variable content\n"); |
224 | return -EINVAL; | 236 | return -EINVAL; |
225 | } | 237 | } |
226 | 238 | ||
227 | memcpy(&entry->var, new_var, count); | 239 | memcpy(&entry->var, new_var, count); |
228 | 240 | ||
229 | err = efivar_entry_set(entry, new_var->Attributes, | 241 | err = efivar_entry_set(entry, attributes, size, data, NULL); |
230 | new_var->DataSize, new_var->Data, NULL); | ||
231 | if (err) { | 242 | if (err) { |
232 | printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err); | 243 | printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err); |
233 | return -EIO; | 244 | return -EIO; |
@@ -328,13 +339,20 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
328 | { | 339 | { |
329 | struct efi_variable *new_var = (struct efi_variable *)buf; | 340 | struct efi_variable *new_var = (struct efi_variable *)buf; |
330 | struct efivar_entry *new_entry; | 341 | struct efivar_entry *new_entry; |
342 | unsigned long size; | ||
343 | u32 attributes; | ||
344 | u8 *data; | ||
331 | int err; | 345 | int err; |
332 | 346 | ||
333 | if (!capable(CAP_SYS_ADMIN)) | 347 | if (!capable(CAP_SYS_ADMIN)) |
334 | return -EACCES; | 348 | return -EACCES; |
335 | 349 | ||
336 | if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 || | 350 | attributes = new_var->Attributes; |
337 | efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) { | 351 | size = new_var->DataSize; |
352 | data = new_var->Data; | ||
353 | |||
354 | if ((attributes & ~EFI_VARIABLE_MASK) != 0 || | ||
355 | efivar_validate(new_var, data, size) == false) { | ||
338 | printk(KERN_ERR "efivars: Malformed variable content\n"); | 356 | printk(KERN_ERR "efivars: Malformed variable content\n"); |
339 | return -EINVAL; | 357 | return -EINVAL; |
340 | } | 358 | } |
@@ -345,8 +363,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
345 | 363 | ||
346 | memcpy(&new_entry->var, new_var, sizeof(*new_var)); | 364 | memcpy(&new_entry->var, new_var, sizeof(*new_var)); |
347 | 365 | ||
348 | err = efivar_entry_set(new_entry, new_var->Attributes, new_var->DataSize, | 366 | err = efivar_entry_set(new_entry, attributes, size, |
349 | new_var->Data, &efivar_sysfs_list); | 367 | data, &efivar_sysfs_list); |
350 | if (err) { | 368 | if (err) { |
351 | if (err == -EEXIST) | 369 | if (err == -EEXIST) |
352 | err = -EINVAL; | 370 | err = -EINVAL; |
@@ -370,14 +388,18 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
370 | { | 388 | { |
371 | struct efi_variable *del_var = (struct efi_variable *)buf; | 389 | struct efi_variable *del_var = (struct efi_variable *)buf; |
372 | struct efivar_entry *entry; | 390 | struct efivar_entry *entry; |
391 | efi_char16_t *name; | ||
392 | efi_guid_t vendor; | ||
373 | int err = 0; | 393 | int err = 0; |
374 | 394 | ||
375 | if (!capable(CAP_SYS_ADMIN)) | 395 | if (!capable(CAP_SYS_ADMIN)) |
376 | return -EACCES; | 396 | return -EACCES; |
377 | 397 | ||
398 | name = del_var->VariableName; | ||
399 | vendor = del_var->VendorGuid; | ||
400 | |||
378 | efivar_entry_iter_begin(); | 401 | efivar_entry_iter_begin(); |
379 | entry = efivar_entry_find(del_var->VariableName, del_var->VendorGuid, | 402 | entry = efivar_entry_find(name, vendor, &efivar_sysfs_list, true); |
380 | &efivar_sysfs_list, true); | ||
381 | if (!entry) | 403 | if (!entry) |
382 | err = -EINVAL; | 404 | err = -EINVAL; |
383 | else if (__efivar_entry_delete(entry)) | 405 | else if (__efivar_entry_delete(entry)) |