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: Jiri Bohac <jbohac@suse.cz> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Matthew Garrett <mjg59@google.com> cc: kexec@lists.infradead.org Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
fef5dad987
commit
99d5cadfde
|
@ -961,7 +961,7 @@ config KEXEC_FILE
|
|||
for kernel and initramfs as opposed to list of segments as
|
||||
accepted by previous system call.
|
||||
|
||||
config KEXEC_VERIFY_SIG
|
||||
config KEXEC_SIG
|
||||
bool "Verify kernel signature during kexec_file_load() syscall"
|
||||
depends on KEXEC_FILE
|
||||
help
|
||||
|
@ -976,13 +976,13 @@ config KEXEC_VERIFY_SIG
|
|||
config KEXEC_IMAGE_VERIFY_SIG
|
||||
bool "Enable Image signature verification support"
|
||||
default y
|
||||
depends on KEXEC_VERIFY_SIG
|
||||
depends on KEXEC_SIG
|
||||
depends on EFI && SIGNED_PE_FILE_VERIFICATION
|
||||
help
|
||||
Enable Image signature verification support.
|
||||
|
||||
comment "Support for PE file signature verification disabled"
|
||||
depends on KEXEC_VERIFY_SIG
|
||||
depends on KEXEC_SIG
|
||||
depends on !EFI || !SIGNED_PE_FILE_VERIFICATION
|
||||
|
||||
config CRASH_DUMP
|
||||
|
|
|
@ -555,7 +555,7 @@ config ARCH_HAS_KEXEC_PURGATORY
|
|||
def_bool y
|
||||
depends on KEXEC_FILE
|
||||
|
||||
config KEXEC_VERIFY_SIG
|
||||
config KEXEC_SIG
|
||||
bool "Verify kernel signature during kexec_file_load() syscall"
|
||||
depends on KEXEC_FILE && SYSTEM_DATA_VERIFICATION
|
||||
help
|
||||
|
|
|
@ -64,7 +64,7 @@ CONFIG_NUMA=y
|
|||
CONFIG_PREEMPT=y
|
||||
CONFIG_HZ_100=y
|
||||
CONFIG_KEXEC_FILE=y
|
||||
CONFIG_KEXEC_VERIFY_SIG=y
|
||||
CONFIG_KEXEC_SIG=y
|
||||
CONFIG_EXPOLINE=y
|
||||
CONFIG_EXPOLINE_AUTO=y
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
|
|
|
@ -39,7 +39,7 @@ CONFIG_NR_CPUS=256
|
|||
CONFIG_NUMA=y
|
||||
CONFIG_HZ_100=y
|
||||
CONFIG_KEXEC_FILE=y
|
||||
CONFIG_KEXEC_VERIFY_SIG=y
|
||||
CONFIG_KEXEC_SIG=y
|
||||
CONFIG_CRASH_DUMP=y
|
||||
CONFIG_HIBERNATION=y
|
||||
CONFIG_PM_DEBUG=y
|
||||
|
|
|
@ -65,7 +65,7 @@ CONFIG_NR_CPUS=512
|
|||
CONFIG_NUMA=y
|
||||
CONFIG_HZ_100=y
|
||||
CONFIG_KEXEC_FILE=y
|
||||
CONFIG_KEXEC_VERIFY_SIG=y
|
||||
CONFIG_KEXEC_SIG=y
|
||||
CONFIG_EXPOLINE=y
|
||||
CONFIG_EXPOLINE_AUTO=y
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
|
|
|
@ -130,7 +130,7 @@ static int s390_elf_probe(const char *buf, unsigned long len)
|
|||
const struct kexec_file_ops s390_kexec_elf_ops = {
|
||||
.probe = s390_elf_probe,
|
||||
.load = s390_elf_load,
|
||||
#ifdef CONFIG_KEXEC_VERIFY_SIG
|
||||
#ifdef CONFIG_KEXEC__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)
|
|||
const struct kexec_file_ops s390_kexec_image_ops = {
|
||||
.probe = s390_image_probe,
|
||||
.load = s390_image_load,
|
||||
#ifdef CONFIG_KEXEC_VERIFY_SIG
|
||||
#ifdef CONFIG_KEXEC_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[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_KEXEC_VERIFY_SIG
|
||||
#ifdef CONFIG_KEXEC_SIG
|
||||
/*
|
||||
* Module signature information block.
|
||||
*
|
||||
|
@ -90,7 +90,7 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
|
|||
VERIFYING_MODULE_SIGNATURE,
|
||||
NULL, NULL);
|
||||
}
|
||||
#endif /* CONFIG_KEXEC_VERIFY_SIG */
|
||||
#endif /* CONFIG_KEXEC_SIG */
|
||||
|
||||
static int kexec_file_update_purgatory(struct kimage *image,
|
||||
struct s390_load_data *data)
|
||||
|
|
|
@ -2006,20 +2006,30 @@ config KEXEC_FILE
|
|||
config ARCH_HAS_KEXEC_PURGATORY
|
||||
def_bool KEXEC_FILE
|
||||
|
||||
config KEXEC_VERIFY_SIG
|
||||
config KEXEC_SIG
|
||||
bool "Verify kernel signature during kexec_file_load() syscall"
|
||||
depends on KEXEC_FILE
|
||||
---help---
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
In addition to that option, you need to enable signature
|
||||
verification for the corresponding kernel image type being
|
||||
loaded in order for this to work.
|
||||
|
||||
config KEXEC_BZIMAGE_VERIFY_SIG
|
||||
bool "Enable bzImage signature verification support"
|
||||
depends on KEXEC_VERIFY_SIG
|
||||
depends on KEXEC_SIG
|
||||
depends on SIGNED_PE_FILE_VERIFICATION
|
||||
select SYSTEM_TRUSTED_KEYRING
|
||||
---help---
|
||||
|
|
|
@ -66,9 +66,9 @@ bool arch_ima_get_secureboot(void)
|
|||
|
||||
/* secureboot 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",
|
||||
#endif /* CONFIG_KEXEC_VERIFY_SIG */
|
||||
#endif /* CONFIG_KEXEC_SIG */
|
||||
"measure func=KEXEC_KERNEL_CHECK",
|
||||
#if !IS_ENABLED(CONFIG_MODULE_SIG)
|
||||
"appraise func=MODULE_CHECK appraise_type=imasig",
|
||||
|
|
|
@ -96,7 +96,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
|
|||
|
||||
if (!ddir->certs.virtual_address || !ddir->certs.size) {
|
||||
pr_debug("Unsigned PE binary\n");
|
||||
return -EKEYREJECTED;
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
chkaddr(ctx->header_size, ddir->certs.virtual_address,
|
||||
|
@ -403,6 +403,8 @@ error_no_desc:
|
|||
* (*) 0 if at least one signature chain intersects with the keys in the trust
|
||||
* keyring, or:
|
||||
*
|
||||
* (*) -ENODATA if there is no signature present.
|
||||
*
|
||||
* (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
|
||||
* chain.
|
||||
*
|
||||
|
|
|
@ -125,7 +125,7 @@ typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf,
|
|||
unsigned long cmdline_len);
|
||||
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,
|
||||
unsigned long kernel_len);
|
||||
#endif
|
||||
|
@ -134,7 +134,7 @@ struct kexec_file_ops {
|
|||
kexec_probe_t *probe;
|
||||
kexec_load_t *load;
|
||||
kexec_cleanup_t *cleanup;
|
||||
#ifdef CONFIG_KEXEC_VERIFY_SIG
|
||||
#ifdef CONFIG_KEXEC_SIG
|
||||
kexec_verify_sig_t *verify_sig;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -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,51 @@ 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;
|
||||
}
|
||||
|
||||
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 +231,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;
|
||||
|
||||
|
@ -205,14 +250,11 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
|
|||
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)) {
|
||||
|
|
|
@ -160,7 +160,7 @@ config IMA_APPRAISE
|
|||
|
||||
config IMA_ARCH_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
|
||||
help
|
||||
This option enables loading an IMA architecture specific policy
|
||||
|
|
|
@ -541,7 +541,7 @@ int ima_load_data(enum kernel_load_data_id id)
|
|||
|
||||
switch (id) {
|
||||
case LOADING_KEXEC_IMAGE:
|
||||
if (IS_ENABLED(CONFIG_KEXEC_VERIFY_SIG)
|
||||
if (IS_ENABLED(CONFIG_KEXEC_SIG)
|
||||
&& arch_ima_get_secureboot()) {
|
||||
pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
|
||||
return -EACCES;
|
||||
|
|
Loading…
Reference in New Issue