ima: measure events between kexec load and execute
Subsystems (7)
cover ima: measure events between kexec load and execute
The current Kernel behavior is IMA measurements snapshot is taken at kexec 'load' and not at kexec 'execute'. IMA log is then carried over to the new Kernel after kexec 'execute'.
Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.
This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.
The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',
- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',
- ima functionality for mapping the measurement list from the current Kernel to the subsequent one,
- necessary changes to the kexec_file_load syscall, enabling it to call the ima functions
- registering a reboot notifier which gets called during kexec 'execute',
- and removal of deprecated functions.
The modifications proposed in this series ensure the integrity of the ima measurements is preserved across kexec soft reboots, thus significantly improving the security of the Kernel post kexec soft reboots.
There were previous attempts to fix this issue [1], [2], [3]. But they were not merged into the mainline Kernel.
We took inspiration from the past work [1] and [2] while working on this patch series.
References:
-----------
[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/
[2] PATCH v2 4/6] kexec_file: Add mechanism to update kexec segments.
https://lkml.org/lkml/2016/8/16/577
[3] [PATCH 1/6] kexec_file: Add buffer hand-over support
https://lore.kernel.org/linuxppc-dev/[email protected]/T/
Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove function ima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: update kexec_file_load syscall to call ima_kexec_post_load
include/linux/ima.h | 3 + include/linux/kexec.h | 13 ++ kernel/kexec_core.c | 72 +++++++++- kernel/kexec_file.c | 7 + kernel/kexec_internal.h | 1 + security/integrity/ima/ima.h | 4 + security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------ security/integrity/ima/ima_queue.c | 32 +++++ 8 files changed, 295 insertions(+), 48 deletions(-)
Signature · 1 line
2.25.1
PATCH 1/10 ima: implement function to allocate buffer at kexec load
IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation. The function should handle the scenario where the kexec load is called multiple times.
Implement a function to allocate buffer of size kexec_segment_size at kexec load. If the buffer was already allocated, free that buffer and reallocate. Finally, initialize ima_khdr struct.
The patch operates under the assumption that the segment size does not change between kexec load and execute.
--- security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
security/integrity/ima/ima_kexec.c +47 -0
@@ -15,6 +15,53 @@#include "ima.h" #ifdef CONFIG_IMA_KEXEC +struct seq_file ima_kexec_file; +struct ima_kexec_hdr ima_khdr; +static size_t kexec_segment_size; + +void ima_clear_kexec_file (void ) +{ +vfree (ima_kexec_file.buf); + ima_kexec_file.buf =NULL ; + ima_kexec_file.size =0 ; + ima_kexec_file.read_pos =0 ; + ima_kexec_file.count =0 ; +} + +static int ima_allocate_buf_at_kexec_load (void ) +{ +if ((kexec_segment_size ==0 ) || + (kexec_segment_size ==ULONG_MAX ) || + ((kexec_segment_size >>PAGE_SHIFT ) >totalram_pages () /2 )) { +pr_err ("%s: Invalid segment size for kexec: %zu\n" , + __func__, kexec_segment_size); +return -EINVAL ; + } + +/* if kexec load was called before, clear the existing buffer +* before allocating a new one +*/ +if (ima_kexec_file.buf) +ima_clear_kexec_file (); + +/* segment size can't change between kexec load and execute */ + ima_kexec_file.buf =vmalloc (kexec_segment_size); +if (!ima_kexec_file.buf) { +pr_err ("%s: No memory for ima kexec measurement buffer\n" , + __func__); +return -ENOMEM ; + } + + ima_kexec_file.size = kexec_segment_size; + ima_kexec_file.read_pos =0 ; + ima_kexec_file.count =sizeof (ima_khdr);/* reserved space */ + +memset (&ima_khdr,0 ,sizeof (ima_khdr)); + ima_khdr.version =1 ; + +return 0 ; +} +static int ima_dump_measurement_list (unsigned long *buffer_size,void **buffer,unsigned long segment_size) {
Signature · 1 line
2.25.1
Mimi Zohar
maintainerRe: [PATCH 01/10] ima: implement function to allocate buffer at kexec load
Hi Tushar,
Quoted 2 lines · Tushar Sugandhi
IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation.
The IMA measurement list is currently being carried across kexec, so obviously a buffer is being allocated for it. IMA not allocating memory for the measurment list is not the problem statement. Please concisely provide the problem statement, explaining why IMA needs to allocate the buffer.
Quoted 2 lines
The function should handle the scenario where
the kexec load is called multiple times.
Currently the buffer is being freed with the kexec 'unload'. With this patch IMA is allocating a buffer for the measurement list, which needs to be freed independently of the kexec 'unload'.
Quoted 8 lines
Implement a function to allocate buffer of size
kexec_segment_sizeat kexec load. If the buffer was already allocated, free that buffer and reallocate. Finally, initialihzeima_khdrstruct.The patch operates under the assumption that the segment size does not change between kexec load and execute.
Signed-off-by Tushar Sugandhi <[email protected]>
Signature · 12 lines
thanks, Mimib _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 01/10] ima: implement function to allocate buffer at kexec load
Adding Eric to cc.
Quoted 11 lines · Mimi Zohar
Hi Tushar,
Quoted 2 lines · Tushar Sugandhi
IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation.
The IMA measurement list is currently being carried across kexec, so obviously a buffer is being allocated for it. IMA not allocating memory for the measurment list is not the problem statement. Please concisely provide the problem statement, explaining why IMA needs to allocate the buffer.
I meant IMA does not provide separate functions to allocate buffer and populate measurements. Both operations are wrapped in an atomic ima_dump_measurement_list().
As I mentioned in the comment in the cover letter, if there is no such technical limitation to allocate the buffer and copy the measurements at kexec ‘execute’ – I will make the necessary code changes and update the above line in the patch description accordingly.
Quoted 5 lines
Quoted 2 lines
The function should handle the scenario where
the kexec load is called multiple times.Currently the buffer is being freed with the kexec 'unload'. With this patch IMA is allocating a buffer for the measurement list, which needs to be freed independently of the kexec 'unload'.
If we end up allocating the buffer at kexec ‘execute’ (which results in soft boot to next Kernel) – is it technically possible that kexec ‘unload’ being called after calling kexec ‘execute’?
If not, should I still free the buffer at kexec ‘unload’ in this scenario?
~Tushar
Quoted 8 lines
Quoted 8 lines
Implement a function to allocate buffer of size
kexec_segment_sizeat kexec load. If the buffer was already allocated, free that buffer and reallocate. Finally, initialihzeima_khdrstruct.The patch operates under the assumption that the segment size does not change between kexec load and execute.
Signed-off-by Tushar Sugandhi <[email protected]>
Mimi Zohar
maintainerRe: [PATCH 01/10] ima: implement function to allocate buffer at kexec load
Quoted 14 lines · Tushar Sugandhi
Adding Eric to cc.
Quoted 11 lines · Mimi Zohar
Hi Tushar,
Quoted 2 lines · Tushar Sugandhi
IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation.
The IMA measurement list is currently being carried across kexec, so obviously a buffer is being allocated for it. IMA not allocating memory for the measurment list is not the problem statement. Please concisely provide the problem statement, explaining why IMA needs to allocate the buffer.
Quoted 3 lines
I meant IMA does not provide separate functions to allocate buffer and populate measurements. Both operations are wrapped in an atomic
ima_dump_measurement_list().
Ok.
Quoted 4 lines
As I mentioned in the comment in the cover letter, if there is no such technical limitation to allocate the buffer and copy the measurements at kexec ‘execute’ – I will make the necessary code changes and update the above line in the patch description accordingly.
The "normal" way of making this type of change would be to split the existing ima_dump_measurement_list() function. Copying the measurement list would still be named ima_dump_measurement_list(). The other could be named ima_alloc_kexec_buf(). Both functions initially would be called.
Eric, besides updating the buffer at kexec execute, is there anything else that needs to be done (e.g. updating digests)?
Quoted 6 lines
Quoted 5 lines
Quoted 2 lines
The function should handle the scenario where
the kexec load is called multiple times.Currently the buffer is being freed with the kexec 'unload'. With this patch IMA is allocating a buffer for the measurement list, which needs to be freed independently of the kexec 'unload'.
Quoted 6 lines
If we end up allocating the buffer at kexec ‘execute’ (which results in soft boot to next Kernel) – is it technically possible that kexec ‘unload’ being called after calling kexec ‘execute’?
If not, should I still free the buffer at kexec ‘unload’ in this scenario?
The question is how to access the buffer once kexec_add_buffer() is called.
Mimi
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 01/10] ima: implement function to allocate buffer at kexec load
Quoted 24 lines · Mimi Zohar
Quoted 14 lines · Tushar Sugandhi
Adding Eric to cc.
Quoted 11 lines · Mimi Zohar
Hi Tushar,
Quoted 2 lines · Tushar Sugandhi
IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation.
The IMA measurement list is currently being carried across kexec, so obviously a buffer is being allocated for it. IMA not allocating memory for the measurment list is not the problem statement. Please concisely provide the problem statement, explaining why IMA needs to allocate the buffer.
Quoted 3 lines
I meant IMA does not provide separate functions to allocate buffer and populate measurements. Both operations are wrapped in an atomic
ima_dump_measurement_list().Ok.
Quoted 4 lines
As I mentioned in the comment in the cover letter, if there is no such technical limitation to allocate the buffer and copy the measurements at kexec ‘execute’ – I will make the necessary code changes and update the above line in the patch description accordingly.
Quoted 6 lines
The "normal" way of making this type of change would be to split the existing
ima_dump_measurement_list()function. Copying the measurement list would still be namedima_dump_measurement_list(). The other could be namedima_alloc_kexec_buf(). Both functions initially would be called.
Sounds good. I will make that change.
I will define ima_alloc_kexec_buf() to allocate memory at kexec 'load'. And update ima_dump_measurement_list() to only copy the measurements.
Both the functions will be called during kexec 'load'.
And only the updated ima_dump_measurement_list() will be called during kexec 'execute'.
Please correct me if I misunderstood.
BTW, as discussed elsewhere I am hoping to get clarity on if we can move everything (memory allocation and copying measurements) to kexec 'execute'.
My current understanding is segment mapping must happen at kexec 'load'. Hopefully someone on this thread can validate if its true or not.
Quoted 3 lines
Eric, besides updating the buffer at kexec execute, is there anything else that needs to be done (e.g. updating digests)?
I will also wait for his response. :)
Quoted 14 lines
Quoted 10 lines
Quoted 5 lines
Quoted 2 lines
The function should handle the scenario where
the kexec load is called multiple times.Currently the buffer is being freed with the kexec 'unload'. With this patch IMA is allocating a buffer for the measurement list, which needs to be freed independently of the kexec 'unload'.
If we end up allocating the buffer at kexec ‘execute’ (which results in soft boot to next Kernel) – is it technically possible that kexec ‘unload’ being called after calling kexec ‘execute’? If not, should I still free the buffer at kexec ‘unload’ in this scenario?
The question is how to access the buffer once
kexec_add_buffer()is called.Mimi
PATCH 2/10 ima: implement function to populate buffer at kexec execute
In reply to Tushar SugandhiThere is no existing IMA functionality to just populate the buffer at kexec execute with IMA measurements.
Implement a function to iterate over ima_measurements and populate the ima_kexec_file buffer. After the loop, populate ima_khdr with buffer details (version, buffer size, number of measurements). Copy the ima_khdr data into ima_kexec_file.buf and update buffer_size and buffer.
The patch assumes that the ima_kexec_file.size is sufficient to hold all the measurements. It returns an error and does not handle scenarios where additional space might be needed.
--- security/integrity/ima/ima_kexec.c | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
security/integrity/ima/ima_kexec.c +52 -0
@@ -62,6 +62,58 @@ static int ima_allocate_buf_at_kexec_load(void)return 0 ; } +static int ima_populate_buf_at_kexec_execute (unsigned long *buffer_size,void **buffer) +{ +struct ima_queue_entry *qe; +int ret =0 ; + +/* +* Ensure the kexec buffer is large enough to hold ima_khdr +*/ +if (ima_kexec_file.size <sizeof (ima_khdr)) { +pr_err ("%s: Kexec buffer size too low to hold ima_khdr\n" , + __func__); +ima_clear_kexec_file (); +return -ENOMEM ; + } + +list_for_each_entry_rcu (qe, &ima_measurements, later) { +if (ima_kexec_file.count < ima_kexec_file.size) { + ima_khdr.count++; +ima_measurements_show (&ima_kexec_file, qe); + }else { + ret = -ENOMEM ; +pr_err ("%s: Kexec ima_measurements buffer too small\n" , + __func__); +break ; + } + } +if (ret <0 ) + goto out; + +/* +* fill in reserved space with some buffer details +* (eg. version, buffer size, number of measurements) +*/ + ima_khdr.buffer_size = ima_kexec_file.count; +if (ima_canonical_fmt) { + ima_khdr.version =cpu_to_le16 (ima_khdr.version); + ima_khdr.count =cpu_to_le64 (ima_khdr.count); + ima_khdr.buffer_size =cpu_to_le64 (ima_khdr.buffer_size); + } + +memcpy (ima_kexec_file.buf, &ima_khdr,sizeof (ima_khdr)); + *buffer_size = ima_kexec_file.count; + *buffer = ima_kexec_file.buf; + +out: +if (ret <0 ) +ima_clear_kexec_file (); + +return ret; +} + +static int ima_dump_measurement_list (unsigned long *buffer_size,void **buffer,unsigned long segment_size) {
Signature · 1 line
2.25.1
Mimi Zohar
maintainerRe: [PATCH 02/10] ima: implement function to populate buffer at kexec execute
Hi Tushar,
Quoted 2 lines · Tushar Sugandhi
There is no existing IMA functionality to just populate the buffer at kexec execute with IMA measurements.
The same function that copies the measurement list at kexec 'load',
could be re-used at kexec 'exec'. Why is a new function that is very
similar to the existing ima_dump_measurement_list() needed?
Quoted 79 lines
Implement a function to iterate over
ima_measurementsand populate theima_kexec_filebuffer. After the loop, populateima_khdrwith buffer details (version, buffer size, number of measurements). Copy theima_khdrdata into ima_kexec_file.buf and updatebuffer_sizeand buffer.The patch assumes that the ima_kexec_file.size is sufficient to hold all the measurements. It returns an error and does not handle scenarios where additional space might be needed.
Signed-off-by Tushar Sugandhi <[email protected]>--- security/integrity/ima/ima_kexec.c | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)security/integrity/ima/ima_kexec.c +51
-0@@ -62,6 +62,58 @@ static int ima_allocate_buf_at_kexec_load(void)return 0 ; } +static int ima_populate_buf_at_kexec_execute (unsigned long *buffer_size,void **buffer) +{ +struct ima_queue_entry *qe; +int ret =0 ; + +/* +* Ensure the kexec buffer is large enough to hold ima_khdr +*/ +if (ima_kexec_file.size <sizeof (ima_khdr)) { +pr_err ("%s: Kexec buffer size too low to hold ima_khdr\n" , + __func__); +ima_clear_kexec_file (); +return -ENOMEM ; + } + +list_for_each_entry_rcu (qe, &ima_measurements, later) { +if (ima_kexec_file.count < ima_kexec_file.size) { + ima_khdr.count++; +ima_measurements_show (&ima_kexec_file, qe); + }else { + ret = -ENOMEM ; +pr_err ("%s: Kexec ima_measurements buffer too small\n" , + __func__); +break ; + } + } +if (ret <0 ) + goto out; + +/* +* fill in reserved space with some buffer details +* (eg. version, buffer size, number of measurements) +*/ + ima_khdr.buffer_size = ima_kexec_file.count; +if (ima_canonical_fmt) { + ima_khdr.version =cpu_to_le16 (ima_khdr.version); + ima_khdr.count =cpu_to_le64 (ima_khdr.count); + ima_khdr.buffer_size =cpu_to_le64 (ima_khdr.buffer_size); + } + +memcpy (ima_kexec_file.buf, &ima_khdr,sizeof (ima_khdr)); + *buffer_size = ima_kexec_file.count; + *buffer = ima_kexec_file.buf; + +out: +if (ret <0 ) +ima_clear_kexec_file (); + +return ret; +} +b+
static int ima_dump_measurement_list(unsigned long*buffer_size, void **buffer,
unsigned longsegment_size)
{
Signature · 9 lines
thanks, Mimi _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 02/10] ima: implement function to populate buffer at kexec execute
Adding Eric to cc.
Quoted 8 lines · Mimi Zohar
Hi Tushar,
Quoted 2 lines · Tushar Sugandhi
There is no existing IMA functionality to just populate the buffer at kexec execute with IMA measurements.
The same function that copies the measurement list at kexec 'load',
could be re-used at kexec 'exec'. Why is a new function that is very
similar to the existingima_dump_measurement_list()needed?
The current implementation of ima_dump_measurement_list() does both -
(1) allocation of buffer and (2) copying the measurements at kexec ‘load’.
The goal is to copy the measurements at kexec ‘execute’.
As I mentioned earlier, my understanding is the buffer must be allocated at kexec ‘load’ time. And the segment size cannot change between kexec ‘load’ and kexec ‘execute’.
That’s why I believe the two new functions are needed. So I split the functionality in ima_dump_measurement_list() into two functions –
(1) ima_allocate_buf_at_kexec_load() in patch 01/10 and
(2) ima_populate_buf_at_kexec_execute() in patch 02/10
and then deprecated ima_dump_measurement_list() in patch 7/10.
If I call ima_dump_measurement_list() both at kexec ‘load’ as well as kexec ‘execute’, it will result in double memory allocation.
As you said, if the functionality can be achieved by simply moving ima_dump_measurement_list() from kexec ‘load’ to kexec ‘execute’ – then you are right, we don’t need the two separate functions.
~Tushar
Quoted 79 lines
Quoted 79 lines
Implement a function to iterate over
ima_measurementsand populate theima_kexec_filebuffer. After the loop, populateima_khdrwith buffer details (version, buffer size, number of measurements). Copy theima_khdrdata into ima_kexec_file.buf and updatebuffer_sizeand buffer.The patch assumes that the ima_kexec_file.size is sufficient to hold all the measurements. It returns an error and does not handle scenarios where additional space might be needed.
Signed-off-by Tushar Sugandhi <[email protected]>--- security/integrity/ima/ima_kexec.c | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)security/integrity/ima/ima_kexec.c +51
-0@@ -62,6 +62,58 @@ static int ima_allocate_buf_at_kexec_load(void)return 0 ; } +static int ima_populate_buf_at_kexec_execute (unsigned long *buffer_size,void **buffer) +{ +struct ima_queue_entry *qe; +int ret =0 ; + +/* +* Ensure the kexec buffer is large enough to hold ima_khdr +*/ +if (ima_kexec_file.size <sizeof (ima_khdr)) { +pr_err ("%s: Kexec buffer size too low to hold ima_khdr\n" , + __func__); +ima_clear_kexec_file (); +return -ENOMEM ; + } + +list_for_each_entry_rcu (qe, &ima_measurements, later) { +if (ima_kexec_file.count < ima_kexec_file.size) { + ima_khdr.count++; +ima_measurements_show (&ima_kexec_file, qe); + }else { + ret = -ENOMEM ; +pr_err ("%s: Kexec ima_measurements buffer too small\n" , + __func__); +break ; + } + } +if (ret <0 ) + goto out; + +/* +* fill in reserved space with some buffer details +* (eg. version, buffer size, number of measurements) +*/ + ima_khdr.buffer_size = ima_kexec_file.count; +if (ima_canonical_fmt) { + ima_khdr.version =cpu_to_le16 (ima_khdr.version); + ima_khdr.count =cpu_to_le64 (ima_khdr.count); + ima_khdr.buffer_size =cpu_to_le64 (ima_khdr.buffer_size); + } + +memcpy (ima_kexec_file.buf, &ima_khdr,sizeof (ima_khdr)); + *buffer_size = ima_kexec_file.count; + *buffer = ima_kexec_file.buf; + +out: +if (ret <0 ) +ima_clear_kexec_file (); + +return ret; +} +b+
static int ima_dump_measurement_list(unsigned long*buffer_size, void **buffer,
unsigned longsegment_size)
{
PATCH 3/10 ima: allocate buffer at kexec load to hold ima measurements
In reply to Tushar SugandhiThe IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.
Update ima_add_kexec_buffer to allocate a buffer of a sufficient size taking ima binary runtime measurements size, size of ima_kexec_hdr, and IMA_KEXEC_EXTRA_SIZE into account. Adjust the kexec_segment_size to align to the PAGE_SIZE. Call ima_allocate_buf_at_kexec_load() to allocate the buffer.
This patch assumes the extra space defined (IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.
--- security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_kexec.c | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-)
security/integrity/ima/ima.h +2 -0
@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };#define NR_BANKS (chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) +#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE) +/* current content of the policy */ extern int ima_policy_flag;
security/integrity/ima/ima_kexec.c +10 -11
@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)/* use more understandable variable names than defined in kbuf */ void *kexec_buffer =NULL ;size_t kexec_buffer_size; -size_t kexec_segment_size;int ret;/* -* Reserve an extra half page of memory for additional measurements -* added during the kexec load. +* Reserve extra memory for measurements added in the window from +* kexec 'load' to kexec 'execute'. */ - binary_runtime_size =ima_get_binary_runtime_size (); + binary_runtime_size =ima_get_binary_runtime_size () + +sizeof (struct ima_kexec_hdr ) + +IMA_KEXEC_EXTRA_SIZE ; +if (binary_runtime_size >=ULONG_MAX -PAGE_SIZE ) kexec_segment_size =ULONG_MAX ;else - kexec_segment_size =ALIGN (ima_get_binary_runtime_size () + -PAGE_SIZE /2 ,PAGE_SIZE ); + kexec_segment_size =ALIGN (binary_runtime_size,PAGE_SIZE ); +if ((kexec_segment_size ==ULONG_MAX ) || ((kexec_segment_size >>PAGE_SHIFT ) >totalram_pages () /2 )) {pr_err ("Binary measurement list too large.\n" );return ; } -ima_dump_measurement_list (&kexec_buffer_size, &kexec_buffer, - kexec_segment_size); -if (!kexec_buffer) { -pr_err ("Not enough memory for the kexec measurement buffer.\n" ); + ret =ima_allocate_buf_at_kexec_load (); +if (ret <0 )return ; - } kbuf.buffer = kexec_buffer; kbuf.bufsz = kexec_buffer_size;
Signature · 1 line
2.25.1
Mimi Zohar
maintainerRe: [PATCH 03/10] ima: allocate buffer at kexec load to hold ima measurements
Hi Tushar,
The function to "ima: allocate buffer at kexec load to hold ima measurements" already exists. Please update the Subject line to indicate increasing the IMA kexec buffer size.
Quoted 2 lines · Tushar Sugandhi
The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.
What is a "dedicated mechanism?". Either start the sentence with "reserve ..." or completely remove it.
Quoted 5 lines
Update
ima_add_kexec_bufferto allocate a buffer of a sufficient size taking ima binary runtime measurements size, size ofima_kexec_hdr, andIMA_KEXEC_EXTRA_SIZEinto account. Adjust thekexec_segment_sizeto align to thePAGE_SIZE. Callima_allocate_buf_at_kexec_load()to allocate the buffer.
The size of the ima_kexec_hdr kind of gets lost in the amount of additional memory being allocated, but sure it's a nice clean up.
Quoted 4 lines
This patch assumes the extra space defined (
IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.
Should the extra amount of memory be hard coded?
Quoted 11 lines
Signed-off-by Tushar Sugandhi <[email protected]>--- security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_kexec.c | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-)security/integrity/ima/ima.h +0
-0
security/integrity/ima/ima.h enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; · line 47
Quoted 5 lines
security/integrity/ima/ima.h +1
-0@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };#define NR_BANKS (chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) +#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE)
Not all IMA policies require extra memory. Define and use a new IMA Kconfig to set the amount of extra memory.
Quoted 30 lines
security/integrity/ima/ima.h +0
-0/* current content of the policy */ extern int ima_policy_flag;security/integrity/ima/ima_kexec.c +6
-6@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)/* use more understandable variable names than defined in kbuf */ void *kexec_buffer =NULL ;size_t kexec_buffer_size; -size_t kexec_segment_size;int ret;/* -* Reserve an extra half page of memory for additional measurements -* added during the kexec load. +* Reserve extra memory for measurements added in the window from +* kexec 'load' to kexec 'execute'. */ - binary_runtime_size =ima_get_binary_runtime_size (); + binary_runtime_size =ima_get_binary_runtime_size () + +sizeof (struct ima_kexec_hdr ) + +IMA_KEXEC_EXTRA_SIZE ; +if (binary_runtime_size >=ULONG_MAX -PAGE_SIZE ) kexec_segment_size =ULONG_MAX ;else - kexec_segment_size =ALIGN (ima_get_binary_runtime_size () + -PAGE_SIZE /2 ,PAGE_SIZE );
security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 211
Quoted 10 lines
security/integrity/ima/ima_kexec.c +2
-2+ kexec_segment_size =ALIGN (binary_runtime_size,PAGE_SIZE ); +if ((kexec_segment_size ==ULONG_MAX ) || ((kexec_segment_size >>PAGE_SHIFT ) >totalram_pages () /2 )) {pr_err ("Binary measurement list too large.\n" );return ; } -ima_dump_measurement_list (&kexec_buffer_size, &kexec_buffer, - kexec_segment_size);
Removing the call to ima_dump_measurement_list here is not bisect safe.
Quoted 9 lines
security/integrity/ima/ima_kexec.c +2
-3-if (!kexec_buffer) { -pr_err ("Not enough memory for the kexec measurement buffer.\n" ); + ret =ima_allocate_buf_at_kexec_load (); +if (ret <0 )return ; - } kbuf.buffer = kexec_buffer; kbuf.bufsz = kexec_buffer_size;
Signature · 9 lines
thanks, Mimi _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 03/10] ima: allocate buffer at kexec load to hold ima measurements
Adding Eric to cc.
Quoted 6 lines · Mimi Zohar
Hi Tushar,
The function to "ima: allocate buffer at kexec load to hold ima measurements" already exists. Please update the Subject line to indicate increasing the IMA kexec buffer size.
Quoted 6 lines
Quoted 2 lines · Tushar Sugandhi
The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.
What is a "dedicated mechanism?". Either start the sentence with "reserve ..." or completely remove it.
Will do.
Quoted 7 lines
Quoted 5 lines
Update
ima_add_kexec_bufferto allocate a buffer of a sufficient size taking ima binary runtime measurements size, size ofima_kexec_hdr, andIMA_KEXEC_EXTRA_SIZEinto account. Adjust thekexec_segment_sizeto align to thePAGE_SIZE. Callima_allocate_buf_at_kexec_load()to allocate the buffer.The size of the
ima_kexec_hdrkind of gets lost in the amount of additional memory being allocated, but sure it's a nice clean up.
Thanks. :)
Quoted 6 lines
Quoted 4 lines
This patch assumes the extra space defined (
IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.Should the extra amount of memory be hard coded?
You are right. As you suggested below, defining the extra amount in Kconfig is a cleaner approach.
Quoted 12 lines
Quoted 12 lines
Signed-off-by Tushar Sugandhi <[email protected]>--- security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_kexec.c | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-)security/integrity/ima/ima.h +0
-0@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
Quoted 6 lines
security/integrity/ima/ima.h enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; · line 50
Quoted 4 lines
security/integrity/ima/ima.h +1
-0#define NR_BANKS (chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) +#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE)Not all IMA policies require extra memory. Define and use a new IMA
Kconfigto set the amount of extra memory.
Sure. Will do.
Quoted 38 lines
Quoted 38 lines
security/integrity/ima/ima.h +0
-0/* current content of the policy */ extern int ima_policy_flag;security/integrity/ima/ima_kexec.c +8
-6@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)/* use more understandable variable names than defined in kbuf */ void *kexec_buffer =NULL ;size_t kexec_buffer_size; -size_t kexec_segment_size;int ret;/* -* Reserve an extra half page of memory for additional measurements -* added during the kexec load. +* Reserve extra memory for measurements added in the window from +* kexec 'load' to kexec 'execute'. */ - binary_runtime_size =ima_get_binary_runtime_size (); + binary_runtime_size =ima_get_binary_runtime_size () + +sizeof (struct ima_kexec_hdr ) + +IMA_KEXEC_EXTRA_SIZE ; +if (binary_runtime_size >=ULONG_MAX -PAGE_SIZE ) kexec_segment_size =ULONG_MAX ;else - kexec_segment_size =ALIGN (ima_get_binary_runtime_size () + -PAGE_SIZE /2 ,PAGE_SIZE ); + kexec_segment_size =ALIGN (binary_runtime_size,PAGE_SIZE ); +if ((kexec_segment_size ==ULONG_MAX ) || ((kexec_segment_size >>PAGE_SHIFT ) >totalram_pages () /2 )) {pr_err ("Binary measurement list too large.\n" );return ; }
Quoted 3 lines
security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 211
Quoted 2 lines
security/integrity/ima/ima_kexec.c +0
-2-ima_dump_measurement_list (&kexec_buffer_size, &kexec_buffer, - kexec_segment_size);Removing the call to
ima_dump_measurement_listhere is not bisect safe.
Agreed. Will take care of this based on if we end up using just ima_dump_measurement_list(), or combination of ima_allocate_buf_at_kexec_load() and ima_populate_buf_at_kexec_execute().
~Tushar
Quoted 9 lines
Quoted 9 lines
security/integrity/ima/ima_kexec.c +2
-3-if (!kexec_buffer) { -pr_err ("Not enough memory for the kexec measurement buffer.\n" ); + ret =ima_allocate_buf_at_kexec_load (); +if (ret <0 )return ; - } kbuf.buffer = kexec_buffer; kbuf.bufsz = kexec_buffer_size;
Re: [PATCH 03/10] ima: allocate buffer at kexec load to hold ima measurements
In reply to Tushar SugandhiQuoted 9 lines · Tushar Sugandhi
The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.
Update
ima_add_kexec_bufferto allocate a buffer of a sufficient size taking ima binary runtime measurements size, size ofima_kexec_hdr, andIMA_KEXEC_EXTRA_SIZEinto account. Adjust thekexec_segment_sizeto align to thePAGE_SIZE. Callima_allocate_buf_at_kexec_load()to allocate the buffer.
Quoted 4 lines
This patch assumes the extra space defined (
IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.
This could be the most problematic part if the 'execute' happens much later than the 'load' with lots of measurement activity in between. I am wondering whether not doing anything at 'load' time and doing the whole work at 'execute' time wouldn't be the right thing to do ?
Otherwise, if we wanted the work to be split as you suggest, could you
- krealloc the src_pages (now in kimage_map_segment) to add space for a few more pages needed for the additional measurements
- add those few more pages to src_pages
- vunmap the previous mapping
- vmap the extended src_pages array
- update ima_kexec_file.buf with the diff between the new and old vmap'ed addresses
- append to the existing log
This presumably would help resolve this potential issue.
The src_pages is currently not kfree'd -- may be a memory leak.
Regards,
Stefan
Quoted 56 lines
Signed-off-by Tushar Sugandhi <[email protected]>--- security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_kexec.c | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-)security/integrity/ima/ima.h +2
-0@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };#define NR_BANKS (chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) +#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE) +/* current content of the policy */ extern int ima_policy_flag;security/integrity/ima/ima_kexec.c +8
-7@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)/* use more understandable variable names than defined in kbuf */ void *kexec_buffer =NULL ;size_t kexec_buffer_size; -size_t kexec_segment_size;int ret;/* -* Reserve an extra half page of memory for additional measurements -* added during the kexec load. +* Reserve extra memory for measurements added in the window from +* kexec 'load' to kexec 'execute'. */ - binary_runtime_size =ima_get_binary_runtime_size (); + binary_runtime_size =ima_get_binary_runtime_size () + +sizeof (struct ima_kexec_hdr ) + +IMA_KEXEC_EXTRA_SIZE ; +if (binary_runtime_size >=ULONG_MAX -PAGE_SIZE ) kexec_segment_size =ULONG_MAX ;else - kexec_segment_size =ALIGN (ima_get_binary_runtime_size () + -PAGE_SIZE /2 ,PAGE_SIZE ); + kexec_segment_size =ALIGN (binary_runtime_size,PAGE_SIZE ); +if ((kexec_segment_size ==ULONG_MAX ) || ((kexec_segment_size >>PAGE_SHIFT ) >totalram_pages () /2 )) {pr_err ("Binary measurement list too large.\n" );return ; } - ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 217
Quoted 10 lines
security/integrity/ima/ima_kexec.c +2
-4- kexec_segment_size); -if (!kexec_buffer) { -pr_err ("Not enough memory for the kexec measurement buffer.\n" ); + ret =ima_allocate_buf_at_kexec_load (); +if (ret <0 )return ; - } kbuf.buffer = kexec_buffer; kbuf.bufsz = kexec_buffer_size;
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 03/10] ima: allocate buffer at kexec load to hold ima measurements
Quoted 12 lines · Stefan Berger
Quoted 9 lines · Tushar Sugandhi
The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.
Update
ima_add_kexec_bufferto allocate a buffer of a sufficient size taking ima binary runtime measurements size, size ofima_kexec_hdr, andIMA_KEXEC_EXTRA_SIZEinto account. Adjust thekexec_segment_sizeto align to the PAGE_SIZE. Callima_allocate_buf_at_kexec_load()to allocate the buffer.
Quoted 8 lines
Quoted 4 lines
This patch assumes the extra space defined (
IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.This could be the most problematic part if the 'execute' happens much later than the 'load' with lots of measurement activity in between. I am wondering whether not doing anything at 'load' time and doing the whole work at 'execute' time
Technically I don't want to do anything at kexec 'load' time.
But as I said elsewhere in this series, I am under impression that segment allocation must happen at kexec 'load' time.
But if that understanding is wrong - then we can move the entire logic to kexec 'execute' time.
I am currently trying to validate if moving the logic to kexec 'execute' works.
Quoted 12 lines
wouldn't be the right thing to do ?
Otherwise, if we wanted the work to be split as you suggest, could you
- krealloc thesrc_pages(now inkimage_map_segment) to add space for a few more pages needed for the additional measurements
- add those few more pages tosrc_pages
- vunmap the previous mapping
- vmap the extendedsrc_pagesarray
- update ima_kexec_file.buf with the diff between the new and old vmap'ed addresses
- append to the existing log
Quoted 1 line
This presumably would help resolve this potential issue.
Thanks for the detailed thoughts.
I will investigate if this approach is needed, based on my comment above. If it is needed and feasible, I will incorporate it in the next iteration.
Thanks again.
~Tushar
Quoted 68 lines
The
src_pagesis currently not kfree'd -- may be a memory leak.Regards,
StefanQuoted 62 lines
Signed-off-by Tushar Sugandhi <[email protected]>---
security/integrity/ima/ima.h | 2 ++security/integrity/ima/ima_kexec.c| 21 ++++++++++-----------2 files changed, 12 insertions(+), 11 deletions(-)security/integrity/ima/ima.h +1
-0@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) +#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE) + /* current content of the policy */ extern int ima_policy_flag;diff --git
a/security/integrity/ima/ima_kexec.cb/security/integrity/ima/ima_kexec.cindex858b67689701..7deb8df31485100644security/integrity/ima/ima_kexec.c +6
-4@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image) /* use more understandable variable names than defined in kbuf */ void *kexec_buffer = NULL; size_t kexec_buffer_size; - size_t kexec_segment_size; int ret; /* - * Reserve an extra half page of memory for additional measurements - * added during the kexec load. + * Reserve extra memory for measurements added in the window from + * kexec 'load' to kexec 'execute'. */ - binary_runtime_size = ima_get_binary_runtime_size(); + binary_runtime_size = ima_get_binary_runtime_size() + + sizeof(struct ima_kexec_hdr) + + IMA_KEXEC_EXTRA_SIZE; + if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE) kexec_segment_size = ULONG_MAX;else
-kexec_segment_size= ALIGN(ima_get_binary_runtime_size() + -PAGE_SIZE/ 2,PAGE_SIZE);
+kexec_segment_size=ALIGN(binary_runtime_size, PAGE_SIZE); +
if ((kexec_segment_size==ULONG_MAX) || ((kexec_segment_size>>PAGE_SHIFT) >totalram_pages()/ 2)) {pr_err("Binary measurement list too large.\n"); return;
}
-ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer, - kexec_segment_size);
- if (!kexec_buffer) {
-pr_err("Not enough memory for the kexec measurement buffer.\n");
+ ret =ima_allocate_buf_at_kexec_load();
+ if (ret < 0)
return;
- }
kbuf.buffer =kexec_buffer;
kbuf.bufsz =kexec_buffer_size;
PATCH 4/10 ima: implement functions to suspend and resume measurements
In reply to Tushar SugandhiThe IMA subsystem needs to provide a mechanism to suspend or resume measurements. This functionality is needed to temporarily halt the recording of IMA measurements during certain system operations.
Add functions ima_measurements_suspend() and ima_measurements_resume() functions to set and reset the suspend_ima_measurements variable, respectively, to suspend/resume IMA measurements. Use ima_extend_list_mutex to ensure that the operations are thread-safe.
Note: Use ima_measurements_suspend() and ima_measurements_resume() in pairs to avoid indefinitely suspending IMA measurements.
--- security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_queue.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+)
security/integrity/ima/ima.h +2 -0
@@ -163,6 +163,8 @@ bool ima_template_has_modsig(const struct ima_template_desc *ima_template);int ima_restore_measurement_entry (struct ima_template_entry *entry);int ima_restore_measurement_list (loff_t bufsize,void *buf);int ima_measurements_show (struct seq_file *m,void *v); +void ima_measurements_suspend (void ); +void ima_measurements_resume (void );unsigned long ima_get_binary_runtime_size (void );int ima_init_template (void );void ima_init_template_list (void );
security/integrity/ima/ima_queue.c +19 -0
@@ -44,6 +44,11 @@ struct ima_h_table ima_htable = {*/ static DEFINE_MUTEX (ima_extend_list_mutex); +/* +* Used internally by the kernel to suspend-resume ima measurements. +*/ +static atomic_t suspend_ima_measurements; +/* lookup up the digest value in the hash table, and return the entry */ static struct ima_queue_entry *ima_lookup_digest_entry (u8 *digest_value,int pcr)
@@ -148,6 +153,20 @@ static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr)return result; } +void ima_measurements_suspend (void ) +{ +mutex_lock (&ima_extend_list_mutex); +atomic_set (&suspend_ima_measurements,1 ); +mutex_unlock (&ima_extend_list_mutex); +} + +void ima_measurements_resume (void ) +{ +mutex_lock (&ima_extend_list_mutex); +atomic_set (&suspend_ima_measurements,0 ); +mutex_unlock (&ima_extend_list_mutex); +} +/* * Add template entry to the measurement list and hash table, and * extend the pcr.
Signature · 1 line
2.25.1
PATCH 5/10 kexec: implement functions to map and unmap segment to kimage
In reply to Tushar SugandhiCurrently, there's no mechanism to map and unmap segments to the kimage structure. This functionality is needed when dealing with memory segments in the context of a kexec operation.
The patch adds two new functions: kimage_map_segment() and kimage_unmap_segment().
Implement kimage_map_segment() which takes a kimage pointer, an address, and a size. Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses. If the mapping operation is successful, the function returns the start of this range. Otherwise, it frees the page pointer array and returns NULL.
Implement kimage_unmap_segment() that takes a pointer to a segment buffer and unmaps it using vunmap().
Finally, move for_each_kimage_entry() macro to kexec.h.
Note: Use kimage_map_segment() and kimage_unmap_segment() carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.
--- include/linux/kexec.h | 13 ++++++++ kernel/kexec_core.c | 72 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 5 deletions(-)
include/linux/kexec.h +13 -0
@@ -490,6 +490,15 @@ static inline int arch_kexec_post_alloc_pages(void *vaddr, unsigned int pages, gstatic inline void arch_kexec_pre_free_pages (void *vaddr,unsigned int pages) { }#endif +#define for_each_kimage_entry (image, ptr, entry) \ + for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ + ptr = (entry & IND_INDIRECTION) ? \ + boot_phys_to_virt((entry & PAGE_MASK)) : ptr + 1) + +extern void *kimage_map_segment (struct kimage *image, +unsigned long addr,unsigned long size); +extern void kimage_unmap_segment (void *buffer); +#else /* !CONFIG_KEXEC_CORE */ struct pt_regs ;struct task_struct ;
@@ -497,6 +506,10 @@ static inline void __crash_kexec(struct pt_regs *regs) { }static inline void crash_kexec (struct pt_regs *regs) { }static inline int kexec_should_crash (struct task_struct *p) {return 0 ; }static inline int kexec_crash_loaded (void ) {return 0 ; } +static inline void *kimage_map_segment (struct kimage *image, +unsigned long addr,unsigned long size) +{return NULL ; } +static inline void kimage_unmap_segment (void *buffer) { }#define kexec_in_progress false#endif /* CONFIG_KEXEC_CORE */
kernel/kexec_core.c +67 -5
84 lines not on this page · raw message
Signature · 1 line
2.25.1
Re: [PATCH 05/10] kexec: implement functions to map and unmap segment to kimage
Quoted 27 lines · Tushar Sugandhi
Currently, there's no mechanism to map and unmap segments to the kimage structure. This functionality is needed when dealing with memory segments in the context of a kexec operation.
The patch adds two new functions:
kimage_map_segment()andkimage_unmap_segment().Implement
kimage_map_segment()which takes a kimage pointer, an address, and a size. Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses. If the mapping operation is successful, the function returns the start of this range. Otherwise, it frees the page pointer array and returns NULL.Implement
kimage_unmap_segment()that takes a pointer to a segment buffer and unmaps it usingvunmap().Finally, move
for_each_kimage_entry()macro tokexec.h.Note: Use
kimage_map_segment()andkimage_unmap_segment()carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.Signed-off-by Tushar Sugandhi <[email protected]>
kernel/kexec_core.c int kimage_load_segment(struct kimage *image, · line 962
Quoted 9 lines
kernel/kexec_core.c +9
-0+ + i =0 ; +for_each_kimage_entry (image, ptr, entry) { +if (entry &IND_DESTINATION ) + dest_page_addr = entry &PAGE_MASK ; +else if (entry &IND_SOURCE ) { +if (dest_page_addr >= addr && dest_page_addr < eaddr) { + src_page_addr = entry &PAGE_MASK ; + src_pages[i++] =phys_to_page (src_page_addr);
Since phys_to_page is not defined on many/most architectures I change it for ppc64 and have successfully used the following:
+ src_pages[i++] = virt_to_page(__va(src_page_addr))
After several kexecs the following check still works:
# evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements Matched per TPM bank calculated digest(s).
Stefan
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 05/10] kexec: implement functions to map and unmap segment to kimage
Adding Eric to cc.
Quoted 46 lines · Stefan Berger
Quoted 27 lines · Tushar Sugandhi
Currently, there's no mechanism to map and unmap segments to the kimage structure. This functionality is needed when dealing with memory segments in the context of a kexec operation.
The patch adds two new functions:
kimage_map_segment()andkimage_unmap_segment().Implement
kimage_map_segment()which takes a kimage pointer, an address, and a size. Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses. If the mapping operation is successful, the function returns the start of this range. Otherwise, it frees the page pointer array and returns NULL.Implement
kimage_unmap_segment()that takes a pointer to a segment buffer and unmaps it usingvunmap().Finally, move
for_each_kimage_entry()macro tokexec.h.Note: Use
kimage_map_segment()andkimage_unmap_segment()carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.Signed-off-by Tushar Sugandhi <[email protected]>Quoted 9 lines
+
+ i = 0;
+for_each_kimage_entry(image, ptr, entry){
+ if (entry &IND_DESTINATION)
+dest_page_addr= entry &PAGE_MASK;
+ else if (entry &IND_SOURCE) {
+ if (dest_page_addr>= addr &&dest_page_addr< eaddr) { +src_page_addr= entry &PAGE_MASK;
+ src_pages[i++] =phys_to_page(src_page_addr);Since
phys_to_pageis not defined on many/most architectures I change it for ppc64 and have successfully used the following:+ src_pages[i++] =
virt_to_page(__va(src_page_addr))
Quoted 7 lines
After several kexecs the following check still works:
# evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements Matched per TPM bank calculated digest(s).Stefan
Thank you so much Stefan for reviewing this series, and catching this issue. Are you suggesting I should use virt_to_page on all architectures unconditionally, or use it only when phys_to_page is not available?
~Tushar
Re: [PATCH 05/10] kexec: implement functions to map and unmap segment to kimage
Quoted 50 lines · Tushar Sugandhi
Adding Eric to cc.
Quoted 47 lines · Stefan Berger
Quoted 27 lines · Tushar Sugandhi
Currently, there's no mechanism to map and unmap segments to the kimage structure. This functionality is needed when dealing with memory segments in the context of a kexec operation.
The patch adds two new functions:
kimage_map_segment()andkimage_unmap_segment().Implement
kimage_map_segment()which takes a kimage pointer, an address, and a size. Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses. If the mapping operation is successful, the function returns the start of this range. Otherwise, it frees the page pointer array and returns NULL.Implement
kimage_unmap_segment()that takes a pointer to a segment buffer and unmaps it usingvunmap().Finally, move
for_each_kimage_entry()macro tokexec.h.Note: Use
kimage_map_segment()andkimage_unmap_segment()carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.Signed-off-by Tushar Sugandhi <[email protected]>Quoted 9 lines
+
+ i = 0;
+for_each_kimage_entry(image, ptr, entry){
+ if (entry &IND_DESTINATION)
+dest_page_addr= entry &PAGE_MASK;
+ else if (entry &IND_SOURCE) {
+ if (dest_page_addr>= addr &&dest_page_addr< eaddr) { +src_page_addr= entry &PAGE_MASK;
+ src_pages[i++] =phys_to_page(src_page_addr);Since
phys_to_pageis not defined on many/most architectures I change it for ppc64 and have successfully used the following:+ src_pages[i++] = virt_to_page(__va(src_page_addr))
After several kexecs the following check still works:
Quoted 8 lines
Quoted 5 lines
# evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements Matched per TPM bank calculated digest(s).Stefan
Thank you so much Stefan for reviewing this series, and catching this issue. Are you suggesting I should use
virt_to_pageon all architectures unconditionally, or use it only whenphys_to_pageis not available?
I would try to used it on all architectures.
Stefan
Quoted 7 lines
~Tushar
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 05/10] kexec: implement functions to map and unmap segment to kimage
Quoted 58 lines · Stefan Berger
Quoted 55 lines · Tushar Sugandhi
Adding Eric to cc.
Quoted 52 lines · Stefan Berger
Quoted 27 lines · Tushar Sugandhi
Currently, there's no mechanism to map and unmap segments to the kimage structure. This functionality is needed when dealing with memory segments in the context of a kexec operation.
The patch adds two new functions:
kimage_map_segment()andkimage_unmap_segment().Implement
kimage_map_segment()which takes a kimage pointer, an address, and a size. Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses. If the mapping operation is successful, the function returns the start of this range. Otherwise, it frees the page pointer array and returns NULL.Implement
kimage_unmap_segment()that takes a pointer to a segment buffer and unmaps it usingvunmap().Finally, move
for_each_kimage_entry()macro tokexec.h.Note: Use
kimage_map_segment()andkimage_unmap_segment()carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.Signed-off-by Tushar Sugandhi <[email protected]>Quoted 9 lines
+
+ i = 0;
+for_each_kimage_entry(image, ptr, entry){
+ if (entry &IND_DESTINATION)
+dest_page_addr= entry &PAGE_MASK;
+ else if (entry &IND_SOURCE) {
+ if (dest_page_addr>= addr &&dest_page_addr< eaddr) { +src_page_addr= entry &PAGE_MASK;
+ src_pages[i++] =phys_to_page(src_page_addr);Since
phys_to_pageis not defined on many/most architectures I change it for ppc64 and have successfully used the following:+ src_pages[i++] =
virt_to_page(__va(src_page_addr))After several kexecs the following check still works:
# evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements Matched per TPM bank calculated digest(s).
Quoted 9 lines
Quoted 4 lines
Quoted 1 line
Stefan
Thank you so much Stefan for reviewing this series, and catching this issue. Are you suggesting I should use
virt_to_pageon all architectures unconditionally, or use it only whenphys_to_pageis not available?I would try to used it on all architectures.
Stefan
Ok. Thanks.
Quoted 7 lines
Quoted 7 lines
~Tushar
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
PATCH 6/10 ima: update buffer at kexec execute with ima measurements
In reply to Tushar SugandhiIn the current implementation, the measurement list is not updated in the buffer during the window between kexec load and execute. This leads to measurement loss in the buffer when transitioning from the old to the new kernel. This patch provides a way to update the measurement list in the buffer during a kexec execution. Suspending the measurements during the buffer update ensures the buffer doesn't get corrupted, or goes out of sync with TPM PCRs. Thus it ensures the integrity of measurements is maintained across kernel transitions during a kexec.
Introduce a new variable ima_kexec_buffer that is used to hold the address of the IMA kexec buffer.
Implement a function ima_update_kexec_buffer() that is called during kexec execute, allowing the IMA to update the measurement list with the events between kexec load and execute. First check if a kexec is in progress and if the IMA kexec buffer is initialized. If these conditions are met, suspend IMA measurements and check if the new buffer size obtained from ima_get_binary_runtime_size() is larger than the current buffer size. If the new buffer size is too large, output an error message, and resume the measurements.
If the new buffer size fits, populate the new buffer with the current measurements using ima_populate_buf_at_kexec_execute() and copy it into ima_kexec_buffer.
Unmap ima_kexec_buffer segment from the image. Resuming the measurements is not needed in case of successful measurements since the control is being passed to the new kernel anyways through kexec execute. However, the measurements should be resumed if there are any errors flagged in the function.
--- security/integrity/ima/ima_kexec.c | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
security/integrity/ima/ima_kexec.c +50 -0
@@ -18,6 +18,7 @@struct seq_file ima_kexec_file;struct ima_kexec_hdr ima_khdr;static size_t kexec_segment_size; +static void *ima_kexec_buffer;void ima_clear_kexec_file (void ) {
@@ -230,6 +231,55 @@ void ima_add_kexec_buffer(struct kimage *image)pr_debug ("kexec measurement buffer for the loaded kernel at 0x%lx.\n" , kbuf.mem); } + +/* +* Called during kexec execute so that IMA can update the measurement list. +*/ +static int ima_update_kexec_buffer (struct notifier_block *self, +unsigned long action,void *data) +{ +void *new_buffer =NULL ; +size_t new_buffer_size, cur_buffer_size; +bool resume = false; + +if (!kexec_in_progress) { +pr_info ("%s: No kexec in progress.\n" , __func__); +return NOTIFY_OK ; + } + +if (!ima_kexec_buffer) { +pr_err ("%s: Kexec buffer not set.\n" , __func__); +return NOTIFY_OK ; + } + +ima_measurements_suspend (); + + cur_buffer_size = kexec_segment_size -sizeof (struct ima_kexec_hdr ); + new_buffer_size =ima_get_binary_runtime_size (); +if (new_buffer_size > cur_buffer_size) { +pr_err ("%s: Measurement list grew too large.\n" , __func__); + resume = true; + goto out; + } + +ima_populate_buf_at_kexec_execute (&new_buffer_size, &new_buffer); + +if (!new_buffer) { +pr_err ("%s: Dump measurements failed.\n" , __func__); + resume = true; + goto out; + } +memcpy (ima_kexec_buffer, new_buffer, new_buffer_size); +out: +kimage_unmap_segment (ima_kexec_buffer); + ima_kexec_buffer =NULL ; + +if (resume) +ima_measurements_resume (); + +return NOTIFY_OK ; +} +#endif /* IMA_KEXEC */ /*
Signature · 1 line
2.25.1
Mimi Zohar
maintainerRe: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements
Hi Tushar,
Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19
-0+/* +* Called during kexec execute so that IMA can update the measurement list. +*/ +static int ima_update_kexec_buffer (struct notifier_block *self, +unsigned long action,void *data) +{ +void *new_buffer =NULL ; +size_t new_buffer_size, cur_buffer_size; +bool resume = false; + +if (!kexec_in_progress) { +pr_info ("%s: No kexec in progress.\n" , __func__); +return NOTIFY_OK ; + } + +if (!ima_kexec_buffer) { +pr_err ("%s: Kexec buffer not set.\n" , __func__); +return NOTIFY_OK ; + }
security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263
Quoted 10 lines
security/integrity/ima/ima_kexec.c +10
-0+ +ima_measurements_suspend (); + + cur_buffer_size = kexec_segment_size -sizeof (struct ima_kexec_hdr ); + new_buffer_size =ima_get_binary_runtime_size (); +if (new_buffer_size > cur_buffer_size) { +pr_err ("%s: Measurement list grew too large.\n" , __func__); + resume = true; + goto out; + }
This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.
This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.
Quoted 21 lines
security/integrity/ima/ima_kexec.c +18
-0+ima_populate_buf_at_kexec_execute (&new_buffer_size, &new_buffer); + +if (!new_buffer) { +pr_err ("%s: Dump measurements failed.\n" , __func__); + resume = true; + goto out; + } +memcpy (ima_kexec_buffer, new_buffer, new_buffer_size); +out: +kimage_unmap_segment (ima_kexec_buffer); + ima_kexec_buffer =NULL ; + +if (resume) +ima_measurements_resume (); + + return NOTIFY_OK; +} +#endif /* IMA_KEXEC */ /*
Signature · 9 lines
thanks, Mimi _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Mimi Zohar
maintainerRe: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements
Quoted 39 lines · Mimi Zohar
Hi Tushar,
Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19
-0+/* +* Called during kexec execute so that IMA can update the measurement list. +*/ +static int ima_update_kexec_buffer (struct notifier_block *self, +unsigned long action,void *data) +{ +void *new_buffer =NULL ; +size_t new_buffer_size, cur_buffer_size; +bool resume = false; + +if (!kexec_in_progress) { +pr_info ("%s: No kexec in progress.\n" , __func__); +return NOTIFY_OK ; + } + +if (!ima_kexec_buffer) { +pr_err ("%s: Kexec buffer not set.\n" , __func__); +return NOTIFY_OK ; + }security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263
Quoted 10 lines
security/integrity/ima/ima_kexec.c +10
-0+ +ima_measurements_suspend (); + + cur_buffer_size = kexec_segment_size -sizeof (struct ima_kexec_hdr ); + new_buffer_size =ima_get_binary_runtime_size (); +if (new_buffer_size > cur_buffer_size) { +pr_err ("%s: Measurement list grew too large.\n" , __func__); + resume = true; + goto out; + }This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.
Quoted 2 lines
This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.
If not carrying even a partial measurement list across kexec is desired, then in addition to the "boot_aggregate" record, define a new record containing the TPM pcrcounter. With this information, attestation servers will at least be able to detect if the measurement list was truncated.
thanks,
Mimi
Quoted 21 lines
Quoted 21 lines
security/integrity/ima/ima_kexec.c +18
-0+ima_populate_buf_at_kexec_execute (&new_buffer_size, &new_buffer); + +if (!new_buffer) { +pr_err ("%s: Dump measurements failed.\n" , __func__); + resume = true; + goto out; + } +memcpy (ima_kexec_buffer, new_buffer, new_buffer_size); +out: +kimage_unmap_segment (ima_kexec_buffer); + ima_kexec_buffer =NULL ; + +if (resume) +ima_measurements_resume (); + + return NOTIFY_OK; +} +#endif /* IMA_KEXEC */
Quoted 2 lines
Quoted 1 line
/*
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements
Adding Eric to cc.
Quoted 47 lines · Mimi Zohar
Quoted 38 lines · Mimi Zohar
Hi Tushar,
Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19
-0+/* +* Called during kexec execute so that IMA can update the measurement list. +*/ +static int ima_update_kexec_buffer (struct notifier_block *self, +unsigned long action,void *data) +{ +void *new_buffer =NULL ; +size_t new_buffer_size, cur_buffer_size; +bool resume = false; + +if (!kexec_in_progress) { +pr_info ("%s: No kexec in progress.\n" , __func__); +return NOTIFY_OK ; + } + +if (!ima_kexec_buffer) { +pr_err ("%s: Kexec buffer not set.\n" , __func__); +return NOTIFY_OK ; + }security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263
Quoted 10 lines
security/integrity/ima/ima_kexec.c +10
-0+ +ima_measurements_suspend (); + + cur_buffer_size = kexec_segment_size -sizeof (struct ima_kexec_hdr ); + new_buffer_size =ima_get_binary_runtime_size (); +if (new_buffer_size > cur_buffer_size) { +pr_err ("%s: Measurement list grew too large.\n" , __func__); + resume = true; + goto out; + }This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.
Quoted 2 lines
This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.
If not carrying even a partial measurement list across kexec is desired, then in addition to the "
boot_aggregate" record, define a new record containing the TPM pcrcounter. With this information, attestation servers will at least be able to detect if the measurement list was truncated.
Quoted 3 lines
thanks,
Mimi
Sure. Recording TPM pcrcounter at boot aggregate and Kexec 'load' should provide the necessary information to the attestation servers. We can implement this if needed, based on how rest of the series evolves.
~Tushar
Quoted 21 lines
Quoted 21 lines
Quoted 21 lines
security/integrity/ima/ima_kexec.c +18
-0+ima_populate_buf_at_kexec_execute (&new_buffer_size, &new_buffer); + +if (!new_buffer) { +pr_err ("%s: Dump measurements failed.\n" , __func__); + resume = true; + goto out; + } +memcpy (ima_kexec_buffer, new_buffer, new_buffer_size); +out: +kimage_unmap_segment (ima_kexec_buffer); + ima_kexec_buffer =NULL ; + +if (resume) +ima_measurements_resume (); + + return NOTIFY_OK; +} +#endif /* IMA_KEXEC */ /*
Mimi Zohar
maintainerRe: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements
Quoted 50 lines · Tushar Sugandhi
Adding Eric to cc.
Quoted 39 lines · Mimi Zohar
Quoted 38 lines · Mimi Zohar
Hi Tushar,
Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19
-0+/* +* Called during kexec execute so that IMA can update the measurement list. +*/ +static int ima_update_kexec_buffer (struct notifier_block *self, +unsigned long action,void *data) +{ +void *new_buffer =NULL ; +size_t new_buffer_size, cur_buffer_size; +bool resume = false; + +if (!kexec_in_progress) { +pr_info ("%s: No kexec in progress.\n" , __func__); +return NOTIFY_OK ; + } + +if (!ima_kexec_buffer) { +pr_err ("%s: Kexec buffer not set.\n" , __func__); +return NOTIFY_OK ; + }security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263
Quoted 10 lines
security/integrity/ima/ima_kexec.c +10
-0+ +ima_measurements_suspend (); + + cur_buffer_size = kexec_segment_size -sizeof (struct ima_kexec_hdr ); + new_buffer_size =ima_get_binary_runtime_size (); +if (new_buffer_size > cur_buffer_size) { +pr_err ("%s: Measurement list grew too large.\n" , __func__); + resume = true; + goto out; + }This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.
Quoted 7 lines
Quoted 2 lines
This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.
If not carrying even a partial measurement list across kexec is desired, then in addition to the "
boot_aggregate" record, define a new record containing the TPM pcrcounter. With this information, attestation servers will at least be able to detect if the measurement list was truncated.
Quoted 4 lines
Sure. Recording TPM pcrcounter at boot aggregate and Kexec 'load' should provide the necessary information to the attestation servers. We can implement this if needed, based on how rest of the series evolves.
Recording the TPM pcrcounter should be done independently of this patch set. This patch set would have a dependency on it.
Signature · 9 lines
thanks, Mimi _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements
In reply to Mimi ZoharAdding Eric to cc.
Quoted 38 lines · Mimi Zohar
Hi Tushar,
Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19
-0+/* +* Called during kexec execute so that IMA can update the measurement list. +*/ +static int ima_update_kexec_buffer (struct notifier_block *self, +unsigned long action,void *data) +{ +void *new_buffer =NULL ; +size_t new_buffer_size, cur_buffer_size; +bool resume = false; + +if (!kexec_in_progress) { +pr_info ("%s: No kexec in progress.\n" , __func__); +return NOTIFY_OK ; + } + +if (!ima_kexec_buffer) { +pr_err ("%s: Kexec buffer not set.\n" , __func__); +return NOTIFY_OK ; + }security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263
Quoted 10 lines
security/integrity/ima/ima_kexec.c +10
-0+ +ima_measurements_suspend (); + + cur_buffer_size = kexec_segment_size -sizeof (struct ima_kexec_hdr ); + new_buffer_size =ima_get_binary_runtime_size (); +if (new_buffer_size > cur_buffer_size) { +pr_err ("%s: Measurement list grew too large.\n" , __func__); + resume = true; + goto out; + }This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.
Quoted 2 lines
This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.
Thanks.
I will update this logic depending if we decide to use ima_dump_measurement_list() at kexec ‘execute’, or combination of ima_allocate_buf_at_kexec_load() and ima_populate_buf_at_kexec_execute() at kexec ‘load’ and kexec ‘execute’ respectively.
~Tushar
Quoted 21 lines
Quoted 21 lines
security/integrity/ima/ima_kexec.c +18
-0+ima_populate_buf_at_kexec_execute (&new_buffer_size, &new_buffer); + +if (!new_buffer) { +pr_err ("%s: Dump measurements failed.\n" , __func__); + resume = true; + goto out; + } +memcpy (ima_kexec_buffer, new_buffer, new_buffer_size); +out: +kimage_unmap_segment (ima_kexec_buffer); + ima_kexec_buffer =NULL ; + +if (resume) +ima_measurements_resume (); + + return NOTIFY_OK; +} +#endif /* IMA_KEXEC */ /*
PATCH 7/10 ima: remove function ima_dump_measurement_list
In reply to Tushar SugandhiThe ima_dump_measurement_list function was designed to iterate over the IMA measurement list and store each entry into a buffer. The buffer, along with its size, would be returned to the caller. However, the function is no longer required in the IMA subsystem. It previously served to dump the measurement list during the kexec 'load' operation, but this functionality has been replaced by an alternative approach in this patch series.
Remove the unused ima_dump_measurement_list function from the IMA subsystem, to ensure a cleaner and more maintainable code.
--- security/integrity/ima/ima_kexec.c | 58 ------------------------------ 1 file changed, 58 deletions(-)
security/integrity/ima/ima_kexec.c +0 -58
@@ -115,64 +115,6 @@ static int ima_populate_buf_at_kexec_execute(unsigned long *buffer_size, void ** } -static int ima_dump_measurement_list (unsigned long *buffer_size,void **buffer, -unsigned long segment_size) -{ -struct ima_queue_entry *qe; -struct seq_file file; -struct ima_kexec_hdr khdr; -int ret =0 ; - -/* segment size can't change between kexec load and execute */ - file.buf =vmalloc (segment_size); -if (!file.buf) { - ret = -ENOMEM ; - goto out; - } - - file.size = segment_size; - file.read_pos =0 ; - file.count =sizeof (khdr);/* reserved space */ - -memset (&khdr,0 ,sizeof (khdr)); - khdr.version =1 ; -list_for_each_entry_rcu (qe, &ima_measurements, later) { -if (file.count < file.size) { - khdr.count++; -ima_measurements_show (&file, qe); - }else { - ret = -EINVAL ; -break ; - } - } - -if (ret <0 ) - goto out; - -/* -* fill in reserved space with some buffer details -* (eg. version, buffer size, number of measurements) -*/ - khdr.buffer_size = file.count; -if (ima_canonical_fmt) { - khdr.version =cpu_to_le16 (khdr.version); - khdr.count =cpu_to_le64 (khdr.count); - khdr.buffer_size =cpu_to_le64 (khdr.buffer_size); - } -memcpy (file.buf, &khdr,sizeof (khdr)); - -print_hex_dump_debug ("ima dump: " ,DUMP_PREFIX_NONE ,16 ,1 , - file.buf, file.count <100 ? file.count :100 , - true); - - *buffer_size = file.count; - *buffer = file.buf; -out: -if (ret == -EINVAL ) -vfree (file.buf); -return ret; -} -/* * Called during kexec_file_load so that IMA can add a segment to the kexec * image for the measurement list for the next kernel.
Signature · 1 line
2.25.1
Mimi Zohar
maintainerRe: [PATCH 07/10] ima: remove function ima_dump_measurement_list
Hi Tushar,
Quoted 8 lines · Tushar Sugandhi
The
ima_dump_measurement_listfunction was designed to iterate over the IMA measurement list and store each entry into a buffer. The buffer, along with its size, would be returned to the caller. However, the function is no longer required in the IMA subsystem. It previously served to dump the measurement list during the kexec 'load' operation, but this functionality has been replaced by an alternative approach in this patch series.
Quoted 4 lines
Remove the unused
ima_dump_measurement_listfunction from the IMA subsystem, to ensure a cleaner and more maintainable code.Signed-off-by Tushar Sugandhi <[email protected]>
Have you compiled the code and tested after applying each patch? Removing the caller before removing the code should have resulted in a warning.
Signature · 3 lines
thanks, Mimi
Re: [PATCH 07/10] ima: remove function ima_dump_measurement_list
Adding Eric to cc.
Quoted 11 lines · Mimi Zohar
Hi Tushar,
Quoted 8 lines · Tushar Sugandhi
The
ima_dump_measurement_listfunction was designed to iterate over the IMA measurement list and store each entry into a buffer. The buffer, along with its size, would be returned to the caller. However, the function is no longer required in the IMA subsystem. It previously served to dump the measurement list during the kexec 'load' operation, but this functionality has been replaced by an alternative approach in this patch series.
Quoted 8 lines
Quoted 4 lines
Remove the unused
ima_dump_measurement_listfunction from the IMA subsystem, to ensure a cleaner and more maintainable code.Signed-off-by Tushar Sugandhi <[email protected]>Have you compiled the code and tested after applying each patch? Removing the caller before removing the code should have resulted in a warning.
Yes, I compiled each patch separately, and I did see this warning. But removing ima_dump_measurement_list after implementing and calling the alternate ima_allocate_buf_at_kexec_load() and ima_populate_buf_at_kexec_execute() felt cleaner in terms of organizing the patches.
I can remove the definition when I deprecate the usage, if we end up using the alternate two functions.
~Tushar
PATCH 8/10 ima: implement and register a reboot notifier function to update kexec buffer
In reply to Tushar SugandhiThe IMA subsystem needs to ensure that the measurement list is up to date during a kexec operation, i.e., when the kernel is rebooted without going through the full system reboot process. Currently, there is no mechanism to update the measurement list when the system is soft booted using kexec.
Add a notifier function ima_update_kexec_buffer that is called during a kexec soft reboot. Implement ima_kexec_post_load, which maps the IMA buffer after a kexec load and registers the reboot notifier.
Define a new notifier block update_buffer_nb, with ima_update_kexec_buffer as its notifier function. Register the notifier function in ima_kexec_post_load if it hasn't been already, indicated by the ima_kexec_update_registered flag.
When a kexec soft reboot is triggered, ima_update_kexec_buffer will be executed to update the IMA buffer. This ensures that the events between kexec 'load' and 'execute' are captured and integrity of measurements remains intact across kexec reboots.
--- include/linux/ima.h | 3 +++ security/integrity/ima/ima_kexec.c | 35 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+)
include/linux/ima.h +3 -0
@@ -49,6 +49,9 @@ static inline void ima_appraise_parse_cmdline(void) {}#ifdef CONFIG_IMA_KEXEC extern void ima_add_kexec_buffer (struct kimage *image); +extern void ima_kexec_post_load (struct kimage *image); +#else +static inline void ima_kexec_post_load (struct kimage *image) {}#endif #else
security/integrity/ima/ima_kexec.c +35 -0
@@ -12,6 +12,8 @@#include <linux/kexec.h> #include <linux/of.h> #include <linux/ima.h> +#include <linux/reboot.h> +#include <asm/page.h> #include "ima.h" #ifdef CONFIG_IMA_KEXEC
@@ -19,6 +21,7 @@ struct seq_file ima_kexec_file;struct ima_kexec_hdr ima_khdr;static size_t kexec_segment_size;static void *ima_kexec_buffer; +static bool ima_kexec_update_registered;void ima_clear_kexec_file (void ) {
@@ -222,6 +225,38 @@ static int ima_update_kexec_buffer(struct notifier_block *self, return NOTIFY_OK; } +struct notifier_block update_buffer_nb = { + .notifier_call = ima_update_kexec_buffer, +}; + +/* +* Create a mapping for the source pages that contain the IMA buffer +* so we can update it later. +*/ +void ima_kexec_post_load (struct kimage *image) +{ +if (ima_kexec_buffer) { +kimage_unmap_segment (ima_kexec_buffer); + ima_kexec_buffer =NULL ; + } + +if (!image->ima_buffer_addr) +return ; + + ima_kexec_buffer =kimage_map_segment (image, + image->ima_buffer_addr, + image->ima_buffer_size); +if (!ima_kexec_buffer) { +pr_err ("%s: Could not map measurements buffer.\n" , __func__); +return ; + } + +if (!ima_kexec_update_registered) { +register_reboot_notifier (&update_buffer_nb); + ima_kexec_update_registered = true; + } +} +#endif /* IMA_KEXEC */ /*
Signature · 1 line
2.25.1
PATCH 9/10 ima: suspend measurements while the kexec buffer is being copied
In reply to Tushar SugandhiIf the new measurements are added to the list while the kexec buffer is being copied during kexec execute, the buffer may get corrupted, or it can go out of sync with TPM PCRs. This could potentially lead to breaking the integrity of the measurements after the kexec soft reboot to the new kernel.
Introduce a check in the ima_add_template_entry function not to measure events and return from the function early when the suspend_ima_measurements flag is set.
This ensures the consistency of the IMA measurement list during the copying of the kexec buffer. When the suspend_ima_measurements flag is set, any new measurements will be ignored until the flag is unset. This allows the buffer to be safely copied without worrying about concurrent modifications to the measurement list. This is crucial for maintaining the integrity of the measurements during a kexec soft reboot.
--- security/integrity/ima/ima_queue.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
security/integrity/ima/ima_queue.c +13 -0
@@ -195,6 +195,19 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, } } +/* +* suspend_ima_measurements will be set if the system is +* undergoing kexec soft boot to a new kernel. +* suspending measurements in this short window ensures the +* consistency of the IMA measurement list during copying +* of the kexec buffer. +*/ +if (atomic_read (&suspend_ima_measurements)) { + audit_cause ="measurements_suspended" ; + audit_info =0 ; + goto out; + } + result =ima_add_digest_entry (entry, !IS_ENABLED (CONFIG_IMA_DISABLE_HTABLE ));if (result <0 ) {
Signature · 1 line
2.25.1
PATCH 10/10 kexec: update kexec_file_load syscall to call ima_kexec_post_load
In reply to Tushar SugandhiThe kexec_file_load syscall is used to load a new kernel for kexec. The syscall needs to update its function to call ima_kexec_post_load, which was implemented in a previous patch. ima_kexec_post_load takes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.
Modify the kexec_file_load syscall to call ima_kexec_post_load after the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.
Declare the kimage_file_post_load function in the kernel/kexec_internal.h, so it can be properly used in the syscall.
--- kernel/kexec_file.c | 7 +++++++ kernel/kexec_internal.h | 1 + 2 files changed, 8 insertions(+)
kernel/kexec_file.c +7 -0
@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image) }#endif +void kimage_file_post_load (struct kimage *image) +{ +ima_kexec_post_load (image); +} +/* * In file mode list of segments is prepared by kernel. Copy relevant * data from user space, do error checking, prepare segment list
@@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,kimage_terminate (image); +kimage_file_post_load (image); + ret =machine_kexec_post_load (image);if (ret) goto out;
kernel/kexec_internal.h +1 -0
@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)#ifdef CONFIG_KEXEC_FILE #include <linux/purgatory.h> +void kimage_file_post_load (struct kimage *image);void kimage_file_post_load_cleanup (struct kimage *image);extern char kexec_purgatory[];extern size_t kexec_purgatory_size;
Signature · 1 line
2.25.1
Re: [PATCH 10/10] kexec: update kexec_file_load syscall to call ima_kexec_post_load
Quoted 39 lines · Tushar Sugandhi
The
kexec_file_loadsyscall is used to load a new kernel for kexec. The syscall needs to update its function to callima_kexec_post_load, which was implemented in a previous patch.ima_kexec_post_loadtakes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.Modify the
kexec_file_loadsyscall to callima_kexec_post_loadafter the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.Declare the
kimage_file_post_loadfunction in thekernel/kexec_internal.h, so it can be properly used in the syscall.Signed-off-by Tushar Sugandhi <[email protected]>--- kernel/kexec_file.c | 7 +++++++ kernel/kexec_internal.h | 1 + 2 files changed, 8 insertions(+)kernel/kexec_file.c +5
-0@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image) }#endif +void kimage_file_post_load (struct kimage *image) +{ +ima_kexec_post_load (image); +} +/* * In file mode list of segments is prepared by kernel. Copy relevant * data from user space, do error checking, prepare segment list
kernel/kexec_file.c SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, · line 407
Quoted 4 lines
kernel/kexec_file.c +1
-0@@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,kimage_terminate (image); +kimage_file_post_load (image);
I think it should be only done for the reboot case, please just exclude the kdump case here..
Quoted 20 lines
kernel/kexec_file.c +1
-0+ ret =machine_kexec_post_load (image);if (ret) goto out;kernel/kexec_internal.h +1
-1@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)#ifdef CONFIG_KEXEC_FILE #include <linux/purgatory.h> +void kimage_file_post_load (struct kimage *image);void kimage_file_post_load_cleanup (struct kimage *image);extern char kexec_purgatory[];extern size_t kexec_purgatory_size; --2.25.1
Quoted 5 lines
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 10/10] kexec: update kexec_file_load syscall to call ima_kexec_post_load
Quoted 41 lines · RuiRui Yang
Quoted 39 lines · Tushar Sugandhi
The
kexec_file_loadsyscall is used to load a new kernel for kexec. The syscall needs to update its function to callima_kexec_post_load, which was implemented in a previous patch.ima_kexec_post_loadtakes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.Modify the
kexec_file_loadsyscall to callima_kexec_post_loadafter the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.Declare the
kimage_file_post_loadfunction in thekernel/kexec_internal.h, so it can be properly used in the syscall.Signed-off-by Tushar Sugandhi <[email protected]>--- kernel/kexec_file.c | 7 +++++++ kernel/kexec_internal.h | 1 + 2 files changed, 8 insertions(+)kernel/kexec_file.c +5
-0@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image) }#endif +void kimage_file_post_load (struct kimage *image) +{ +ima_kexec_post_load (image); +} +/* * In file mode list of segments is prepared by kernel. Copy relevant * data from user space, do error checking, prepare segment list @@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
Quoted 6 lines
kernel/kexec_file.c SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, · line 407
Quoted 3 lines
kernel/kexec_file.c +1
-0kimage_terminate (image); +kimage_file_post_load (image);I think it should be only done for the reboot case, please just exclude the kdump case here..
Thanks for the feedback RuiRui. Appreciate it.
Conceptually I agree with you that this needs to be done only for reboot. I need to figure out how to do it implementation wise.
If you can give me pointers/suggestions, that would help.
~Tushar
Quoted 25 lines
Quoted 25 lines
kernel/kexec_file.c +1
-0+ ret =machine_kexec_post_load (image);if (ret) goto out;kernel/kexec_internal.h +1
-1@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)#ifdef CONFIG_KEXEC_FILE #include <linux/purgatory.h> +void kimage_file_post_load (struct kimage *image);void kimage_file_post_load_cleanup (struct kimage *image);extern char kexec_purgatory[];extern size_t kexec_purgatory_size; --2.25.1
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 10/10] kexec: update kexec_file_load syscall to call ima_kexec_post_load
Quoted 50 lines · Tushar Sugandhi
Quoted 41 lines · RuiRui Yang
Quoted 39 lines · Tushar Sugandhi
The
kexec_file_loadsyscall is used to load a new kernel for kexec. The syscall needs to update its function to callima_kexec_post_load, which was implemented in a previous patch.ima_kexec_post_loadtakes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.Modify the
kexec_file_loadsyscall to callima_kexec_post_loadafter the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.Declare the
kimage_file_post_loadfunction in thekernel/kexec_internal.h, so it can be properly used in the syscall.Signed-off-by Tushar Sugandhi <[email protected]>--- kernel/kexec_file.c | 7 +++++++ kernel/kexec_internal.h | 1 + 2 files changed, 8 insertions(+)kernel/kexec_file.c +5
-0@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image) }#endif +void kimage_file_post_load (struct kimage *image) +{ +ima_kexec_post_load (image); +} +/* * In file mode list of segments is prepared by kernel. Copy relevant * data from user space, do error checking, prepare segment list @@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,Quoted 6 lines
kernel/kexec_file.c SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, · line 407
Quoted 3 lines
kernel/kexec_file.c +1
-0kimage_terminate (image); +kimage_file_post_load (image);I think it should be only done for the reboot case, please just exclude the kdump case here..
Quoted 6 lines
Thanks for the feedback RuiRui. Appreciate it.
Conceptually I agree with you that this needs to be done only for reboot. I need to figure out how to do it implementation wise.
If you can give me pointers/suggestions, that would help.
Hi Tushar,
You can check the flags argument in the function
if (flags & KEXEC_FILE_ON_CRASH) is true then this is a kdump kernel loading, just skip the kimage_file_post_load in that case?
Quoted 28 lines
~Tushar
Quoted 25 lines
Quoted 25 lines
kernel/kexec_file.c +1
-0+ ret =machine_kexec_post_load (image);if (ret) goto out;kernel/kexec_internal.h +1
-1@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)#ifdef CONFIG_KEXEC_FILE #include <linux/purgatory.h> +void kimage_file_post_load (struct kimage *image);void kimage_file_post_load_cleanup (struct kimage *image);extern char kexec_purgatory[];extern size_t kexec_purgatory_size; --2.25.1
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH 10/10] kexec: update kexec_file_load syscall to call ima_kexec_post_load
Quoted 56 lines · RuiRui Yang
Quoted 54 lines · Tushar Sugandhi
Quoted 41 lines · RuiRui Yang
Quoted 39 lines · Tushar Sugandhi
The
kexec_file_loadsyscall is used to load a new kernel for kexec. The syscall needs to update its function to callima_kexec_post_load, which was implemented in a previous patch.ima_kexec_post_loadtakes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.Modify the
kexec_file_loadsyscall to callima_kexec_post_loadafter the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.Declare the
kimage_file_post_loadfunction in thekernel/kexec_internal.h, so it can be properly used in the syscall.Signed-off-by Tushar Sugandhi <[email protected]>--- kernel/kexec_file.c | 7 +++++++ kernel/kexec_internal.h | 1 + 2 files changed, 8 insertions(+)kernel/kexec_file.c +5
-0@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image) }#endif +void kimage_file_post_load (struct kimage *image) +{ +ima_kexec_post_load (image); +} +/* * In file mode list of segments is prepared by kernel. Copy relevant * data from user space, do error checking, prepare segment list @@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,Quoted 6 lines
kernel/kexec_file.c SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, · line 407
Quoted 3 lines
kernel/kexec_file.c +1
-0kimage_terminate (image); +kimage_file_post_load (image);I think it should be only done for the reboot case, please just exclude the kdump case here..
Thanks for the feedback RuiRui. Appreciate it.
Conceptually I agree with you that this needs to be done only for reboot. I need to figure out how to do it implementation wise.
Quoted 6 lines
Quoted 1 line
If you can give me pointers/suggestions, that would help.
Hi Tushar,
You can check the flags argument in the function
if (flags &KEXEC_FILE_ON_CRASH) is true then this is a kdump kernel loading, just skip thekimage_file_post_loadin that case?
Great. Thanks for the pointer. Will do.
~Tushar
Quoted 26 lines
Quoted 26 lines
~Tushar
Quoted 25 lines
Quoted 25 lines
kernel/kexec_file.c +1
-0+ ret =machine_kexec_post_load (image);if (ret) goto out;kernel/kexec_internal.h +1
-1@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)#ifdef CONFIG_KEXEC_FILE #include <linux/purgatory.h> +void kimage_file_post_load (struct kimage *image);void kimage_file_post_load_cleanup (struct kimage *image);extern char kexec_purgatory[];extern size_t kexec_purgatory_size; --2.25.1
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
[Add Eric in cc]
Quoted 82 lines · Tushar Sugandhi
The current Kernel behavior is IMA measurements snapshot is taken at kexec 'load' and not at kexec 'execute'. IMA log is then carried over to the new Kernel after kexec 'execute'.
Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.
This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.
The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',
- ima functionality for mapping the measurement list from the current Kernel to the subsequent one,
- necessary changes to the
kexec_file_loadsyscall, enabling it to call the ima functions- registering a reboot notifier which gets called during kexec 'execute',
- and removal of deprecated functions.
The modifications proposed in this series ensure the integrity of the ima measurements is preserved across kexec soft reboots, thus significantly improving the security of the Kernel post kexec soft reboots.
There were previous attempts to fix this issue [1], [2], [3]. But they were not merged into the mainline Kernel.
We took inspiration from the past work [1] and [2] while working on this patch series.
References:
-----------[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/[2] PATCH v2 4/6]
kexec_file: Add mechanism to update kexec segments.
https://lkml.org/lkml/2016/8/16/577[3] [PATCH 1/6]
kexec_file: Add buffer hand-over support
https://lore.kernel.org/linuxppc-dev/[email protected]/T/Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove functionima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: updatekexec_file_loadsyscall to callima_kexec_post_loadinclude/linux/ima.h | 3 + include/linux/kexec.h | 13 ++ kernel/kexec_core.c | 72 +++++++++- kernel/kexec_file.c | 7 + kernel/kexec_internal.h | 1 + security/integrity/ima/ima.h | 4 + security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------ security/integrity/ima/ima_queue.c | 32 +++++ 8 files changed, 295 insertions(+), 48 deletions(-)
Quoted 9 lines
--
2.25.1_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Thanks Dave for taking a look at this.
I will keep Eric looped in on the next versions of this patch series.
~Tushar
Quoted 94 lines · Dave Young
[Add Eric in cc]
Quoted 90 lines · Tushar Sugandhi
The current Kernel behavior is IMA measurements snapshot is taken at kexec 'load' and not at kexec 'execute'. IMA log is then carried over to the new Kernel after kexec 'execute'.
Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.
This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.
The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',
- ima functionality for mapping the measurement list from the current Kernel to the subsequent one,
- necessary changes to the
kexec_file_loadsyscall, enabling it to call the ima functions- registering a reboot notifier which gets called during kexec 'execute',
- and removal of deprecated functions.
The modifications proposed in this series ensure the integrity of the ima measurements is preserved across kexec soft reboots, thus significantly improving the security of the Kernel post kexec soft reboots.
There were previous attempts to fix this issue [1], [2], [3]. But they were not merged into the mainline Kernel.
We took inspiration from the past work [1] and [2] while working on this patch series.
References:
-----------[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/[2] PATCH v2 4/6]
kexec_file: Add mechanism to update kexec segments.
https://lkml.org/lkml/2016/8/16/577[3] [PATCH 1/6]
kexec_file: Add buffer hand-over support
https://lore.kernel.org/linuxppc-dev/[email protected]/T/Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove functionima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: updatekexec_file_loadsyscall to callima_kexec_post_loadinclude/linux/ima.h | 3 + include/linux/kexec.h | 13 ++ kernel/kexec_core.c | 72 +++++++++- kernel/kexec_file.c | 7 + kernel/kexec_internal.h | 1 + security/integrity/ima/ima.h | 4 + security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------ security/integrity/ima/ima_queue.c | 32 +++++ 8 files changed, 295 insertions(+), 48 deletions(-)--
2.25.1_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Mimi Zohar
maintainerQuoted 15 lines · Tushar Sugandhi
The current Kernel behavior is IMA measurements snapshot is taken at kexec 'load' and not at kexec 'execute'. IMA log is then carried over to the new Kernel after kexec 'execute'.
Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.
Quoted 3 lines
This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.
Thanks, Tushar. Depending on the IMA policy, the above problem
statement is correct, but not all policies are affected by it. It's also unclear why so much needs to change. Instead of copying the measurement list at kexec 'load', using the existing method and simply copying them at kexec 'exec' would suffice.
Also as mentioned in comment on 3/10, the ordering of this patch set is not bisect safe. If the same method of copying the measurement list was used, changing from copying at kexec 'load' to kexec 'exec' could be done in the same patch.
Mimi
Quoted 53 lines
The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',
- ima functionality for mapping the measurement list from the current Kernel to the subsequent one,
- necessary changes to the
kexec_file_loadsyscall, enabling it to call the ima functions- registering a reboot notifier which gets called during kexec 'execute',
- and removal of deprecated functions.
The modifications proposed in this series ensure the integrity of the ima measurements is preserved across kexec soft reboots, thus significantly improving the security of the Kernel post kexec soft reboots.
There were previous attempts to fix this issue [1], [2], [3]. But they were not merged into the mainline Kernel.
We took inspiration from the past work [1] and [2] while working on this patch series.
References:
-----------[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/[2] PATCH v2 4/6]
kexec_file: Add mechanism to update kexec segments.
https://lkml.org/lkml/2016/8/16/577[3] [PATCH 1/6]
kexec_file: Add buffer hand-over support
https://lore.kernel.org/linuxppc-dev/[email protected]/T/Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove functionima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: updatekexec_file_loadsyscall to callima_kexec_post_load
Quoted 10 lines
include/linux/ima.h | 3 + include/linux/kexec.h | 13 ++ kernel/kexec_core.c | 72 +++++++++- kernel/kexec_file.c | 7 + kernel/kexec_internal.h | 1 + security/integrity/ima/ima.h | 4 + security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------ security/integrity/ima/ima_queue.c | 32 +++++ 8 files changed, 295 insertions(+), 48 deletions(-)
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Thanks for reviewing this series Mimi. Appreciate it.
Adding Eric to cc.
Quoted 16 lines · Mimi Zohar
Quoted 15 lines · Tushar Sugandhi
The current Kernel behavior is IMA measurements snapshot is taken at kexec 'load' and not at kexec 'execute'. IMA log is then carried over to the new Kernel after kexec 'execute'.
Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.
Quoted 8 lines
Quoted 3 lines
This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.
Thanks, Tushar. Depending on the IMA policy, the above problem
statement is correct, but not all policies are affected by it. It's also unclear why so much needs to change. Instead of copying the measurement list at kexec 'load', using the existing method and simply copying them at kexec 'exec' would suffice.
My understanding is the buffer must be allocated at kexec ‘load’ time. The segment size cannot change between kexec ‘load’ and kexec ‘execute’. Not sure if this is a technical limitation of IMA, or KEXEC.
Could you/someone from kexec side let me know?
If my current understanding is not correct, then I agree, simply copying the measurements at kexec ‘execute’ using ima_dump_measurement_list should suffice.
Quoted 7 lines
Also as mentioned in comment on 3/10, the ordering of this patch set is not bisect safe. If the same method of copying the measurement list was used, changing from copying at kexec 'load' to kexec 'exec' could be done in the same patch.
Mimi
Ok. Based on my above response, if there is no such technical limitation to allocate and copy at kexec ‘execute’ – I will simply move the call to ima_dump_measurement_list from kexec 'load' to 'exec'. And that can be done inthe same patch as you mentioned.
~Tushar
Quoted 63 lines
Quoted 63 lines
The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',
- ima functionality for mapping the measurement list from the current Kernel to the subsequent one,
- necessary changes to the
kexec_file_loadsyscall, enabling it to call the ima functions- registering a reboot notifier which gets called during kexec 'execute',
- and removal of deprecated functions.
The modifications proposed in this series ensure the integrity of the ima measurements is preserved across kexec soft reboots, thus significantly improving the security of the Kernel post kexec soft reboots.
There were previous attempts to fix this issue [1], [2], [3]. But they were not merged into the mainline Kernel.
We took inspiration from the past work [1] and [2] while working on this patch series.
References:
-----------[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/[2] PATCH v2 4/6]
kexec_file: Add mechanism to update kexec segments.
https://lkml.org/lkml/2016/8/16/577[3] [PATCH 1/6]
kexec_file: Add buffer hand-over support
https://lore.kernel.org/linuxppc-dev/[email protected]/T/Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove functionima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: updatekexec_file_loadsyscall to callima_kexec_post_loadinclude/linux/ima.h | 3 + include/linux/kexec.h | 13 ++ kernel/kexec_core.c | 72 +++++++++- kernel/kexec_file.c | 7 + kernel/kexec_internal.h | 1 + security/integrity/ima/ima.h | 4 + security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------ security/integrity/ima/ima_queue.c | 32 +++++ 8 files changed, 295 insertions(+), 48 deletions(-)
Quoted 45 lines · Tushar Sugandhi
Thanks for reviewing this series Mimi. Appreciate it.
Adding Eric to cc.
Quoted 16 lines · Mimi Zohar
Quoted 15 lines · Tushar Sugandhi
The current Kernel behavior is IMA measurements snapshot is taken at kexec 'load' and not at kexec 'execute'. IMA log is then carried over to the new Kernel after kexec 'execute'.
Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.
Quoted 8 lines
Quoted 3 lines
This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.
Thanks, Tushar. Depending on the IMA policy, the above problem statement is correct, but not all policies are affected by it. It's also unclear why so much needs to change. Instead of copying the measurement list at kexec 'load', using the existing method and simply copying them at kexec 'exec' would suffice.
My understanding is the buffer must be allocated at kexec ‘load’ time. The segment size cannot change between kexec ‘load’ and kexec ‘execute’. Not sure if this is a technical limitation of IMA, or KEXEC.
Could you/someone from kexec side let me know?
If my current understanding is not correct, then I agree, simply copying the measurements at kexec ‘execute’ using
ima_dump_measurement_listshould suffice.Quoted 6 lines
Also as mentioned in comment on 3/10, the ordering of this patch set is not bisect safe. If the same method of copying the measurement list was used, changing from copying at kexec 'load' to kexec 'exec' could be done in the same patch.
Quoted 7 lines
Quoted 1 line
Mimi
Ok. Based on my above response, if there is no such technical limitation to allocate and copy at kexec ‘execute’ – I will simply move the call to
ima_dump_measurement_listfrom kexec 'load' to 'exec'. And that can be done inthe same patch as you mentioned.~Tushar
Hello all,
For the last few days, I did several experiments to allocate the memory during kexec 'execute' rather than at the existing kexec 'load'.
My experiments either resulted in Kernel panics, or didn't copy the IMA log entries added between 'load' and 'execute'.
As per my understanding, and also documented in several comments in kexec code (e.g. in kexec_file.c [1]), adding buffer after allocating control pages is not allowed. All segments need to be placed first before any control pages are allocated.
And control page allocation happens at kexec 'load' [3][4][5].
There are several checks that ensures new buffer segments are not allocated after control pages are allocated at kexec 'load'. e.g. kexec_file.c[1][3], kexec_core.c[2].
If we want to allocate buffer at kexec 'execute' to address this issue of "missing entries in IMA log during kexec load-execute window", we will have to bypass those checks. That would be a very significant change in kexec logic. And I do not believe its the right approach.
I believe we have to stick with the current approach of allocating memory segments at kexec 'load', and copy whatever we can, during kexe 'execute'.
Thanks,
Tushar
[1] https://elixir.bootlin.com/linux/latest/source/kernel/kexec_file.c#L652
int kexec_add_buffer(struct kexec_buf *kbuf)
{
...
/*
* Make sure we are not trying to add buffer after allocating
* control pages. All segments need to be placed first before
* any control pages are allocated. As control page allocation
* logic goes through list of segments to make sure there are
* no destination overlaps.
*/
if (!list_empty(&kbuf->image->control_pages)) {
WARN_ON(1);
return -EINVAL;
}
...
}
[2] https://elixir.bootlin.com/linux/latest/source/kernel/kexec_core.c#L352
static struct page *kimage_alloc_normal_control_pages(struct kimage *image, unsigned int order)
{
/* Control pages are special, they are the intermediaries
* that are needed while we copy the rest of the pages
* to their final resting place. As such they must
* not conflict with either the destination addresses
* or memory the kernel is already using.
*
* The only case where we really need more than one of
* these are for architectures where we cannot disable
* the MMU and must instead generate an identity mapped
* page table for all of the memory.
*
* At worst this runs in O(N) of the image size.
*/
...
}
[3] https://elixir.bootlin.com/linux/latest/source/kernel/kexec_file.c#L299
static int
kimage_file_alloc_init(struct kimage **rimage, int kernel_fd, int initrd_fd, const char __user *cmdline_ptr, unsigned long cmdline_len, unsigned long flags) {
image->control_code_page = kimage_alloc_control_pages(image, get_order(KEXEC_CONTROL_PAGE_SIZE)); if (!image->control_code_page) {
pr_err("Could not allocate control_code_buffer\n"); goto out_free_post_load_bufs;
}
}
[4] https://elixir.bootlin.com/linux/latest/source/kernel/kexec_file.c#L366
SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, unsigned long, cmdline_len, const char __user *, cmdline_ptr, unsigned long, flags)
{
...
ret = kimage_file_alloc_init(&image, kernel_fd, initrd_fd, cmdline_ptr,
... cmdline_len, flags);
}
[5] https://elixir.bootlin.com/linux/latest/source/kernel/kexec.c#L63
static int kimage_alloc_init(struct kimage **rimage, unsigned long entry, unsigned long nr_segments,
struct kexec_segment *segments,
unsigned long flags)
{
...
image->control_code_page = kimage_alloc_control_pages(image,
get_order(KEXEC_CONTROL_PAGE_SIZE));
if (!image->control_code_page) {
pr_err("Could not allocate control_code_buffer\n");
goto out_free_image;
}
...
}Quoted 63 lines
Quoted 63 lines
Quoted 63 lines
The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',
- ima functionality for mapping the measurement list from the current Kernel to the subsequent one,
- necessary changes to the
kexec_file_loadsyscall, enabling it to call the ima functions- registering a reboot notifier which gets called during kexec 'execute',
- and removal of deprecated functions.
The modifications proposed in this series ensure the integrity of the ima measurements is preserved across kexec soft reboots, thus significantly improving the security of the Kernel post kexec soft reboots.
There were previous attempts to fix this issue [1], [2], [3]. But they were not merged into the mainline Kernel.
We took inspiration from the past work [1] and [2] while working on this patch series.
References:
-----------[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/[2] PATCH v2 4/6]
kexec_file: Add mechanism to update kexec segments.
https://lkml.org/lkml/2016/8/16/577[3] [PATCH 1/6]
kexec_file: Add buffer hand-over support
https://lore.kernel.org/linuxppc-dev/[email protected]/T/Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove functionima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: updatekexec_file_loadsyscall to callima_kexec_post_loadinclude/linux/ima.h | 3 + include/linux/kexec.h | 13 ++ kernel/kexec_core.c | 72 +++++++++- kernel/kexec_file.c | 7 + kernel/kexec_internal.h | 1 + security/integrity/ima/ima.h | 4 +
security/integrity/ima/ima_kexec.c| 211 +++++++++++++++++++++++------security/integrity/ima/ima_queue.c| 32 +++++8 files changed, 295 insertions(+), 48 deletions(-)