Skip to content

Commit 7af6e3f

Browse files
committed
Merge tag 'integrity-v6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity updates from Mimi Zohar: "Carrying the IMA measurement list across kexec is not a new feature, but is updated to address a couple of issues: - Carrying the IMA measurement list across kexec required knowing apriori all the file measurements between the "kexec load" and "kexec execute" in order to measure them before the "kexec load". Any delay between the "kexec load" and "kexec exec" exacerbated the problem. - Any file measurements post "kexec load" were not carried across kexec, resulting in the measurement list being out of sync with the TPM PCR. With these changes, the buffer for the IMA measurement list is still allocated at "kexec load", but copying the IMA measurement list is deferred to after quiescing the TPM. Two new kexec critical data records are defined" * tag 'integrity-v6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: ima: do not copy measurement list to kdump kernel ima: measure kexec load and exec events as critical data ima: make the kexec extra memory configurable ima: verify if the segment size has changed ima: kexec: move IMA log copy from kexec load to execute ima: kexec: define functions to copy IMA log at soft boot ima: kexec: skip IMA segment validation after kexec soft reboot kexec: define functions to map and unmap segments ima: define and call ima_alloc_kexec_file_buf() ima: rename variable the seq_file "file" to "ima_kexec_file"
2 parents cbaed2f + fe3aebf commit 7af6e3f

8 files changed

Lines changed: 283 additions & 34 deletions

File tree

include/linux/ima.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ static inline void ima_appraise_parse_cmdline(void) {}
3232

3333
#ifdef CONFIG_IMA_KEXEC
3434
extern void ima_add_kexec_buffer(struct kimage *image);
35+
extern void ima_kexec_post_load(struct kimage *image);
36+
#else
37+
static inline void ima_kexec_post_load(struct kimage *image) {}
3538
#endif
3639

3740
#else

include/linux/kexec.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ struct kimage {
369369

370370
phys_addr_t ima_buffer_addr;
371371
size_t ima_buffer_size;
372+
373+
unsigned long ima_segment_index;
374+
bool is_ima_segment_index_set;
372375
#endif
373376

374377
/* Core ELF header buffer */
@@ -474,13 +477,19 @@ extern bool kexec_file_dbg_print;
474477
#define kexec_dprintk(fmt, arg...) \
475478
do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
476479

480+
extern void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size);
481+
extern void kimage_unmap_segment(void *buffer);
477482
#else /* !CONFIG_KEXEC_CORE */
478483
struct pt_regs;
479484
struct task_struct;
485+
struct kimage;
480486
static inline void __crash_kexec(struct pt_regs *regs) { }
481487
static inline void crash_kexec(struct pt_regs *regs) { }
482488
static inline int kexec_should_crash(struct task_struct *p) { return 0; }
483489
static inline int kexec_crash_loaded(void) { return 0; }
490+
static inline void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size)
491+
{ return NULL; }
492+
static inline void kimage_unmap_segment(void *buffer) { }
484493
#define kexec_in_progress false
485494
#endif /* CONFIG_KEXEC_CORE */
486495

kernel/kexec_core.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,60 @@ int kimage_load_segment(struct kimage *image,
877877
return result;
878878
}
879879

880+
void *kimage_map_segment(struct kimage *image,
881+
unsigned long addr, unsigned long size)
882+
{
883+
unsigned long src_page_addr, dest_page_addr = 0;
884+
unsigned long eaddr = addr + size;
885+
kimage_entry_t *ptr, entry;
886+
struct page **src_pages;
887+
unsigned int npages;
888+
void *vaddr = NULL;
889+
int i;
890+
891+
/*
892+
* Collect the source pages and map them in a contiguous VA range.
893+
*/
894+
npages = PFN_UP(eaddr) - PFN_DOWN(addr);
895+
src_pages = kmalloc_array(npages, sizeof(*src_pages), GFP_KERNEL);
896+
if (!src_pages) {
897+
pr_err("Could not allocate ima pages array.\n");
898+
return NULL;
899+
}
900+
901+
i = 0;
902+
for_each_kimage_entry(image, ptr, entry) {
903+
if (entry & IND_DESTINATION) {
904+
dest_page_addr = entry & PAGE_MASK;
905+
} else if (entry & IND_SOURCE) {
906+
if (dest_page_addr >= addr && dest_page_addr < eaddr) {
907+
src_page_addr = entry & PAGE_MASK;
908+
src_pages[i++] =
909+
virt_to_page(__va(src_page_addr));
910+
if (i == npages)
911+
break;
912+
dest_page_addr += PAGE_SIZE;
913+
}
914+
}
915+
}
916+
917+
/* Sanity check. */
918+
WARN_ON(i < npages);
919+
920+
vaddr = vmap(src_pages, npages, VM_MAP, PAGE_KERNEL);
921+
kfree(src_pages);
922+
923+
if (!vaddr)
924+
pr_err("Could not map ima buffer.\n");
925+
926+
return vaddr;
927+
}
928+
929+
void kimage_unmap_segment(void *segment_buffer)
930+
{
931+
vunmap(segment_buffer);
932+
}
933+
880934
struct kexec_load_limit {
881935
/* Mutex protects the limit count. */
882936
struct mutex mutex;

kernel/kexec_file.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ void set_kexec_sig_enforced(void)
3838
}
3939
#endif
4040

41+
#ifdef CONFIG_IMA_KEXEC
42+
static bool check_ima_segment_index(struct kimage *image, int i)
43+
{
44+
if (image->is_ima_segment_index_set && i == image->ima_segment_index)
45+
return true;
46+
else
47+
return false;
48+
}
49+
#else
50+
static bool check_ima_segment_index(struct kimage *image, int i)
51+
{
52+
return false;
53+
}
54+
#endif
55+
4156
static int kexec_calculate_store_digests(struct kimage *image);
4257

4358
/* Maximum size in bytes for kernel/initrd files. */
@@ -186,6 +201,15 @@ kimage_validate_signature(struct kimage *image)
186201
}
187202
#endif
188203

204+
static int kexec_post_load(struct kimage *image, unsigned long flags)
205+
{
206+
#ifdef CONFIG_IMA_KEXEC
207+
if (!(flags & KEXEC_FILE_ON_CRASH))
208+
ima_kexec_post_load(image);
209+
#endif
210+
return machine_kexec_post_load(image);
211+
}
212+
189213
/*
190214
* In file mode list of segments is prepared by kernel. Copy relevant
191215
* data from user space, do error checking, prepare segment list
@@ -413,7 +437,7 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
413437

414438
kimage_terminate(image);
415439

416-
ret = machine_kexec_post_load(image);
440+
ret = kexec_post_load(image, flags);
417441
if (ret)
418442
goto out;
419443

@@ -776,6 +800,13 @@ static int kexec_calculate_store_digests(struct kimage *image)
776800
if (ksegment->kbuf == pi->purgatory_buf)
777801
continue;
778802

803+
/*
804+
* Skip the segment if ima_segment_index is set and matches
805+
* the current index
806+
*/
807+
if (check_ima_segment_index(image, i))
808+
continue;
809+
779810
ret = crypto_shash_update(desc, ksegment->kbuf,
780811
ksegment->bufsz);
781812
if (ret)

security/integrity/ima/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,4 +321,15 @@ config IMA_DISABLE_HTABLE
321321
help
322322
This option disables htable to allow measurement of duplicate records.
323323

324+
config IMA_KEXEC_EXTRA_MEMORY_KB
325+
int "Extra memory for IMA measurements added during kexec soft reboot"
326+
range 0 40
327+
depends on IMA_KEXEC
328+
default 0
329+
help
330+
IMA_KEXEC_EXTRA_MEMORY_KB determines the extra memory to be
331+
allocated (in kb) for IMA measurements added during kexec soft reboot.
332+
If set to the default value of 0, an extra half page of memory for those
333+
additional measurements will be allocated.
334+
324335
endif

security/integrity/ima/ima.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
244244
unsigned long flags, bool create);
245245
#endif
246246

247+
#ifdef CONFIG_IMA_KEXEC
248+
void ima_measure_kexec_event(const char *event_name);
249+
#else
250+
static inline void ima_measure_kexec_event(const char *event_name) {}
251+
#endif
252+
247253
/*
248254
* The default binary_runtime_measurements list format is defined as the
249255
* platform native format. The canonical format is defined as little-endian.

0 commit comments

Comments
 (0)