s390/kexec_file: Signature verification prototype

Add kernel signature verification to kexec_file. The verification is based
on module signature verification and works with kernel images signed via
scripts/sign-file.

Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Philipp Rudo 2019-02-26 10:50:39 +01:00 committed by Martin Schwidefsky
parent 653beba24d
commit e23a8020ce
8 changed files with 95 additions and 0 deletions

View File

@ -553,6 +553,17 @@ config ARCH_HAS_KEXEC_PURGATORY
def_bool y
depends on KEXEC_FILE
config KEXEC_VERIFY_SIG
bool "Verify kernel signature during kexec_file_load() syscall"
depends on KEXEC_FILE && SYSTEM_DATA_VERIFICATION
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 ARCH_RANDOM
def_bool y
prompt "s390 architectural random number generation API"

View File

@ -64,6 +64,7 @@ CONFIG_NUMA=y
CONFIG_PREEMPT=y
CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y
CONFIG_EXPOLINE=y
CONFIG_EXPOLINE_AUTO=y
CONFIG_MEMORY_HOTPLUG=y

View File

@ -65,6 +65,7 @@ CONFIG_NR_CPUS=512
CONFIG_NUMA=y
CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y
CONFIG_EXPOLINE=y
CONFIG_EXPOLINE_AUTO=y
CONFIG_MEMORY_HOTPLUG=y

View File

@ -39,6 +39,7 @@ CONFIG_NR_CPUS=256
CONFIG_NUMA=y
CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y
CONFIG_CRASH_DUMP=y
CONFIG_HIBERNATION=y
CONFIG_PM_DEBUG=y

View File

@ -65,6 +65,7 @@ struct s390_load_data {
size_t memsz;
};
int s390_verify_sig(const char *kernel, unsigned long kernel_len);
void *kexec_file_add_components(struct kimage *image,
int (*add_kernel)(struct kimage *image,
struct s390_load_data *data));

View File

@ -125,4 +125,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
.verify_sig = s390_verify_sig,
#endif /* CONFIG_KEXEC_VERIFY_SIG */
};

View File

@ -54,4 +54,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
.verify_sig = s390_verify_sig,
#endif /* CONFIG_KEXEC_VERIFY_SIG */
};

View File

@ -8,7 +8,11 @@
*/
#include <linux/elf.h>
#include <linux/errno.h>
#include <linux/kexec.h>
#include <linux/module.h>
#include <linux/verification.h>
#include <asm/ipl.h>
#include <asm/setup.h>
const struct kexec_file_ops * const kexec_file_loaders[] = {
@ -17,6 +21,76 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
NULL,
};
#ifdef CONFIG_KEXEC_VERIFY_SIG
/*
* Module signature information block.
*
* The constituents of the signature section are, in order:
*
* - Signer's name
* - Key identifier
* - Signature data
* - Information block
*/
struct module_signature {
u8 algo; /* Public-key crypto algorithm [0] */
u8 hash; /* Digest algorithm [0] */
u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
u8 signer_len; /* Length of signer's name [0] */
u8 key_id_len; /* Length of key identifier [0] */
u8 __pad[3];
__be32 sig_len; /* Length of signature data */
};
#define PKEY_ID_PKCS7 2
int s390_verify_sig(const char *kernel, unsigned long kernel_len)
{
const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
struct module_signature *ms;
unsigned long sig_len;
/* Skip signature verification when not secure IPLed. */
if (!ipl_secure_flag)
return 0;
if (marker_len > kernel_len)
return -EKEYREJECTED;
if (memcmp(kernel + kernel_len - marker_len, MODULE_SIG_STRING,
marker_len))
return -EKEYREJECTED;
kernel_len -= marker_len;
ms = (void *)kernel + kernel_len - sizeof(*ms);
kernel_len -= sizeof(*ms);
sig_len = be32_to_cpu(ms->sig_len);
if (sig_len >= kernel_len)
return -EKEYREJECTED;
kernel_len -= sig_len;
if (ms->id_type != PKEY_ID_PKCS7)
return -EKEYREJECTED;
if (ms->algo != 0 ||
ms->hash != 0 ||
ms->signer_len != 0 ||
ms->key_id_len != 0 ||
ms->__pad[0] != 0 ||
ms->__pad[1] != 0 ||
ms->__pad[2] != 0) {
return -EBADMSG;
}
return verify_pkcs7_signature(kernel, kernel_len,
kernel + kernel_len, sig_len,
VERIFY_USE_PLATFORM_KEYRING,
VERIFYING_MODULE_SIGNATURE,
NULL, NULL);
}
#endif /* CONFIG_KEXEC_VERIFY_SIG */
static int kexec_file_update_purgatory(struct kimage *image,
struct s390_load_data *data)
{