Merge branch 'asoc-5.4' into asoc-5.5
[linux-2.6-microblaze.git] / kernel / kexec_file.c
index ef7b951..79f252a 100644 (file)
@@ -88,7 +88,7 @@ int __weak arch_kimage_file_post_load_cleanup(struct kimage *image)
        return kexec_image_post_load_cleanup_default(image);
 }
 
-#ifdef CONFIG_KEXEC_VERIFY_SIG
+#ifdef CONFIG_KEXEC_SIG
 static int kexec_image_verify_sig_default(struct kimage *image, void *buf,
                                          unsigned long buf_len)
 {
@@ -177,6 +177,59 @@ void kimage_file_post_load_cleanup(struct kimage *image)
        image->image_loader_data = NULL;
 }
 
+#ifdef CONFIG_KEXEC_SIG
+static int
+kimage_validate_signature(struct kimage *image)
+{
+       const char *reason;
+       int ret;
+
+       ret = arch_kexec_kernel_verify_sig(image, image->kernel_buf,
+                                          image->kernel_buf_len);
+       switch (ret) {
+       case 0:
+               break;
+
+               /* Certain verification errors are non-fatal if we're not
+                * checking errors, provided we aren't mandating that there
+                * must be a valid signature.
+                */
+       case -ENODATA:
+               reason = "kexec of unsigned image";
+               goto decide;
+       case -ENOPKG:
+               reason = "kexec of image with unsupported crypto";
+               goto decide;
+       case -ENOKEY:
+               reason = "kexec of image with unavailable key";
+       decide:
+               if (IS_ENABLED(CONFIG_KEXEC_SIG_FORCE)) {
+                       pr_notice("%s rejected\n", reason);
+                       return ret;
+               }
+
+               /* If IMA is guaranteed to appraise a signature on the kexec
+                * image, permit it even if the kernel is otherwise locked
+                * down.
+                */
+               if (!ima_appraise_signature(READING_KEXEC_IMAGE) &&
+                   security_locked_down(LOCKDOWN_KEXEC))
+                       return -EPERM;
+
+               return 0;
+
+               /* All other errors are fatal, including nomem, unparseable
+                * signatures and signature check failures - even if signatures
+                * aren't required.
+                */
+       default:
+               pr_notice("kernel signature verification failed (%d).\n", ret);
+       }
+
+       return ret;
+}
+#endif
+
 /*
  * In file mode list of segments is prepared by kernel. Copy relevant
  * data from user space, do error checking, prepare segment list
@@ -186,7 +239,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
                             const char __user *cmdline_ptr,
                             unsigned long cmdline_len, unsigned flags)
 {
-       int ret = 0;
+       int ret;
        void *ldata;
        loff_t size;
 
@@ -196,23 +249,17 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
                return ret;
        image->kernel_buf_len = size;
 
-       /* IMA needs to pass the measurement list to the next kernel. */
-       ima_add_kexec_buffer(image);
-
        /* Call arch image probe handlers */
        ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
                                            image->kernel_buf_len);
        if (ret)
                goto out;
 
-#ifdef CONFIG_KEXEC_VERIFY_SIG
-       ret = arch_kexec_kernel_verify_sig(image, image->kernel_buf,
-                                          image->kernel_buf_len);
-       if (ret) {
-               pr_debug("kernel signature verification failed.\n");
+#ifdef CONFIG_KEXEC_SIG
+       ret = kimage_validate_signature(image);
+
+       if (ret)
                goto out;
-       }
-       pr_debug("kernel signature verification successful.\n");
 #endif
        /* It is possible that there no initramfs is being loaded */
        if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {
@@ -239,8 +286,14 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
                        ret = -EINVAL;
                        goto out;
                }
+
+               ima_kexec_cmdline(image->cmdline_buf,
+                                 image->cmdline_buf_len - 1);
        }
 
+       /* IMA needs to pass the measurement list to the next kernel. */
+       ima_add_kexec_buffer(image);
+
        /* Call arch image load handlers */
        ldata = arch_kexec_kernel_image_load(image);