firmware_loader: Use security_post_load_data()
authorKees Cook <keescook@chromium.org>
Fri, 2 Oct 2020 17:38:21 +0000 (10:38 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Oct 2020 11:37:03 +0000 (13:37 +0200)
Now that security_post_load_data() is wired up, use it instead
of the NULL file argument style of security_post_read_file(),
and update the security_kernel_load_data() call to indicate that a
security_kernel_post_load_data() call is expected.

Wire up the IMA check to match earlier logic. Perhaps a generalized
change to ima_post_load_data() might look something like this:

    return process_buffer_measurement(buf, size,
                                      kernel_load_data_id_str(load_id),
                                      read_idmap[load_id] ?: FILE_CHECK,
                                      0, NULL);

Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Link: https://lore.kernel.org/r/20201002173828.2099543-10-keescook@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/base/firmware_loader/fallback.c
drivers/base/firmware_loader/fallback_platform.c
security/integrity/ima/ima_main.c

index bff4717..251d92f 100644 (file)
@@ -272,9 +272,9 @@ static ssize_t firmware_loading_store(struct device *dev,
                                dev_err(dev, "%s: map pages failed\n",
                                        __func__);
                        else
-                               rc = security_kernel_post_read_file(NULL,
-                                               fw_priv->data, fw_priv->size,
-                                               READING_FIRMWARE);
+                               rc = security_kernel_post_load_data(fw_priv->data,
+                                               fw_priv->size,
+                                               LOADING_FIRMWARE, "blob");
 
                        /*
                         * Same logic as fw_load_abort, only the DONE bit
@@ -613,7 +613,7 @@ static bool fw_run_sysfs_fallback(u32 opt_flags)
                return false;
 
        /* Also permit LSMs and IMA to fail firmware sysfs fallback */
-       ret = security_kernel_load_data(LOADING_FIRMWARE, false);
+       ret = security_kernel_load_data(LOADING_FIRMWARE, true);
        if (ret < 0)
                return false;
 
index a12c79d..8bdf880 100644 (file)
@@ -17,7 +17,7 @@ int firmware_fallback_platform(struct fw_priv *fw_priv, u32 opt_flags)
        if (!(opt_flags & FW_OPT_FALLBACK_PLATFORM))
                return -ENOENT;
 
-       rc = security_kernel_load_data(LOADING_FIRMWARE, false);
+       rc = security_kernel_load_data(LOADING_FIRMWARE, true);
        if (rc)
                return rc;
 
@@ -27,6 +27,12 @@ int firmware_fallback_platform(struct fw_priv *fw_priv, u32 opt_flags)
 
        if (fw_priv->data && size > fw_priv->allocated_size)
                return -ENOMEM;
+
+       rc = security_kernel_post_load_data((u8 *)data, size, LOADING_FIRMWARE,
+                                               "platform");
+       if (rc)
+               return rc;
+
        if (!fw_priv->data)
                fw_priv->data = vmalloc(size);
        if (!fw_priv->data)
index 9dd9c5f..6f2b835 100644 (file)
@@ -648,15 +648,6 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
        enum ima_hooks func;
        u32 secid;
 
-       if (!file && read_id == READING_FIRMWARE) {
-               if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
-                   (ima_appraise & IMA_APPRAISE_ENFORCE)) {
-                       pr_err("Prevent firmware loading_store.\n");
-                       return -EACCES; /* INTEGRITY_UNKNOWN */
-               }
-               return 0;
-       }
-
        /* permit signed certs */
        if (!file && read_id == READING_X509_CERTIFICATE)
                return 0;
@@ -706,7 +697,7 @@ int ima_load_data(enum kernel_load_data_id id, bool contents)
                }
                break;
        case LOADING_FIRMWARE:
-               if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE)) {
+               if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE) && !contents) {
                        pr_err("Prevent firmware sysfs fallback loading.\n");
                        return -EACCES; /* INTEGRITY_UNKNOWN */
                }
@@ -742,6 +733,15 @@ int ima_post_load_data(char *buf, loff_t size,
                       enum kernel_load_data_id load_id,
                       char *description)
 {
+       if (load_id == LOADING_FIRMWARE) {
+               if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
+                   (ima_appraise & IMA_APPRAISE_ENFORCE)) {
+                       pr_err("Prevent firmware loading_store.\n");
+                       return -EACCES; /* INTEGRITY_UNKNOWN */
+               }
+               return 0;
+       }
+
        return 0;
 }