aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/firmware_class.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 11:06:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 11:06:39 -0400
commitbb2cbf5e9367d8598fecd0c48dead69560750223 (patch)
treefb2c620451b90f41a31726bdd82077813f941e39 /drivers/base/firmware_class.c
parente7fda6c4c3c1a7d6996dd75fd84670fa0b5d448f (diff)
parent478d085524c57cf4283699f529d5a4c22188ea69 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "In this release: - PKCS#7 parser for the key management subsystem from David Howells - appoint Kees Cook as seccomp maintainer - bugfixes and general maintenance across the subsystem" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (94 commits) X.509: Need to export x509_request_asymmetric_key() netlabel: shorter names for the NetLabel catmap funcs/structs netlabel: fix the catmap walking functions netlabel: fix the horribly broken catmap functions netlabel: fix a problem when setting bits below the previously lowest bit PKCS#7: X.509 certificate issuer and subject are mandatory fields in the ASN.1 tpm: simplify code by using %*phN specifier tpm: Provide a generic means to override the chip returned timeouts tpm: missing tpm_chip_put in tpm_get_random() tpm: Properly clean sysfs entries in error path tpm: Add missing tpm_do_selftest to ST33 I2C driver PKCS#7: Use x509_request_asymmetric_key() Revert "selinux: fix the default socket labeling in sock_graft()" X.509: x509_request_asymmetric_keys() doesn't need string length arguments PKCS#7: fix sparse non static symbol warning KEYS: revert encrypted key change ima: add support for measuring and appraising firmware firmware_class: perform new LSM checks security: introduce kernel_fw_from_file hook PKCS#7: Missing inclusion of linux/err.h ...
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r--drivers/base/firmware_class.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index da77791793f1..bf424305f3dc 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
@@ -303,12 +304,17 @@ static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
303 if (rc != size) { 304 if (rc != size) {
304 if (rc > 0) 305 if (rc > 0)
305 rc = -EIO; 306 rc = -EIO;
306 vfree(buf); 307 goto fail;
307 return rc;
308 } 308 }
309 rc = security_kernel_fw_from_file(file, buf, size);
310 if (rc)
311 goto fail;
309 fw_buf->data = buf; 312 fw_buf->data = buf;
310 fw_buf->size = size; 313 fw_buf->size = size;
311 return 0; 314 return 0;
315fail:
316 vfree(buf);
317 return rc;
312} 318}
313 319
314static int fw_get_filesystem_firmware(struct device *device, 320static int fw_get_filesystem_firmware(struct device *device,
@@ -612,6 +618,7 @@ static ssize_t firmware_loading_store(struct device *dev,
612{ 618{
613 struct firmware_priv *fw_priv = to_firmware_priv(dev); 619 struct firmware_priv *fw_priv = to_firmware_priv(dev);
614 struct firmware_buf *fw_buf; 620 struct firmware_buf *fw_buf;
621 ssize_t written = count;
615 int loading = simple_strtol(buf, NULL, 10); 622 int loading = simple_strtol(buf, NULL, 10);
616 int i; 623 int i;
617 624
@@ -635,6 +642,8 @@ static ssize_t firmware_loading_store(struct device *dev,
635 break; 642 break;
636 case 0: 643 case 0:
637 if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) { 644 if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
645 int rc;
646
638 set_bit(FW_STATUS_DONE, &fw_buf->status); 647 set_bit(FW_STATUS_DONE, &fw_buf->status);
639 clear_bit(FW_STATUS_LOADING, &fw_buf->status); 648 clear_bit(FW_STATUS_LOADING, &fw_buf->status);
640 649
@@ -644,10 +653,23 @@ static ssize_t firmware_loading_store(struct device *dev,
644 * see the mapped 'buf->data' once the loading 653 * see the mapped 'buf->data' once the loading
645 * is completed. 654 * is completed.
646 * */ 655 * */
647 if (fw_map_pages_buf(fw_buf)) 656 rc = fw_map_pages_buf(fw_buf);
657 if (rc)
648 dev_err(dev, "%s: map pages failed\n", 658 dev_err(dev, "%s: map pages failed\n",
649 __func__); 659 __func__);
660 else
661 rc = security_kernel_fw_from_file(NULL,
662 fw_buf->data, fw_buf->size);
663
664 /*
665 * Same logic as fw_load_abort, only the DONE bit
666 * is ignored and we set ABORT only on failure.
667 */
650 list_del_init(&fw_buf->pending_list); 668 list_del_init(&fw_buf->pending_list);
669 if (rc) {
670 set_bit(FW_STATUS_ABORT, &fw_buf->status);
671 written = rc;
672 }
651 complete_all(&fw_buf->completion); 673 complete_all(&fw_buf->completion);
652 break; 674 break;
653 } 675 }
@@ -661,7 +683,7 @@ static ssize_t firmware_loading_store(struct device *dev,
661 } 683 }
662out: 684out:
663 mutex_unlock(&fw_lock); 685 mutex_unlock(&fw_lock);
664 return count; 686 return written;
665} 687}
666 688
667static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); 689static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);