- Add the ability to pass early an RNG seed to the kernel from the boot
loader - Add the ability to pass the IMA measurement of kernel and bootloader to the kexec-ed kernel -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmLn770ACgkQEsHwGGHe VUoOyA//R7ljAspkzqE+kY02GOXCvVo+Ix/WFbpeUMouSb71vxjyqJED6lMrWKvM HPzXwuQ5C1bXIbvWW424l66q9O48Iu3FvnURGc05ngBvgnyLxw+IdfWREr3rhVtR ZKdaMHCzj1RsxCRYXie4NIyW86D1Bd4V4W7KFG/u26LSo9VL2oY1JXd0vxXrh0e6 F4pwJsS+5TrgaFPwfSLm66HWlM2oxmqBVD/Fi8Pmzq7/ewb3KSgIWralOjew5X13 f4ob9GVLojM9yVPLSww0p2CRitlxypO5pv3rsrcwo77UhikflFk4Ruc4IeMd4792 ZszDCyWWCzFHZDizo2tni4IbcKtOx1lL389sYj/ZVsAYarGzeRRNYpN5TE6cSFXK 6hqurMMTDrmeczScBK3uQ4BFkMzWYGCYWy6JNrTmD43Onb5fe2usWIbpz+oFB0Kd 26Oa85lAKUhOUTnU1yM5aeRYBYiouyD80BRKgve5pcN00BXwO0OOny5sijFt3hvC 266k2g/+zY6wNawnEesNfLFkUvR09416xEbe5W3l64vlCGsjt9doB4vPKLkHBXq4 YilUVFFT3/djTvfLy50L2ta9oNdYXK7ECfGj0t2UCcnj0IrO4E0Cm0BlPN8r/a6L gwE9I4txaYZmT8VRBG2kiyUljUSqZUj1UFHevMuCS09dzLonJN4= =s9Om -----END PGP SIGNATURE----- Merge tag 'x86_kdump_for_v6.0_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 kdump updates from Borislav Petkov: - Add the ability to pass early an RNG seed to the kernel from the boot loader - Add the ability to pass the IMA measurement of kernel and bootloader to the kexec-ed kernel * tag 'x86_kdump_for_v6.0_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/setup: Use rng seeds from setup_data x86/kexec: Carry forward IMA measurement log on kexec
This commit is contained in:
commit
60ee49fac8
@ -2010,6 +2010,7 @@ config KEXEC
|
||||
config KEXEC_FILE
|
||||
bool "kexec file based system call"
|
||||
select KEXEC_CORE
|
||||
select HAVE_IMA_KEXEC if IMA
|
||||
depends on X86_64
|
||||
depends on CRYPTO=y
|
||||
depends on CRYPTO_SHA256=y
|
||||
|
@ -11,11 +11,12 @@
|
||||
#define SETUP_APPLE_PROPERTIES 5
|
||||
#define SETUP_JAILHOUSE 6
|
||||
#define SETUP_CC_BLOB 7
|
||||
#define SETUP_IMA 8
|
||||
#define SETUP_RNG_SEED 9
|
||||
#define SETUP_ENUM_MAX SETUP_RNG_SEED
|
||||
|
||||
#define SETUP_INDIRECT (1<<31)
|
||||
|
||||
/* SETUP_INDIRECT | max(SETUP_*) */
|
||||
#define SETUP_TYPE_MAX (SETUP_INDIRECT | SETUP_CC_BLOB)
|
||||
#define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT)
|
||||
|
||||
/* ram_size flags */
|
||||
#define RAMDISK_IMAGE_START_MASK 0x07FF
|
||||
@ -172,6 +173,14 @@ struct jailhouse_setup_data {
|
||||
} __attribute__((packed)) v2;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* IMA buffer setup data information from the previous kernel during kexec
|
||||
*/
|
||||
struct ima_setup_data {
|
||||
__u64 addr;
|
||||
__u64 size;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* The so-called "zeropage" */
|
||||
struct boot_params {
|
||||
struct screen_info screen_info; /* 0x000 */
|
||||
|
@ -1017,10 +1017,10 @@ void __init e820__reserve_setup_data(void)
|
||||
e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
|
||||
|
||||
/*
|
||||
* SETUP_EFI is supplied by kexec and does not need to be
|
||||
* reserved.
|
||||
* SETUP_EFI and SETUP_IMA are supplied by kexec and do not need
|
||||
* to be reserved.
|
||||
*/
|
||||
if (data->type != SETUP_EFI)
|
||||
if (data->type != SETUP_EFI && data->type != SETUP_IMA)
|
||||
e820__range_update_kexec(pa_data,
|
||||
sizeof(*data) + data->len,
|
||||
E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/verification.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <asm/bootparam.h>
|
||||
#include <asm/setup.h>
|
||||
@ -110,6 +111,26 @@ static int setup_e820_entries(struct boot_params *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum { RNG_SEED_LENGTH = 32 };
|
||||
|
||||
static void
|
||||
setup_rng_seed(struct boot_params *params, unsigned long params_load_addr,
|
||||
unsigned int rng_seed_setup_data_offset)
|
||||
{
|
||||
struct setup_data *sd = (void *)params + rng_seed_setup_data_offset;
|
||||
unsigned long setup_data_phys;
|
||||
|
||||
if (!rng_is_initialized())
|
||||
return;
|
||||
|
||||
sd->type = SETUP_RNG_SEED;
|
||||
sd->len = RNG_SEED_LENGTH;
|
||||
get_random_bytes(sd->data, RNG_SEED_LENGTH);
|
||||
setup_data_phys = params_load_addr + rng_seed_setup_data_offset;
|
||||
sd->next = params->hdr.setup_data;
|
||||
params->hdr.setup_data = setup_data_phys;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
static int setup_efi_info_memmap(struct boot_params *params,
|
||||
unsigned long params_load_addr,
|
||||
@ -186,11 +207,38 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
|
||||
}
|
||||
#endif /* CONFIG_EFI */
|
||||
|
||||
static void
|
||||
setup_ima_state(const struct kimage *image, struct boot_params *params,
|
||||
unsigned long params_load_addr,
|
||||
unsigned int ima_setup_data_offset)
|
||||
{
|
||||
#ifdef CONFIG_IMA_KEXEC
|
||||
struct setup_data *sd = (void *)params + ima_setup_data_offset;
|
||||
unsigned long setup_data_phys;
|
||||
struct ima_setup_data *ima;
|
||||
|
||||
if (!image->ima_buffer_size)
|
||||
return;
|
||||
|
||||
sd->type = SETUP_IMA;
|
||||
sd->len = sizeof(*ima);
|
||||
|
||||
ima = (void *)sd + sizeof(struct setup_data);
|
||||
ima->addr = image->ima_buffer_addr;
|
||||
ima->size = image->ima_buffer_size;
|
||||
|
||||
/* Add setup data */
|
||||
setup_data_phys = params_load_addr + ima_setup_data_offset;
|
||||
sd->next = params->hdr.setup_data;
|
||||
params->hdr.setup_data = setup_data_phys;
|
||||
#endif /* CONFIG_IMA_KEXEC */
|
||||
}
|
||||
|
||||
static int
|
||||
setup_boot_parameters(struct kimage *image, struct boot_params *params,
|
||||
unsigned long params_load_addr,
|
||||
unsigned int efi_map_offset, unsigned int efi_map_sz,
|
||||
unsigned int efi_setup_data_offset)
|
||||
unsigned int setup_data_offset)
|
||||
{
|
||||
unsigned int nr_e820_entries;
|
||||
unsigned long long mem_k, start, end;
|
||||
@ -245,8 +293,22 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
|
||||
#ifdef CONFIG_EFI
|
||||
/* Setup EFI state */
|
||||
setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz,
|
||||
efi_setup_data_offset);
|
||||
setup_data_offset);
|
||||
setup_data_offset += sizeof(struct setup_data) +
|
||||
sizeof(struct efi_setup_data);
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_IMA_KEXEC)) {
|
||||
/* Setup IMA log buffer state */
|
||||
setup_ima_state(image, params, params_load_addr,
|
||||
setup_data_offset);
|
||||
setup_data_offset += sizeof(struct setup_data) +
|
||||
sizeof(struct ima_setup_data);
|
||||
}
|
||||
|
||||
/* Setup RNG seed */
|
||||
setup_rng_seed(params, params_load_addr, setup_data_offset);
|
||||
|
||||
/* Setup EDD info */
|
||||
memcpy(params->eddbuf, boot_params.eddbuf,
|
||||
EDDMAXNR * sizeof(struct edd_info));
|
||||
@ -401,7 +463,13 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
|
||||
params_cmdline_sz = ALIGN(params_cmdline_sz, 16);
|
||||
kbuf.bufsz = params_cmdline_sz + ALIGN(efi_map_sz, 16) +
|
||||
sizeof(struct setup_data) +
|
||||
sizeof(struct efi_setup_data);
|
||||
sizeof(struct efi_setup_data) +
|
||||
sizeof(struct setup_data) +
|
||||
RNG_SEED_LENGTH;
|
||||
|
||||
if (IS_ENABLED(CONFIG_IMA_KEXEC))
|
||||
kbuf.bufsz += sizeof(struct setup_data) +
|
||||
sizeof(struct ima_setup_data);
|
||||
|
||||
params = kzalloc(kbuf.bufsz, GFP_KERNEL);
|
||||
if (!params)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/ima.h>
|
||||
#include <linux/init_ohci1394_dma.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/iscsi_ibft.h>
|
||||
@ -23,6 +24,7 @@
|
||||
#include <linux/usb/xhci-dbgp.h>
|
||||
#include <linux/static_call.h>
|
||||
#include <linux/swiotlb.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <uapi/linux/mount.h>
|
||||
|
||||
@ -140,6 +142,11 @@ __visible unsigned long mmu_cr4_features __ro_after_init;
|
||||
__visible unsigned long mmu_cr4_features __ro_after_init = X86_CR4_PAE;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IMA
|
||||
static phys_addr_t ima_kexec_buffer_phys;
|
||||
static size_t ima_kexec_buffer_size;
|
||||
#endif
|
||||
|
||||
/* Boot loader ID and version as integers, for the benefit of proc_dointvec */
|
||||
int bootloader_type, bootloader_version;
|
||||
|
||||
@ -330,6 +337,60 @@ static void __init reserve_initrd(void)
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
|
||||
static void __init add_early_ima_buffer(u64 phys_addr)
|
||||
{
|
||||
#ifdef CONFIG_IMA
|
||||
struct ima_setup_data *data;
|
||||
|
||||
data = early_memremap(phys_addr + sizeof(struct setup_data), sizeof(*data));
|
||||
if (!data) {
|
||||
pr_warn("setup: failed to memremap ima_setup_data entry\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->size) {
|
||||
memblock_reserve(data->addr, data->size);
|
||||
ima_kexec_buffer_phys = data->addr;
|
||||
ima_kexec_buffer_size = data->size;
|
||||
}
|
||||
|
||||
early_memunmap(data, sizeof(*data));
|
||||
#else
|
||||
pr_warn("Passed IMA kexec data, but CONFIG_IMA not set. Ignoring.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_HAVE_IMA_KEXEC) && !defined(CONFIG_OF_FLATTREE)
|
||||
int __init ima_free_kexec_buffer(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!ima_kexec_buffer_size)
|
||||
return -ENOENT;
|
||||
|
||||
rc = memblock_phys_free(ima_kexec_buffer_phys,
|
||||
ima_kexec_buffer_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ima_kexec_buffer_phys = 0;
|
||||
ima_kexec_buffer_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init ima_get_kexec_buffer(void **addr, size_t *size)
|
||||
{
|
||||
if (!ima_kexec_buffer_size)
|
||||
return -ENOENT;
|
||||
|
||||
*addr = __va(ima_kexec_buffer_phys);
|
||||
*size = ima_kexec_buffer_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __init parse_setup_data(void)
|
||||
{
|
||||
struct setup_data *data;
|
||||
@ -355,6 +416,18 @@ static void __init parse_setup_data(void)
|
||||
case SETUP_EFI:
|
||||
parse_efi_setup(pa_data, data_len);
|
||||
break;
|
||||
case SETUP_IMA:
|
||||
add_early_ima_buffer(pa_data);
|
||||
break;
|
||||
case SETUP_RNG_SEED:
|
||||
data = early_memremap(pa_data, data_len);
|
||||
add_bootloader_randomness(data->data, data->len);
|
||||
/* Zero seed for forward secrecy. */
|
||||
memzero_explicit(data->data, data->len);
|
||||
/* Zero length in case we find ourselves back here by accident. */
|
||||
memzero_explicit(&data->len, sizeof(data->len));
|
||||
early_memunmap(data, data_len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
* Copyright (C) 2016 IBM Corporation
|
||||
*/
|
||||
|
||||
#include <linux/ima.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/memblock.h>
|
||||
@ -115,6 +116,7 @@ static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_IMA_KEXEC
|
||||
/**
|
||||
* ima_get_kexec_buffer - get IMA buffer from the previous kernel
|
||||
* @addr: On successful return, set to point to the buffer contents.
|
||||
@ -122,16 +124,13 @@ static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
|
||||
*
|
||||
* Return: 0 on success, negative errno on error.
|
||||
*/
|
||||
int ima_get_kexec_buffer(void **addr, size_t *size)
|
||||
int __init ima_get_kexec_buffer(void **addr, size_t *size)
|
||||
{
|
||||
int ret, len;
|
||||
unsigned long tmp_addr;
|
||||
size_t tmp_size;
|
||||
const void *prop;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
|
||||
return -ENOTSUPP;
|
||||
|
||||
prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
|
||||
if (!prop)
|
||||
return -ENOENT;
|
||||
@ -149,16 +148,13 @@ int ima_get_kexec_buffer(void **addr, size_t *size)
|
||||
/**
|
||||
* ima_free_kexec_buffer - free memory used by the IMA buffer
|
||||
*/
|
||||
int ima_free_kexec_buffer(void)
|
||||
int __init ima_free_kexec_buffer(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long addr;
|
||||
size_t size;
|
||||
struct property *prop;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
|
||||
return -ENOTSUPP;
|
||||
|
||||
prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
|
||||
if (!prop)
|
||||
return -ENOENT;
|
||||
@ -173,6 +169,7 @@ int ima_free_kexec_buffer(void)
|
||||
|
||||
return memblock_phys_free(addr, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
|
||||
|
@ -140,6 +140,11 @@ static inline int ima_measure_critical_data(const char *event_label,
|
||||
|
||||
#endif /* CONFIG_IMA */
|
||||
|
||||
#ifdef CONFIG_HAVE_IMA_KEXEC
|
||||
int __init ima_free_kexec_buffer(void);
|
||||
int __init ima_get_kexec_buffer(void **addr, size_t *size);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
|
||||
extern bool arch_ima_get_secureboot(void);
|
||||
extern const char * const *arch_get_ima_policy(void);
|
||||
|
@ -441,8 +441,6 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
|
||||
unsigned long initrd_load_addr,
|
||||
unsigned long initrd_len,
|
||||
const char *cmdline, size_t extra_fdt_size);
|
||||
int ima_get_kexec_buffer(void **addr, size_t *size);
|
||||
int ima_free_kexec_buffer(void);
|
||||
#else /* CONFIG_OF */
|
||||
|
||||
static inline void of_core_init(void)
|
||||
|
@ -137,7 +137,7 @@ void ima_add_kexec_buffer(struct kimage *image)
|
||||
/*
|
||||
* Restore the measurement list from the previous kernel.
|
||||
*/
|
||||
void ima_load_kexec_buffer(void)
|
||||
void __init ima_load_kexec_buffer(void)
|
||||
{
|
||||
void *kexec_buffer = NULL;
|
||||
size_t kexec_buffer_size = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user