Message ID | 20250416021028.1403-10-chenste@linux.microsoft.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | ima: kexec: measure events between kexec load and execute | expand |
On 04/15/25 at 07:10pm, steven chen wrote: > From: Steven Chen <chenste@linux.microsoft.com> > > The amount of memory allocated at kexec load, even with the extra memory > allocated, might not be large enough for the entire measurement list. The > indeterminate interval between kexec 'load' and 'execute' could exacerbate > this problem. > > Define two new IMA events, 'kexec_load' and 'kexec_execute', to be > measured as critical data at kexec 'load' and 'execute' respectively. > Report the allocated kexec segment size, IMA binary log size and the > runtime measurements count as part of those events. > > These events, and the values reported through them, serve as markers in > the IMA log to verify the IMA events are captured during kexec soft > reboot. The presence of a 'kexec_load' event in between the last two > 'boot_aggregate' events in the IMA log implies this is a kexec soft > reboot, and not a cold-boot. And the absence of 'kexec_execute' event > after kexec soft reboot implies missing events in that window which > results in inconsistency with TPM PCR quotes, necessitating a cold boot > for a successful remote attestation. > > These critical data events are displayed as hex encoded ascii in the > ascii_runtime_measurement_list. Verifying the critical data hash requires > calculating the hash of the decoded ascii string. > > For example, to verify the 'kexec_load' data hash: > > sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements > | grep kexec_load | cut -d' ' -f 6 | xxd -r -p | sha256sum > > > To verify the 'kexec_execute' data hash: > > sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements > | grep kexec_execute | cut -d' ' -f 6 | xxd -r -p | sha256sum > > Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com> ^^^^^ > Signed-off-by: Steven Chen <chenste@linux.microsoft.com> ^^^^^ > Reviewed-by: Mimi Zohar <zohar@linux.ibm.com> > --- > security/integrity/ima/ima.h | 6 ++++++ > security/integrity/ima/ima_kexec.c | 21 +++++++++++++++++++++ > security/integrity/ima/ima_queue.c | 5 +++++ > 3 files changed, 32 insertions(+) Acked-by: Baoquan He <bhe@redhat.com> > > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h > index 24d09ea91b87..34815baf5e21 100644 > --- a/security/integrity/ima/ima.h > +++ b/security/integrity/ima/ima.h > @@ -240,6 +240,12 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, > unsigned long flags, bool create); > #endif > > +#ifdef CONFIG_IMA_KEXEC > +void ima_measure_kexec_event(const char *event_name); > +#else > +static inline void ima_measure_kexec_event(const char *event_name) {} > +#endif > + > /* > * The default binary_runtime_measurements list format is defined as the > * platform native format. The canonical format is defined as little-endian. > diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c > index d1c9d369ba08..38cb2500f4c3 100644 > --- a/security/integrity/ima/ima_kexec.c > +++ b/security/integrity/ima/ima_kexec.c > @@ -17,6 +17,8 @@ > #include "ima.h" > > #ifdef CONFIG_IMA_KEXEC > +#define IMA_KEXEC_EVENT_LEN 256 > + > static bool ima_kexec_update_registered; > static struct seq_file ima_kexec_file; > static size_t kexec_segment_size; > @@ -31,6 +33,24 @@ static void ima_free_kexec_file_buf(struct seq_file *sf) > sf->count = 0; > } > > +void ima_measure_kexec_event(const char *event_name) > +{ > + char ima_kexec_event[IMA_KEXEC_EVENT_LEN]; > + size_t buf_size = 0; > + long len; > + int n; > + > + buf_size = ima_get_binary_runtime_size(); > + len = atomic_long_read(&ima_htable.len); > + > + n = scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN, > + "kexec_segment_size=%lu;ima_binary_runtime_size=%lu;" > + "ima_runtime_measurements_count=%ld;", > + kexec_segment_size, buf_size, len); > + > + ima_measure_critical_data("ima_kexec", event_name, ima_kexec_event, n, false, NULL, 0); > +} > + > static int ima_alloc_kexec_file_buf(size_t segment_size) > { > /* > @@ -53,6 +73,7 @@ static int ima_alloc_kexec_file_buf(size_t segment_size) > out: > ima_kexec_file.read_pos = 0; > ima_kexec_file.count = sizeof(struct ima_kexec_hdr); /* reserved space */ > + ima_measure_kexec_event("kexec_load"); > > return 0; > } > diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c > index 83d53824aa98..590637e81ad1 100644 > --- a/security/integrity/ima/ima_queue.c > +++ b/security/integrity/ima/ima_queue.c > @@ -241,6 +241,11 @@ static int ima_reboot_notifier(struct notifier_block *nb, > unsigned long action, > void *data) > { > +#ifdef CONFIG_IMA_KEXEC > + if (action == SYS_RESTART && data && !strcmp(data, "kexec reboot")) > + ima_measure_kexec_event("kexec_execute"); > +#endif > + > ima_measurements_suspend(); > > return NOTIFY_DONE; > -- > 2.43.0 >
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 24d09ea91b87..34815baf5e21 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -240,6 +240,12 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, unsigned long flags, bool create); #endif +#ifdef CONFIG_IMA_KEXEC +void ima_measure_kexec_event(const char *event_name); +#else +static inline void ima_measure_kexec_event(const char *event_name) {} +#endif + /* * The default binary_runtime_measurements list format is defined as the * platform native format. The canonical format is defined as little-endian. diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index d1c9d369ba08..38cb2500f4c3 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -17,6 +17,8 @@ #include "ima.h" #ifdef CONFIG_IMA_KEXEC +#define IMA_KEXEC_EVENT_LEN 256 + static bool ima_kexec_update_registered; static struct seq_file ima_kexec_file; static size_t kexec_segment_size; @@ -31,6 +33,24 @@ static void ima_free_kexec_file_buf(struct seq_file *sf) sf->count = 0; } +void ima_measure_kexec_event(const char *event_name) +{ + char ima_kexec_event[IMA_KEXEC_EVENT_LEN]; + size_t buf_size = 0; + long len; + int n; + + buf_size = ima_get_binary_runtime_size(); + len = atomic_long_read(&ima_htable.len); + + n = scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN, + "kexec_segment_size=%lu;ima_binary_runtime_size=%lu;" + "ima_runtime_measurements_count=%ld;", + kexec_segment_size, buf_size, len); + + ima_measure_critical_data("ima_kexec", event_name, ima_kexec_event, n, false, NULL, 0); +} + static int ima_alloc_kexec_file_buf(size_t segment_size) { /* @@ -53,6 +73,7 @@ static int ima_alloc_kexec_file_buf(size_t segment_size) out: ima_kexec_file.read_pos = 0; ima_kexec_file.count = sizeof(struct ima_kexec_hdr); /* reserved space */ + ima_measure_kexec_event("kexec_load"); return 0; } diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 83d53824aa98..590637e81ad1 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -241,6 +241,11 @@ static int ima_reboot_notifier(struct notifier_block *nb, unsigned long action, void *data) { +#ifdef CONFIG_IMA_KEXEC + if (action == SYS_RESTART && data && !strcmp(data, "kexec reboot")) + ima_measure_kexec_event("kexec_execute"); +#endif + ima_measurements_suspend(); return NOTIFY_DONE;