diff options
-rw-r--r-- | drivers/base/firmware_class.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d276e33880be..63f165c59da8 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/suspend.h> | 28 | #include <linux/suspend.h> |
29 | #include <linux/syscore_ops.h> | 29 | #include <linux/syscore_ops.h> |
30 | #include <linux/reboot.h> | 30 | #include <linux/reboot.h> |
31 | #include <linux/security.h> | ||
31 | 32 | ||
32 | #include <generated/utsrelease.h> | 33 | #include <generated/utsrelease.h> |
33 | 34 | ||
@@ -308,12 +309,17 @@ static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) | |||
308 | if (rc != size) { | 309 | if (rc != size) { |
309 | if (rc > 0) | 310 | if (rc > 0) |
310 | rc = -EIO; | 311 | rc = -EIO; |
311 | vfree(buf); | 312 | goto fail; |
312 | return rc; | ||
313 | } | 313 | } |
314 | rc = security_kernel_fw_from_file(file, buf, size); | ||
315 | if (rc) | ||
316 | goto fail; | ||
314 | fw_buf->data = buf; | 317 | fw_buf->data = buf; |
315 | fw_buf->size = size; | 318 | fw_buf->size = size; |
316 | return 0; | 319 | return 0; |
320 | fail: | ||
321 | vfree(buf); | ||
322 | return rc; | ||
317 | } | 323 | } |
318 | 324 | ||
319 | static int fw_get_filesystem_firmware(struct device *device, | 325 | static int fw_get_filesystem_firmware(struct device *device, |
@@ -617,6 +623,7 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
617 | { | 623 | { |
618 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | 624 | struct firmware_priv *fw_priv = to_firmware_priv(dev); |
619 | struct firmware_buf *fw_buf; | 625 | struct firmware_buf *fw_buf; |
626 | ssize_t written = count; | ||
620 | int loading = simple_strtol(buf, NULL, 10); | 627 | int loading = simple_strtol(buf, NULL, 10); |
621 | int i; | 628 | int i; |
622 | 629 | ||
@@ -640,6 +647,8 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
640 | break; | 647 | break; |
641 | case 0: | 648 | case 0: |
642 | if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) { | 649 | if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) { |
650 | int rc; | ||
651 | |||
643 | set_bit(FW_STATUS_DONE, &fw_buf->status); | 652 | set_bit(FW_STATUS_DONE, &fw_buf->status); |
644 | clear_bit(FW_STATUS_LOADING, &fw_buf->status); | 653 | clear_bit(FW_STATUS_LOADING, &fw_buf->status); |
645 | 654 | ||
@@ -649,10 +658,23 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
649 | * see the mapped 'buf->data' once the loading | 658 | * see the mapped 'buf->data' once the loading |
650 | * is completed. | 659 | * is completed. |
651 | * */ | 660 | * */ |
652 | if (fw_map_pages_buf(fw_buf)) | 661 | rc = fw_map_pages_buf(fw_buf); |
662 | if (rc) | ||
653 | dev_err(dev, "%s: map pages failed\n", | 663 | dev_err(dev, "%s: map pages failed\n", |
654 | __func__); | 664 | __func__); |
665 | else | ||
666 | rc = security_kernel_fw_from_file(NULL, | ||
667 | fw_buf->data, fw_buf->size); | ||
668 | |||
669 | /* | ||
670 | * Same logic as fw_load_abort, only the DONE bit | ||
671 | * is ignored and we set ABORT only on failure. | ||
672 | */ | ||
655 | list_del_init(&fw_buf->pending_list); | 673 | list_del_init(&fw_buf->pending_list); |
674 | if (rc) { | ||
675 | set_bit(FW_STATUS_ABORT, &fw_buf->status); | ||
676 | written = rc; | ||
677 | } | ||
656 | complete_all(&fw_buf->completion); | 678 | complete_all(&fw_buf->completion); |
657 | break; | 679 | break; |
658 | } | 680 | } |
@@ -666,7 +688,7 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
666 | } | 688 | } |
667 | out: | 689 | out: |
668 | mutex_unlock(&fw_lock); | 690 | mutex_unlock(&fw_lock); |
669 | return count; | 691 | return written; |
670 | } | 692 | } |
671 | 693 | ||
672 | static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); | 694 | static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); |