diff options
-rw-r--r-- | arch/x86/Kconfig | 22 | ||||
-rw-r--r-- | arch/x86/kernel/kexec-bzimage64.c | 21 | ||||
-rw-r--r-- | arch/x86/kernel/machine_kexec_64.c | 11 | ||||
-rw-r--r-- | include/linux/kexec.h | 3 | ||||
-rw-r--r-- | kernel/kexec.c | 15 |
5 files changed, 72 insertions, 0 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9558b9fcafbf..4aafd322e21e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -1599,6 +1599,28 @@ config KEXEC | |||
1599 | interface is strongly in flux, so no good recommendation can be | 1599 | interface is strongly in flux, so no good recommendation can be |
1600 | made. | 1600 | made. |
1601 | 1601 | ||
1602 | config KEXEC_VERIFY_SIG | ||
1603 | bool "Verify kernel signature during kexec_file_load() syscall" | ||
1604 | depends on KEXEC | ||
1605 | ---help--- | ||
1606 | This option makes kernel signature verification mandatory for | ||
1607 | kexec_file_load() syscall. If kernel is signature can not be | ||
1608 | verified, kexec_file_load() will fail. | ||
1609 | |||
1610 | This option enforces signature verification at generic level. | ||
1611 | One needs to enable signature verification for type of kernel | ||
1612 | image being loaded to make sure it works. For example, enable | ||
1613 | bzImage signature verification option to be able to load and | ||
1614 | verify signatures of bzImage. Otherwise kernel loading will fail. | ||
1615 | |||
1616 | config KEXEC_BZIMAGE_VERIFY_SIG | ||
1617 | bool "Enable bzImage signature verification support" | ||
1618 | depends on KEXEC_VERIFY_SIG | ||
1619 | depends on SIGNED_PE_FILE_VERIFICATION | ||
1620 | select SYSTEM_TRUSTED_KEYRING | ||
1621 | ---help--- | ||
1622 | Enable bzImage signature verification support. | ||
1623 | |||
1602 | config CRASH_DUMP | 1624 | config CRASH_DUMP |
1603 | bool "kernel crash dumps" | 1625 | bool "kernel crash dumps" |
1604 | depends on X86_64 || (X86_32 && HIGHMEM) | 1626 | depends on X86_64 || (X86_32 && HIGHMEM) |
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index 623e6c58081f..9642b9b33655 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
21 | #include <linux/efi.h> | 21 | #include <linux/efi.h> |
22 | #include <linux/verify_pefile.h> | ||
23 | #include <keys/system_keyring.h> | ||
22 | 24 | ||
23 | #include <asm/bootparam.h> | 25 | #include <asm/bootparam.h> |
24 | #include <asm/setup.h> | 26 | #include <asm/setup.h> |
@@ -525,8 +527,27 @@ int bzImage64_cleanup(void *loader_data) | |||
525 | return 0; | 527 | return 0; |
526 | } | 528 | } |
527 | 529 | ||
530 | #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG | ||
531 | int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len) | ||
532 | { | ||
533 | bool trusted; | ||
534 | int ret; | ||
535 | |||
536 | ret = verify_pefile_signature(kernel, kernel_len, | ||
537 | system_trusted_keyring, &trusted); | ||
538 | if (ret < 0) | ||
539 | return ret; | ||
540 | if (!trusted) | ||
541 | return -EKEYREJECTED; | ||
542 | return 0; | ||
543 | } | ||
544 | #endif | ||
545 | |||
528 | struct kexec_file_ops kexec_bzImage64_ops = { | 546 | struct kexec_file_ops kexec_bzImage64_ops = { |
529 | .probe = bzImage64_probe, | 547 | .probe = bzImage64_probe, |
530 | .load = bzImage64_load, | 548 | .load = bzImage64_load, |
531 | .cleanup = bzImage64_cleanup, | 549 | .cleanup = bzImage64_cleanup, |
550 | #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG | ||
551 | .verify_sig = bzImage64_verify_sig, | ||
552 | #endif | ||
532 | }; | 553 | }; |
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 9330434da777..8b04018e5d1f 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c | |||
@@ -372,6 +372,17 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image) | |||
372 | return image->fops->cleanup(image->image_loader_data); | 372 | return image->fops->cleanup(image->image_loader_data); |
373 | } | 373 | } |
374 | 374 | ||
375 | int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel, | ||
376 | unsigned long kernel_len) | ||
377 | { | ||
378 | if (!image->fops || !image->fops->verify_sig) { | ||
379 | pr_debug("kernel loader does not support signature verification."); | ||
380 | return -EKEYREJECTED; | ||
381 | } | ||
382 | |||
383 | return image->fops->verify_sig(kernel, kernel_len); | ||
384 | } | ||
385 | |||
375 | /* | 386 | /* |
376 | * Apply purgatory relocations. | 387 | * Apply purgatory relocations. |
377 | * | 388 | * |
diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 9481703b0e7a..4b2a0e11cc5b 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h | |||
@@ -191,11 +191,14 @@ typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf, | |||
191 | unsigned long initrd_len, char *cmdline, | 191 | unsigned long initrd_len, char *cmdline, |
192 | unsigned long cmdline_len); | 192 | unsigned long cmdline_len); |
193 | typedef int (kexec_cleanup_t)(void *loader_data); | 193 | typedef int (kexec_cleanup_t)(void *loader_data); |
194 | typedef int (kexec_verify_sig_t)(const char *kernel_buf, | ||
195 | unsigned long kernel_len); | ||
194 | 196 | ||
195 | struct kexec_file_ops { | 197 | struct kexec_file_ops { |
196 | kexec_probe_t *probe; | 198 | kexec_probe_t *probe; |
197 | kexec_load_t *load; | 199 | kexec_load_t *load; |
198 | kexec_cleanup_t *cleanup; | 200 | kexec_cleanup_t *cleanup; |
201 | kexec_verify_sig_t *verify_sig; | ||
199 | }; | 202 | }; |
200 | 203 | ||
201 | /* kexec interface functions */ | 204 | /* kexec interface functions */ |
diff --git a/kernel/kexec.c b/kernel/kexec.c index f18c780f9716..0b49a0a58102 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -416,6 +416,12 @@ void __weak arch_kimage_file_post_load_cleanup(struct kimage *image) | |||
416 | { | 416 | { |
417 | } | 417 | } |
418 | 418 | ||
419 | int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf, | ||
420 | unsigned long buf_len) | ||
421 | { | ||
422 | return -EKEYREJECTED; | ||
423 | } | ||
424 | |||
419 | /* Apply relocations of type RELA */ | 425 | /* Apply relocations of type RELA */ |
420 | int __weak | 426 | int __weak |
421 | arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | 427 | arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, |
@@ -494,6 +500,15 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, | |||
494 | if (ret) | 500 | if (ret) |
495 | goto out; | 501 | goto out; |
496 | 502 | ||
503 | #ifdef CONFIG_KEXEC_VERIFY_SIG | ||
504 | ret = arch_kexec_kernel_verify_sig(image, image->kernel_buf, | ||
505 | image->kernel_buf_len); | ||
506 | if (ret) { | ||
507 | pr_debug("kernel signature verification failed.\n"); | ||
508 | goto out; | ||
509 | } | ||
510 | pr_debug("kernel signature verification successful.\n"); | ||
511 | #endif | ||
497 | /* It is possible that there no initramfs is being loaded */ | 512 | /* It is possible that there no initramfs is being loaded */ |
498 | if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { | 513 | if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { |
499 | ret = copy_file_from_fd(initrd_fd, &image->initrd_buf, | 514 | ret = copy_file_from_fd(initrd_fd, &image->initrd_buf, |