Commit 99d5cadf authored by Jiri Bohac's avatar Jiri Bohac Committed by James Morris

kexec_file: split KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE

This is a preparatory patch for kexec_file_load() lockdown.  A locked down
kernel needs to prevent unsigned kernel images from being loaded with
kexec_file_load().  Currently, the only way to force the signature
verification is compiling with KEXEC_VERIFY_SIG.  This prevents loading
usigned images even when the kernel is not locked down at runtime.

This patch splits KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE.
Analogous to the MODULE_SIG and MODULE_SIG_FORCE for modules, KEXEC_SIG
turns on the signature verification but allows unsigned images to be
loaded.  KEXEC_SIG_FORCE disallows images without a valid signature.
Signed-off-by: default avatarJiri Bohac <jbohac@suse.cz>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarMatthew Garrett <mjg59@google.com>
cc: kexec@lists.infradead.org
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent fef5dad9
...@@ -961,7 +961,7 @@ config KEXEC_FILE ...@@ -961,7 +961,7 @@ config KEXEC_FILE
for kernel and initramfs as opposed to list of segments as for kernel and initramfs as opposed to list of segments as
accepted by previous system call. accepted by previous system call.
config KEXEC_VERIFY_SIG config KEXEC_SIG
bool "Verify kernel signature during kexec_file_load() syscall" bool "Verify kernel signature during kexec_file_load() syscall"
depends on KEXEC_FILE depends on KEXEC_FILE
help help
...@@ -976,13 +976,13 @@ config KEXEC_VERIFY_SIG ...@@ -976,13 +976,13 @@ config KEXEC_VERIFY_SIG
config KEXEC_IMAGE_VERIFY_SIG config KEXEC_IMAGE_VERIFY_SIG
bool "Enable Image signature verification support" bool "Enable Image signature verification support"
default y default y
depends on KEXEC_VERIFY_SIG depends on KEXEC_SIG
depends on EFI && SIGNED_PE_FILE_VERIFICATION depends on EFI && SIGNED_PE_FILE_VERIFICATION
help help
Enable Image signature verification support. Enable Image signature verification support.
comment "Support for PE file signature verification disabled" comment "Support for PE file signature verification disabled"
depends on KEXEC_VERIFY_SIG depends on KEXEC_SIG
depends on !EFI || !SIGNED_PE_FILE_VERIFICATION depends on !EFI || !SIGNED_PE_FILE_VERIFICATION
config CRASH_DUMP config CRASH_DUMP
......
...@@ -555,7 +555,7 @@ config ARCH_HAS_KEXEC_PURGATORY ...@@ -555,7 +555,7 @@ config ARCH_HAS_KEXEC_PURGATORY
def_bool y def_bool y
depends on KEXEC_FILE depends on KEXEC_FILE
config KEXEC_VERIFY_SIG config KEXEC_SIG
bool "Verify kernel signature during kexec_file_load() syscall" bool "Verify kernel signature during kexec_file_load() syscall"
depends on KEXEC_FILE && SYSTEM_DATA_VERIFICATION depends on KEXEC_FILE && SYSTEM_DATA_VERIFICATION
help help
......
...@@ -64,7 +64,7 @@ CONFIG_NUMA=y ...@@ -64,7 +64,7 @@ CONFIG_NUMA=y
CONFIG_PREEMPT=y CONFIG_PREEMPT=y
CONFIG_HZ_100=y CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y CONFIG_KEXEC_SIG=y
CONFIG_EXPOLINE=y CONFIG_EXPOLINE=y
CONFIG_EXPOLINE_AUTO=y CONFIG_EXPOLINE_AUTO=y
CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTPLUG=y
......
...@@ -39,7 +39,7 @@ CONFIG_NR_CPUS=256 ...@@ -39,7 +39,7 @@ CONFIG_NR_CPUS=256
CONFIG_NUMA=y CONFIG_NUMA=y
CONFIG_HZ_100=y CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y CONFIG_KEXEC_SIG=y
CONFIG_CRASH_DUMP=y CONFIG_CRASH_DUMP=y
CONFIG_HIBERNATION=y CONFIG_HIBERNATION=y
CONFIG_PM_DEBUG=y CONFIG_PM_DEBUG=y
......
...@@ -65,7 +65,7 @@ CONFIG_NR_CPUS=512 ...@@ -65,7 +65,7 @@ CONFIG_NR_CPUS=512
CONFIG_NUMA=y CONFIG_NUMA=y
CONFIG_HZ_100=y CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y CONFIG_KEXEC_SIG=y
CONFIG_EXPOLINE=y CONFIG_EXPOLINE=y
CONFIG_EXPOLINE_AUTO=y CONFIG_EXPOLINE_AUTO=y
CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTPLUG=y
......
...@@ -130,7 +130,7 @@ static int s390_elf_probe(const char *buf, unsigned long len) ...@@ -130,7 +130,7 @@ static int s390_elf_probe(const char *buf, unsigned long len)
const struct kexec_file_ops s390_kexec_elf_ops = { const struct kexec_file_ops s390_kexec_elf_ops = {
.probe = s390_elf_probe, .probe = s390_elf_probe,
.load = s390_elf_load, .load = s390_elf_load,
#ifdef CONFIG_KEXEC_VERIFY_SIG #ifdef CONFIG_KEXEC__SIG
.verify_sig = s390_verify_sig, .verify_sig = s390_verify_sig,
#endif /* CONFIG_KEXEC_VERIFY_SIG */ #endif /* CONFIG_KEXEC_SIG */
}; };
...@@ -59,7 +59,7 @@ static int s390_image_probe(const char *buf, unsigned long len) ...@@ -59,7 +59,7 @@ static int s390_image_probe(const char *buf, unsigned long len)
const struct kexec_file_ops s390_kexec_image_ops = { const struct kexec_file_ops s390_kexec_image_ops = {
.probe = s390_image_probe, .probe = s390_image_probe,
.load = s390_image_load, .load = s390_image_load,
#ifdef CONFIG_KEXEC_VERIFY_SIG #ifdef CONFIG_KEXEC_SIG
.verify_sig = s390_verify_sig, .verify_sig = s390_verify_sig,
#endif /* CONFIG_KEXEC_VERIFY_SIG */ #endif /* CONFIG_KEXEC_SIG */
}; };
...@@ -22,7 +22,7 @@ const struct kexec_file_ops * const kexec_file_loaders[] = { ...@@ -22,7 +22,7 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
NULL, NULL,
}; };
#ifdef CONFIG_KEXEC_VERIFY_SIG #ifdef CONFIG_KEXEC_SIG
/* /*
* Module signature information block. * Module signature information block.
* *
...@@ -90,7 +90,7 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len) ...@@ -90,7 +90,7 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
VERIFYING_MODULE_SIGNATURE, VERIFYING_MODULE_SIGNATURE,
NULL, NULL); NULL, NULL);
} }
#endif /* CONFIG_KEXEC_VERIFY_SIG */ #endif /* CONFIG_KEXEC_SIG */
static int kexec_file_update_purgatory(struct kimage *image, static int kexec_file_update_purgatory(struct kimage *image,
struct s390_load_data *data) struct s390_load_data *data)
......
...@@ -2006,20 +2006,30 @@ config KEXEC_FILE ...@@ -2006,20 +2006,30 @@ config KEXEC_FILE
config ARCH_HAS_KEXEC_PURGATORY config ARCH_HAS_KEXEC_PURGATORY
def_bool KEXEC_FILE def_bool KEXEC_FILE
config KEXEC_VERIFY_SIG config KEXEC_SIG
bool "Verify kernel signature during kexec_file_load() syscall" bool "Verify kernel signature during kexec_file_load() syscall"
depends on KEXEC_FILE depends on KEXEC_FILE
---help--- ---help---
This option makes kernel signature verification mandatory for
the kexec_file_load() syscall.
In addition to that option, you need to enable signature This option makes the kexec_file_load() syscall check for a valid
signature of the kernel image. The image can still be loaded without
a valid signature unless you also enable KEXEC_SIG_FORCE, though if
there's a signature that we can check, then it must be valid.
In addition to this option, you need to enable signature
verification for the corresponding kernel image type being verification for the corresponding kernel image type being
loaded in order for this to work. loaded in order for this to work.
config KEXEC_SIG_FORCE
bool "Require a valid signature in kexec_file_load() syscall"
depends on KEXEC_SIG
---help---
This option makes kernel signature verification mandatory for
the kexec_file_load() syscall.
config KEXEC_BZIMAGE_VERIFY_SIG config KEXEC_BZIMAGE_VERIFY_SIG
bool "Enable bzImage signature verification support" bool "Enable bzImage signature verification support"
depends on KEXEC_VERIFY_SIG depends on KEXEC_SIG
depends on SIGNED_PE_FILE_VERIFICATION depends on SIGNED_PE_FILE_VERIFICATION
select SYSTEM_TRUSTED_KEYRING select SYSTEM_TRUSTED_KEYRING
---help--- ---help---
......
...@@ -66,9 +66,9 @@ bool arch_ima_get_secureboot(void) ...@@ -66,9 +66,9 @@ bool arch_ima_get_secureboot(void)
/* secureboot arch rules */ /* secureboot arch rules */
static const char * const sb_arch_rules[] = { static const char * const sb_arch_rules[] = {
#if !IS_ENABLED(CONFIG_KEXEC_VERIFY_SIG) #if !IS_ENABLED(CONFIG_KEXEC_SIG)
"appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig", "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
#endif /* CONFIG_KEXEC_VERIFY_SIG */ #endif /* CONFIG_KEXEC_SIG */
"measure func=KEXEC_KERNEL_CHECK", "measure func=KEXEC_KERNEL_CHECK",
#if !IS_ENABLED(CONFIG_MODULE_SIG) #if !IS_ENABLED(CONFIG_MODULE_SIG)
"appraise func=MODULE_CHECK appraise_type=imasig", "appraise func=MODULE_CHECK appraise_type=imasig",
......
...@@ -96,7 +96,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen, ...@@ -96,7 +96,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
if (!ddir->certs.virtual_address || !ddir->certs.size) { if (!ddir->certs.virtual_address || !ddir->certs.size) {
pr_debug("Unsigned PE binary\n"); pr_debug("Unsigned PE binary\n");
return -EKEYREJECTED; return -ENODATA;
} }
chkaddr(ctx->header_size, ddir->certs.virtual_address, chkaddr(ctx->header_size, ddir->certs.virtual_address,
...@@ -403,6 +403,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, ...@@ -403,6 +403,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
* (*) 0 if at least one signature chain intersects with the keys in the trust * (*) 0 if at least one signature chain intersects with the keys in the trust
* keyring, or: * keyring, or:
* *
* (*) -ENODATA if there is no signature present.
*
* (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
* chain. * chain.
* *
......
...@@ -125,7 +125,7 @@ typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf, ...@@ -125,7 +125,7 @@ typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf,
unsigned long cmdline_len); unsigned long cmdline_len);
typedef int (kexec_cleanup_t)(void *loader_data); typedef int (kexec_cleanup_t)(void *loader_data);
#ifdef CONFIG_KEXEC_VERIFY_SIG #ifdef CONFIG_KEXEC_SIG
typedef int (kexec_verify_sig_t)(const char *kernel_buf, typedef int (kexec_verify_sig_t)(const char *kernel_buf,
unsigned long kernel_len); unsigned long kernel_len);
#endif #endif
...@@ -134,7 +134,7 @@ struct kexec_file_ops { ...@@ -134,7 +134,7 @@ struct kexec_file_ops {
kexec_probe_t *probe; kexec_probe_t *probe;
kexec_load_t *load; kexec_load_t *load;
kexec_cleanup_t *cleanup; kexec_cleanup_t *cleanup;
#ifdef CONFIG_KEXEC_VERIFY_SIG #ifdef CONFIG_KEXEC_SIG
kexec_verify_sig_t *verify_sig; kexec_verify_sig_t *verify_sig;
#endif #endif
}; };
......
...@@ -88,7 +88,7 @@ int __weak arch_kimage_file_post_load_cleanup(struct kimage *image) ...@@ -88,7 +88,7 @@ int __weak arch_kimage_file_post_load_cleanup(struct kimage *image)
return kexec_image_post_load_cleanup_default(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, static int kexec_image_verify_sig_default(struct kimage *image, void *buf,
unsigned long buf_len) unsigned long buf_len)
{ {
...@@ -177,6 +177,51 @@ void kimage_file_post_load_cleanup(struct kimage *image) ...@@ -177,6 +177,51 @@ void kimage_file_post_load_cleanup(struct kimage *image)
image->image_loader_data = NULL; 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;
}
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 * In file mode list of segments is prepared by kernel. Copy relevant
* data from user space, do error checking, prepare segment list * data from user space, do error checking, prepare segment list
...@@ -186,7 +231,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, ...@@ -186,7 +231,7 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
const char __user *cmdline_ptr, const char __user *cmdline_ptr,
unsigned long cmdline_len, unsigned flags) unsigned long cmdline_len, unsigned flags)
{ {
int ret = 0; int ret;
void *ldata; void *ldata;
loff_t size; loff_t size;
...@@ -205,14 +250,11 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, ...@@ -205,14 +250,11 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
if (ret) if (ret)
goto out; goto out;
#ifdef CONFIG_KEXEC_VERIFY_SIG #ifdef CONFIG_KEXEC_SIG
ret = arch_kexec_kernel_verify_sig(image, image->kernel_buf, ret = kimage_validate_signature(image);
image->kernel_buf_len);
if (ret) { if (ret)
pr_debug("kernel signature verification failed.\n");
goto out; goto out;
}
pr_debug("kernel signature verification successful.\n");
#endif #endif
/* It is possible that there no initramfs is being loaded */ /* It is possible that there no initramfs is being loaded */
if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {
......
...@@ -160,7 +160,7 @@ config IMA_APPRAISE ...@@ -160,7 +160,7 @@ config IMA_APPRAISE
config IMA_ARCH_POLICY config IMA_ARCH_POLICY
bool "Enable loading an IMA architecture specific policy" bool "Enable loading an IMA architecture specific policy"
depends on KEXEC_VERIFY_SIG || IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS depends on KEXEC_SIG || IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
default n default n
help help
This option enables loading an IMA architecture specific policy This option enables loading an IMA architecture specific policy
......
...@@ -541,7 +541,7 @@ int ima_load_data(enum kernel_load_data_id id) ...@@ -541,7 +541,7 @@ int ima_load_data(enum kernel_load_data_id id)
switch (id) { switch (id) {
case LOADING_KEXEC_IMAGE: case LOADING_KEXEC_IMAGE:
if (IS_ENABLED(CONFIG_KEXEC_VERIFY_SIG) if (IS_ENABLED(CONFIG_KEXEC_SIG)
&& arch_ima_get_secureboot()) { && arch_ima_get_secureboot()) {
pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
return -EACCES; return -EACCES;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment