1
0
Fork 0

firmware_class: perform new LSM checks

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>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
hifive-unleashed-5.1
Kees Cook 2014-02-25 13:06:00 -08:00
parent 13752fe2d7
commit 6593d9245b
1 changed files with 26 additions and 4 deletions

View File

@ -28,6 +28,7 @@
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/syscore_ops.h> #include <linux/syscore_ops.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/security.h>
#include <generated/utsrelease.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 != size) {
if (rc > 0) if (rc > 0)
rc = -EIO; rc = -EIO;
vfree(buf); goto fail;
return rc;
} }
rc = security_kernel_fw_from_file(file, buf, size);
if (rc)
goto fail;
fw_buf->data = buf; fw_buf->data = buf;
fw_buf->size = size; fw_buf->size = size;
return 0; return 0;
fail:
vfree(buf);
return rc;
} }
static int fw_get_filesystem_firmware(struct device *device, 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_priv *fw_priv = to_firmware_priv(dev);
struct firmware_buf *fw_buf; struct firmware_buf *fw_buf;
ssize_t written = count;
int loading = simple_strtol(buf, NULL, 10); int loading = simple_strtol(buf, NULL, 10);
int i; int i;
@ -640,6 +647,8 @@ static ssize_t firmware_loading_store(struct device *dev,
break; break;
case 0: case 0:
if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) { if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
int rc;
set_bit(FW_STATUS_DONE, &fw_buf->status); set_bit(FW_STATUS_DONE, &fw_buf->status);
clear_bit(FW_STATUS_LOADING, &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 * see the mapped 'buf->data' once the loading
* is completed. * 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", dev_err(dev, "%s: map pages failed\n",
__func__); __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); list_del_init(&fw_buf->pending_list);
if (rc) {
set_bit(FW_STATUS_ABORT, &fw_buf->status);
written = rc;
}
complete_all(&fw_buf->completion); complete_all(&fw_buf->completion);
break; break;
} }
@ -666,7 +688,7 @@ static ssize_t firmware_loading_store(struct device *dev,
} }
out: out:
mutex_unlock(&fw_lock); mutex_unlock(&fw_lock);
return count; return written;
} }
static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);