All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] security: introduce kernel_fw_from_file hook
@ 2014-07-22 18:28 Kees Cook
  2014-07-22 18:29 ` [PATCH v3 1/2] " Kees Cook
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Kees Cook @ 2014-07-22 18:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: Kees Cook, Ming Lei, Takashi Iwai, James Morris,
	Greg Kroah-Hartman, linux-security-module

This adds an LSM hook to the existing firmware loading logic so that
the LSM can reason about the origin and contents of a firmware coming
from userspace.

Thanks,

-Kees

v3:
- correctly return LSM error to userspace (ming.lei)
- finalize memory map before calling LSM hook (tiwai)
v2:
- further clarify header comments (jmorris)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v3 1/2] security: introduce kernel_fw_from_file hook
  2014-07-22 18:28 [PATCH v3 0/2] security: introduce kernel_fw_from_file hook Kees Cook
@ 2014-07-22 18:29 ` Kees Cook
  2014-07-22 18:29 ` [PATCH v3 2/2] firmware_class: perform new LSM checks Kees Cook
  2014-07-23 10:14 ` [PATCH v3 0/2] security: introduce kernel_fw_from_file hook Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: Kees Cook @ 2014-07-22 18:29 UTC (permalink / raw)
  To: linux-kernel
  Cc: Kees Cook, Ming Lei, Takashi Iwai, James Morris,
	Greg Kroah-Hartman, linux-security-module

In order to validate the contents of firmware being loaded, there must be
a hook to evaluate any loaded firmware that wasn't built into the kernel
itself. Without this, there is a risk that a root user could load malicious
firmware designed to mount an attack against kernel memory (e.g. via DMA).

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/security.h |   17 +++++++++++++++++
 security/capability.c    |    6 ++++++
 security/security.c      |    6 ++++++
 3 files changed, 29 insertions(+)

diff --git a/include/linux/security.h b/include/linux/security.h
index 9c6b9722ff48..623f90e5f38d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -702,6 +702,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	@inode points to the inode to use as a reference.
  *	The current task must be the one that nominated @inode.
  *	Return 0 if successful.
+ * @kernel_fw_from_file:
+ *	Load firmware from userspace (not called for built-in firmware).
+ *	@file contains the file structure pointing to the file containing
+ *	the firmware to load. This argument will be NULL if the firmware
+ *	was loaded via the uevent-triggered blob-based interface exposed
+ *	by CONFIG_FW_LOADER_USER_HELPER.
+ *	@buf pointer to buffer containing firmware contents.
+ *	@size length of the firmware contents.
+ *	Return 0 if permission is granted.
  * @kernel_module_request:
  *	Ability to trigger the kernel to automatically upcall to userspace for
  *	userspace to load a kernel module with the given name.
@@ -1565,6 +1574,7 @@ struct security_operations {
 	void (*cred_transfer)(struct cred *new, const struct cred *old);
 	int (*kernel_act_as)(struct cred *new, u32 secid);
 	int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
+	int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
 	int (*kernel_module_request)(char *kmod_name);
 	int (*kernel_module_from_file)(struct file *file);
 	int (*task_fix_setuid) (struct cred *new, const struct cred *old,
@@ -1837,6 +1847,7 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
 void security_transfer_creds(struct cred *new, const struct cred *old);
 int security_kernel_act_as(struct cred *new, u32 secid);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
+int security_kernel_fw_from_file(struct file *file, char *buf, size_t size);
 int security_kernel_module_request(char *kmod_name);
 int security_kernel_module_from_file(struct file *file);
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
@@ -2363,6 +2374,12 @@ static inline int security_kernel_create_files_as(struct cred *cred,
 	return 0;
 }
 
+static inline int security_kernel_fw_from_file(struct file *file,
+					       char *buf, size_t size)
+{
+	return 0;
+}
+
 static inline int security_kernel_module_request(char *kmod_name)
 {
 	return 0;
diff --git a/security/capability.c b/security/capability.c
index e76373de3129..a74fde6a7468 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -401,6 +401,11 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)
 	return 0;
 }
 
+static int cap_kernel_fw_from_file(struct file *file, char *buf, size_t size)
+{
+	return 0;
+}
+
 static int cap_kernel_module_request(char *kmod_name)
 {
 	return 0;
@@ -1015,6 +1020,7 @@ void __init security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, cred_transfer);
 	set_to_cap_if_null(ops, kernel_act_as);
 	set_to_cap_if_null(ops, kernel_create_files_as);
+	set_to_cap_if_null(ops, kernel_fw_from_file);
 	set_to_cap_if_null(ops, kernel_module_request);
 	set_to_cap_if_null(ops, kernel_module_from_file);
 	set_to_cap_if_null(ops, task_fix_setuid);
diff --git a/security/security.c b/security/security.c
index 31614e9e96e5..35d37d0f0d49 100644
--- a/security/security.c
+++ b/security/security.c
@@ -845,6 +845,12 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)
 	return security_ops->kernel_create_files_as(new, inode);
 }
 
+int security_kernel_fw_from_file(struct file *file, char *buf, size_t size)
+{
+	return security_ops->kernel_fw_from_file(file, buf, size);
+}
+EXPORT_SYMBOL_GPL(security_kernel_fw_from_file);
+
 int security_kernel_module_request(char *kmod_name)
 {
 	return security_ops->kernel_module_request(kmod_name);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v3 2/2] firmware_class: perform new LSM checks
  2014-07-22 18:28 [PATCH v3 0/2] security: introduce kernel_fw_from_file hook Kees Cook
  2014-07-22 18:29 ` [PATCH v3 1/2] " Kees Cook
@ 2014-07-22 18:29 ` Kees Cook
  2014-07-23 10:14 ` [PATCH v3 0/2] security: introduce kernel_fw_from_file hook Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: Kees Cook @ 2014-07-22 18:29 UTC (permalink / raw)
  To: linux-kernel
  Cc: Kees Cook, Ming Lei, Takashi Iwai, James Morris,
	Greg Kroah-Hartman, linux-security-module

This attaches LSM hooks to the existing firmware loading interfaces:
filesystem-found firmware and demand-loaded blobs. On errors, loads
are aborted and the failure code is returned to userspace.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/base/firmware_class.c |   30 ++++++++++++++++++++++++++----
 1 file 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 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
+#include <linux/security.h>
 
 #include <generated/utsrelease.h>
 
@@ -308,12 +309,17 @@ static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
 	if (rc != size) {
 		if (rc > 0)
 			rc = -EIO;
-		vfree(buf);
-		return rc;
+		goto fail;
 	}
+	rc = security_kernel_fw_from_file(file, buf, size);
+	if (rc)
+		goto fail;
 	fw_buf->data = buf;
 	fw_buf->size = size;
 	return 0;
+fail:
+	vfree(buf);
+	return rc;
 }
 
 static int fw_get_filesystem_firmware(struct device *device,
@@ -617,6 +623,7 @@ static ssize_t firmware_loading_store(struct device *dev,
 {
 	struct firmware_priv *fw_priv = to_firmware_priv(dev);
 	struct firmware_buf *fw_buf;
+	ssize_t written = count;
 	int loading = simple_strtol(buf, NULL, 10);
 	int i;
 
@@ -640,6 +647,8 @@ static ssize_t firmware_loading_store(struct device *dev,
 		break;
 	case 0:
 		if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
+			int rc;
+
 			set_bit(FW_STATUS_DONE, &fw_buf->status);
 			clear_bit(FW_STATUS_LOADING, &fw_buf->status);
 
@@ -649,10 +658,23 @@ static ssize_t firmware_loading_store(struct device *dev,
 			 * see the mapped 'buf->data' once the loading
 			 * is completed.
 			 * */
-			if (fw_map_pages_buf(fw_buf))
+			rc = fw_map_pages_buf(fw_buf);
+			if (rc)
 				dev_err(dev, "%s: map pages failed\n",
 					__func__);
+			else
+				rc = security_kernel_fw_from_file(NULL,
+						fw_buf->data, fw_buf->size);
+
+			/*
+			 * Same logic as fw_load_abort, only the DONE bit
+			 * is ignored and we set ABORT only on failure.
+			 */
 			list_del_init(&fw_buf->pending_list);
+			if (rc) {
+				set_bit(FW_STATUS_ABORT, &fw_buf->status);
+				written = rc;
+			}
 			complete_all(&fw_buf->completion);
 			break;
 		}
@@ -666,7 +688,7 @@ static ssize_t firmware_loading_store(struct device *dev,
 	}
 out:
 	mutex_unlock(&fw_lock);
-	return count;
+	return written;
 }
 
 static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v3 0/2] security: introduce kernel_fw_from_file hook
  2014-07-22 18:28 [PATCH v3 0/2] security: introduce kernel_fw_from_file hook Kees Cook
  2014-07-22 18:29 ` [PATCH v3 1/2] " Kees Cook
  2014-07-22 18:29 ` [PATCH v3 2/2] firmware_class: perform new LSM checks Kees Cook
@ 2014-07-23 10:14 ` Takashi Iwai
  2 siblings, 0 replies; 4+ messages in thread
From: Takashi Iwai @ 2014-07-23 10:14 UTC (permalink / raw)
  To: Kees Cook
  Cc: linux-kernel, Ming Lei, Takashi Iwai, James Morris,
	Greg Kroah-Hartman, linux-security-module

At Tue, 22 Jul 2014 11:28:59 -0700,
Kees Cook wrote:
n> 
> This adds an LSM hook to the existing firmware loading logic so that
> the LSM can reason about the origin and contents of a firmware coming
> from userspace.
> 
> Thanks,
> 
> -Kees
> 
> v3:
> - correctly return LSM error to userspace (ming.lei)
> - finalize memory map before calling LSM hook (tiwai)
> v2:
> - further clarify header comments (jmorris)

To both patches,
  Reviewed-by: Takashi Iwai <tiwai@suse.de>


thanks,

Takashi

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-07-23 10:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-22 18:28 [PATCH v3 0/2] security: introduce kernel_fw_from_file hook Kees Cook
2014-07-22 18:29 ` [PATCH v3 1/2] " Kees Cook
2014-07-22 18:29 ` [PATCH v3 2/2] firmware_class: perform new LSM checks Kees Cook
2014-07-23 10:14 ` [PATCH v3 0/2] security: introduce kernel_fw_from_file hook Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.