forked from Minki/linux
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>
This commit is contained in:
parent
13752fe2d7
commit
6593d9245b
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user