aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/firmware/efivars.c106
1 files changed, 79 insertions, 27 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 7320bf891706..0d504971ed4c 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -426,6 +426,44 @@ get_var_data(struct efivars *efivars, struct efi_variable *var)
426 return status; 426 return status;
427} 427}
428 428
429static efi_status_t
430check_var_size_locked(struct efivars *efivars, u32 attributes,
431 unsigned long size)
432{
433 u64 storage_size, remaining_size, max_size;
434 efi_status_t status;
435 const struct efivar_operations *fops = efivars->ops;
436
437 if (!efivars->ops->query_variable_info)
438 return EFI_UNSUPPORTED;
439
440 status = fops->query_variable_info(attributes, &storage_size,
441 &remaining_size, &max_size);
442
443 if (status != EFI_SUCCESS)
444 return status;
445
446 if (!storage_size || size > remaining_size || size > max_size ||
447 (remaining_size - size) < (storage_size / 2))
448 return EFI_OUT_OF_RESOURCES;
449
450 return status;
451}
452
453
454static efi_status_t
455check_var_size(struct efivars *efivars, u32 attributes, unsigned long size)
456{
457 efi_status_t status;
458 unsigned long flags;
459
460 spin_lock_irqsave(&efivars->lock, flags);
461 status = check_var_size_locked(efivars, attributes, size);
462 spin_unlock_irqrestore(&efivars->lock, flags);
463
464 return status;
465}
466
429static ssize_t 467static ssize_t
430efivar_guid_read(struct efivar_entry *entry, char *buf) 468efivar_guid_read(struct efivar_entry *entry, char *buf)
431{ 469{
@@ -547,11 +585,16 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
547 } 585 }
548 586
549 spin_lock_irq(&efivars->lock); 587 spin_lock_irq(&efivars->lock);
550 status = efivars->ops->set_variable(new_var->VariableName, 588
551 &new_var->VendorGuid, 589 status = check_var_size_locked(efivars, new_var->Attributes,
552 new_var->Attributes, 590 new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
553 new_var->DataSize, 591
554 new_var->Data); 592 if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
593 status = efivars->ops->set_variable(new_var->VariableName,
594 &new_var->VendorGuid,
595 new_var->Attributes,
596 new_var->DataSize,
597 new_var->Data);
555 598
556 spin_unlock_irq(&efivars->lock); 599 spin_unlock_irq(&efivars->lock);
557 600
@@ -702,8 +745,7 @@ static ssize_t efivarfs_file_write(struct file *file,
702 u32 attributes; 745 u32 attributes;
703 struct inode *inode = file->f_mapping->host; 746 struct inode *inode = file->f_mapping->host;
704 unsigned long datasize = count - sizeof(attributes); 747 unsigned long datasize = count - sizeof(attributes);
705 unsigned long newdatasize; 748 unsigned long newdatasize, varsize;
706 u64 storage_size, remaining_size, max_size;
707 ssize_t bytes = 0; 749 ssize_t bytes = 0;
708 750
709 if (count < sizeof(attributes)) 751 if (count < sizeof(attributes))
@@ -722,28 +764,18 @@ static ssize_t efivarfs_file_write(struct file *file,
722 * amounts of memory. Pick a default size of 64K if 764 * amounts of memory. Pick a default size of 64K if
723 * QueryVariableInfo() isn't supported by the firmware. 765 * QueryVariableInfo() isn't supported by the firmware.
724 */ 766 */
725 spin_lock_irq(&efivars->lock);
726 767
727 if (!efivars->ops->query_variable_info) 768 varsize = datasize + utf16_strsize(var->var.VariableName, 1024);
728 status = EFI_UNSUPPORTED; 769 status = check_var_size(efivars, attributes, varsize);
729 else {
730 const struct efivar_operations *fops = efivars->ops;
731 status = fops->query_variable_info(attributes, &storage_size,
732 &remaining_size, &max_size);
733 }
734
735 spin_unlock_irq(&efivars->lock);
736 770
737 if (status != EFI_SUCCESS) { 771 if (status != EFI_SUCCESS) {
738 if (status != EFI_UNSUPPORTED) 772 if (status != EFI_UNSUPPORTED)
739 return efi_status_to_err(status); 773 return efi_status_to_err(status);
740 774
741 remaining_size = 65536; 775 if (datasize > 65536)
776 return -ENOSPC;
742 } 777 }
743 778
744 if (datasize > remaining_size)
745 return -ENOSPC;
746
747 data = kmalloc(datasize, GFP_KERNEL); 779 data = kmalloc(datasize, GFP_KERNEL);
748 if (!data) 780 if (!data)
749 return -ENOMEM; 781 return -ENOMEM;
@@ -765,6 +797,19 @@ static ssize_t efivarfs_file_write(struct file *file,
765 */ 797 */
766 spin_lock_irq(&efivars->lock); 798 spin_lock_irq(&efivars->lock);
767 799
800 /*
801 * Ensure that the available space hasn't shrunk below the safe level
802 */
803
804 status = check_var_size_locked(efivars, attributes, varsize);
805
806 if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) {
807 spin_unlock_irq(&efivars->lock);
808 kfree(data);
809
810 return efi_status_to_err(status);
811 }
812
768 status = efivars->ops->set_variable(var->var.VariableName, 813 status = efivars->ops->set_variable(var->var.VariableName,
769 &var->var.VendorGuid, 814 &var->var.VendorGuid,
770 attributes, datasize, 815 attributes, datasize,
@@ -1345,7 +1390,6 @@ static int efi_pstore_write(enum pstore_type_id type,
1345 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 1390 efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
1346 struct efivars *efivars = psi->data; 1391 struct efivars *efivars = psi->data;
1347 int i, ret = 0; 1392 int i, ret = 0;
1348 u64 storage_space, remaining_space, max_variable_size;
1349 efi_status_t status = EFI_NOT_FOUND; 1393 efi_status_t status = EFI_NOT_FOUND;
1350 unsigned long flags; 1394 unsigned long flags;
1351 1395
@@ -1365,11 +1409,11 @@ static int efi_pstore_write(enum pstore_type_id type,
1365 * size: a size of logging data 1409 * size: a size of logging data
1366 * DUMP_NAME_LEN * 2: a maximum size of variable name 1410 * DUMP_NAME_LEN * 2: a maximum size of variable name
1367 */ 1411 */
1368 status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES, 1412
1369 &storage_space, 1413 status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES,
1370 &remaining_space, 1414 size + DUMP_NAME_LEN * 2);
1371 &max_variable_size); 1415
1372 if (status || remaining_space < size + DUMP_NAME_LEN * 2) { 1416 if (status) {
1373 spin_unlock_irqrestore(&efivars->lock, flags); 1417 spin_unlock_irqrestore(&efivars->lock, flags);
1374 *id = part; 1418 *id = part;
1375 return -ENOSPC; 1419 return -ENOSPC;
@@ -1544,6 +1588,14 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
1544 return -EINVAL; 1588 return -EINVAL;
1545 } 1589 }
1546 1590
1591 status = check_var_size_locked(efivars, new_var->Attributes,
1592 new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
1593
1594 if (status && status != EFI_UNSUPPORTED) {
1595 spin_unlock_irq(&efivars->lock);
1596 return efi_status_to_err(status);
1597 }
1598
1547 /* now *really* create the variable via EFI */ 1599 /* now *really* create the variable via EFI */
1548 status = efivars->ops->set_variable(new_var->VariableName, 1600 status = efivars->ops->set_variable(new_var->VariableName,
1549 &new_var->VendorGuid, 1601 &new_var->VendorGuid,