Commit 60ee49fa authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 8b705452 68b8e971
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+12 −3
Original line number Diff line number Diff line
@@ -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 */
+3 −3
Original line number Diff line number Diff line
@@ -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);
+71 −3
Original line number Diff line number Diff line
@@ -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)
+73 −0
Original line number Diff line number Diff line
@@ -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;
		}
Loading