Skip to content

Commit b69a2af

Browse files
u1f35csuryasaimadhu
authored andcommitted
x86/kexec: Carry forward IMA measurement log on kexec
On kexec file load, the Integrity Measurement Architecture (IMA) subsystem may verify the IMA signature of the kernel and initramfs, and measure it. The command line parameters passed to the kernel in the kexec call may also be measured by IMA. A remote attestation service can verify a TPM quote based on the TPM event log, the IMA measurement list and the TPM PCR data. This can be achieved only if the IMA measurement log is carried over from the current kernel to the next kernel across the kexec call. PowerPC and ARM64 both achieve this using device tree with a "linux,ima-kexec-buffer" node. x86 platforms generally don't make use of device tree, so use the setup_data mechanism to pass the IMA buffer to the new kernel. Signed-off-by: Jonathan McDowell <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Reviewed-by: Mimi Zohar <[email protected]> # IMA function definitions Link: https://lore.kernel.org/r/YmKyvlF3my1yWTvK@noodles-fedora-PC23Y6EG
1 parent 03c765b commit b69a2af

File tree

9 files changed

+127
-16
lines changed

9 files changed

+127
-16
lines changed

arch/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,6 +2033,7 @@ config KEXEC_FILE
20332033
bool "kexec file based system call"
20342034
select KEXEC_CORE
20352035
select BUILD_BIN2C
2036+
select HAVE_IMA_KEXEC if IMA
20362037
depends on X86_64
20372038
depends on CRYPTO=y
20382039
depends on CRYPTO_SHA256=y

arch/x86/include/uapi/asm/bootparam.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define SETUP_APPLE_PROPERTIES 5
1212
#define SETUP_JAILHOUSE 6
1313
#define SETUP_CC_BLOB 7
14+
#define SETUP_IMA 8
1415

1516
#define SETUP_INDIRECT (1<<31)
1617

@@ -172,6 +173,14 @@ struct jailhouse_setup_data {
172173
} __attribute__((packed)) v2;
173174
} __attribute__((packed));
174175

176+
/*
177+
* IMA buffer setup data information from the previous kernel during kexec
178+
*/
179+
struct ima_setup_data {
180+
__u64 addr;
181+
__u64 size;
182+
} __attribute__((packed));
183+
175184
/* The so-called "zeropage" */
176185
struct boot_params {
177186
struct screen_info screen_info; /* 0x000 */

arch/x86/kernel/e820.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,10 +1017,10 @@ void __init e820__reserve_setup_data(void)
10171017
e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
10181018

10191019
/*
1020-
* SETUP_EFI is supplied by kexec and does not need to be
1021-
* reserved.
1020+
* SETUP_EFI and SETUP_IMA are supplied by kexec and do not need
1021+
* to be reserved.
10221022
*/
1023-
if (data->type != SETUP_EFI)
1023+
if (data->type != SETUP_EFI && data->type != SETUP_IMA)
10241024
e820__range_update_kexec(pa_data,
10251025
sizeof(*data) + data->len,
10261026
E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);

arch/x86/kernel/kexec-bzimage64.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,38 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
186186
}
187187
#endif /* CONFIG_EFI */
188188

189+
static void
190+
setup_ima_state(const struct kimage *image, struct boot_params *params,
191+
unsigned long params_load_addr,
192+
unsigned int ima_setup_data_offset)
193+
{
194+
#ifdef CONFIG_IMA_KEXEC
195+
struct setup_data *sd = (void *)params + ima_setup_data_offset;
196+
unsigned long setup_data_phys;
197+
struct ima_setup_data *ima;
198+
199+
if (!image->ima_buffer_size)
200+
return;
201+
202+
sd->type = SETUP_IMA;
203+
sd->len = sizeof(*ima);
204+
205+
ima = (void *)sd + sizeof(struct setup_data);
206+
ima->addr = image->ima_buffer_addr;
207+
ima->size = image->ima_buffer_size;
208+
209+
/* Add setup data */
210+
setup_data_phys = params_load_addr + ima_setup_data_offset;
211+
sd->next = params->hdr.setup_data;
212+
params->hdr.setup_data = setup_data_phys;
213+
#endif /* CONFIG_IMA_KEXEC */
214+
}
215+
189216
static int
190217
setup_boot_parameters(struct kimage *image, struct boot_params *params,
191218
unsigned long params_load_addr,
192219
unsigned int efi_map_offset, unsigned int efi_map_sz,
193-
unsigned int efi_setup_data_offset)
220+
unsigned int setup_data_offset)
194221
{
195222
unsigned int nr_e820_entries;
196223
unsigned long long mem_k, start, end;
@@ -245,8 +272,15 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
245272
#ifdef CONFIG_EFI
246273
/* Setup EFI state */
247274
setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz,
248-
efi_setup_data_offset);
275+
setup_data_offset);
276+
setup_data_offset += sizeof(struct setup_data) +
277+
sizeof(struct efi_setup_data);
249278
#endif
279+
280+
/* Setup IMA log buffer state */
281+
setup_ima_state(image, params, params_load_addr,
282+
setup_data_offset);
283+
250284
/* Setup EDD info */
251285
memcpy(params->eddbuf, boot_params.eddbuf,
252286
EDDMAXNR * sizeof(struct edd_info));
@@ -403,6 +437,10 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
403437
sizeof(struct setup_data) +
404438
sizeof(struct efi_setup_data);
405439

440+
if (IS_ENABLED(CONFIG_IMA_KEXEC))
441+
kbuf.bufsz += sizeof(struct setup_data) +
442+
sizeof(struct ima_setup_data);
443+
406444
params = kzalloc(kbuf.bufsz, GFP_KERNEL);
407445
if (!params)
408446
return ERR_PTR(-ENOMEM);

arch/x86/kernel/setup.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/dma-map-ops.h>
1212
#include <linux/dmi.h>
1313
#include <linux/efi.h>
14+
#include <linux/ima.h>
1415
#include <linux/init_ohci1394_dma.h>
1516
#include <linux/initrd.h>
1617
#include <linux/iscsi_ibft.h>
@@ -140,6 +141,11 @@ __visible unsigned long mmu_cr4_features __ro_after_init;
140141
__visible unsigned long mmu_cr4_features __ro_after_init = X86_CR4_PAE;
141142
#endif
142143

144+
#ifdef CONFIG_IMA
145+
static phys_addr_t ima_kexec_buffer_phys;
146+
static size_t ima_kexec_buffer_size;
147+
#endif
148+
143149
/* Boot loader ID and version as integers, for the benefit of proc_dointvec */
144150
int bootloader_type, bootloader_version;
145151

@@ -330,6 +336,60 @@ static void __init reserve_initrd(void)
330336
}
331337
#endif /* CONFIG_BLK_DEV_INITRD */
332338

339+
static void __init add_early_ima_buffer(u64 phys_addr)
340+
{
341+
#ifdef CONFIG_IMA
342+
struct ima_setup_data *data;
343+
344+
data = early_memremap(phys_addr + sizeof(struct setup_data), sizeof(*data));
345+
if (!data) {
346+
pr_warn("setup: failed to memremap ima_setup_data entry\n");
347+
return;
348+
}
349+
350+
if (data->size) {
351+
memblock_reserve(data->addr, data->size);
352+
ima_kexec_buffer_phys = data->addr;
353+
ima_kexec_buffer_size = data->size;
354+
}
355+
356+
early_memunmap(data, sizeof(*data));
357+
#else
358+
pr_warn("Passed IMA kexec data, but CONFIG_IMA not set. Ignoring.\n");
359+
#endif
360+
}
361+
362+
#if defined(CONFIG_HAVE_IMA_KEXEC) && !defined(CONFIG_OF_FLATTREE)
363+
int __init ima_free_kexec_buffer(void)
364+
{
365+
int rc;
366+
367+
if (!ima_kexec_buffer_size)
368+
return -ENOENT;
369+
370+
rc = memblock_phys_free(ima_kexec_buffer_phys,
371+
ima_kexec_buffer_size);
372+
if (rc)
373+
return rc;
374+
375+
ima_kexec_buffer_phys = 0;
376+
ima_kexec_buffer_size = 0;
377+
378+
return 0;
379+
}
380+
381+
int __init ima_get_kexec_buffer(void **addr, size_t *size)
382+
{
383+
if (!ima_kexec_buffer_size)
384+
return -ENOENT;
385+
386+
*addr = __va(ima_kexec_buffer_phys);
387+
*size = ima_kexec_buffer_size;
388+
389+
return 0;
390+
}
391+
#endif
392+
333393
static void __init parse_setup_data(void)
334394
{
335395
struct setup_data *data;
@@ -355,6 +415,9 @@ static void __init parse_setup_data(void)
355415
case SETUP_EFI:
356416
parse_efi_setup(pa_data, data_len);
357417
break;
418+
case SETUP_IMA:
419+
add_early_ima_buffer(pa_data);
420+
break;
358421
default:
359422
break;
360423
}

drivers/of/kexec.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* Copyright (C) 2016 IBM Corporation
1010
*/
1111

12+
#include <linux/ima.h>
1213
#include <linux/kernel.h>
1314
#include <linux/kexec.h>
1415
#include <linux/memblock.h>
@@ -115,23 +116,21 @@ static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
115116
return 0;
116117
}
117118

119+
#ifdef CONFIG_HAVE_IMA_KEXEC
118120
/**
119121
* ima_get_kexec_buffer - get IMA buffer from the previous kernel
120122
* @addr: On successful return, set to point to the buffer contents.
121123
* @size: On successful return, set to the buffer size.
122124
*
123125
* Return: 0 on success, negative errno on error.
124126
*/
125-
int ima_get_kexec_buffer(void **addr, size_t *size)
127+
int __init ima_get_kexec_buffer(void **addr, size_t *size)
126128
{
127129
int ret, len;
128130
unsigned long tmp_addr;
129131
size_t tmp_size;
130132
const void *prop;
131133

132-
if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
133-
return -ENOTSUPP;
134-
135134
prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
136135
if (!prop)
137136
return -ENOENT;
@@ -149,16 +148,13 @@ int ima_get_kexec_buffer(void **addr, size_t *size)
149148
/**
150149
* ima_free_kexec_buffer - free memory used by the IMA buffer
151150
*/
152-
int ima_free_kexec_buffer(void)
151+
int __init ima_free_kexec_buffer(void)
153152
{
154153
int ret;
155154
unsigned long addr;
156155
size_t size;
157156
struct property *prop;
158157

159-
if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
160-
return -ENOTSUPP;
161-
162158
prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
163159
if (!prop)
164160
return -ENOENT;
@@ -173,6 +169,7 @@ int ima_free_kexec_buffer(void)
173169

174170
return memblock_phys_free(addr, size);
175171
}
172+
#endif
176173

177174
/**
178175
* remove_ima_buffer - remove the IMA buffer property and reservation from @fdt

include/linux/ima.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ static inline int ima_measure_critical_data(const char *event_label,
140140

141141
#endif /* CONFIG_IMA */
142142

143+
#ifdef CONFIG_HAVE_IMA_KEXEC
144+
int __init ima_free_kexec_buffer(void);
145+
int __init ima_get_kexec_buffer(void **addr, size_t *size);
146+
#endif
147+
143148
#ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
144149
extern bool arch_ima_get_secureboot(void);
145150
extern const char * const *arch_get_ima_policy(void);

include/linux/of.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,6 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
441441
unsigned long initrd_load_addr,
442442
unsigned long initrd_len,
443443
const char *cmdline, size_t extra_fdt_size);
444-
int ima_get_kexec_buffer(void **addr, size_t *size);
445-
int ima_free_kexec_buffer(void);
446444
#else /* CONFIG_OF */
447445

448446
static inline void of_core_init(void)

security/integrity/ima/ima_kexec.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ void ima_add_kexec_buffer(struct kimage *image)
137137
/*
138138
* Restore the measurement list from the previous kernel.
139139
*/
140-
void ima_load_kexec_buffer(void)
140+
void __init ima_load_kexec_buffer(void)
141141
{
142142
void *kexec_buffer = NULL;
143143
size_t kexec_buffer_size = 0;

0 commit comments

Comments
 (0)