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:
parent
653beba24d
commit
e23a8020ce
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue