...
...
63
63
64
V8 of this series is available here[10] for reference.
64
V8 of this series is available here[10] for reference.
65
65
66
V9 of this series is available here[11] for reference.
66
V9 of this series is available here[11] for reference.
67
67
68
V10 of this series is available here[12] for reference.
69
68
References:
70
References:
69
-----------
71
-----------
70
72
71
[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
73
[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
72
https://lore.kernel.org/lkml/1472596811-9596-6-git-send-email-zohar@linux.vnet.ibm.com/
74
https://lore.kernel.org/lkml/1472596811-9596-6-git-send-email-zohar@linux.vnet.ibm.com/
...
...
98
[10] [PATCH v8 0/7] ima: kexec: measure events between kexec load and execute
100
[10] [PATCH v8 0/7] ima: kexec: measure events between kexec load and execute
99
https://lore.kernel.org/all/20250218225502.747963-1-chenste@linux.microsoft.com/
101
https://lore.kernel.org/all/20250218225502.747963-1-chenste@linux.microsoft.com/
100
102
101
[11] [PATCH v9 0/7] ima: kexec: measure events between kexec load and execute
103
[11] [PATCH v9 0/7] ima: kexec: measure events between kexec load and execute
102
https://lore.kernel.org/all/20250304190351.96975-1-chenste@linux.microsoft.com/
104
https://lore.kernel.org/all/20250304190351.96975-1-chenste@linux.microsoft.com/
105
106
[12] [PATCH v10 0/8] ima: kexec: measure events between kexec load and execute
107
https://lore.kernel.org/all/20250318010448.954-1-chenste@linux.microsoft.com/
108
109
Change Log v11:
110
- Incorporated feedback from the community (Mimi Zohar and Baoquan He) on
111
v10 of this series[12].
112
- [PATCH V10 2/8] was splited into two [PATCH V11 2/9] and [PATCH V11 7/9].
113
Per Mimi comment on [PATCH V10 2/8].
114
- Verified all the patches are bisect-safe by booting into each
115
patch and verifying multiple kexec 'load' operations work,
116
and also verifying kexec soft reboot works, and IMA log gets
117
carried over for each patch.
118
- Updated patch descriptions as necessary.
103
119
104
Change Log v10:
120
Change Log v10:
105
- Incorporated feedback from the community (Mimi Zohar, Baoquan He, and
121
- Incorporated feedback from the community (Mimi Zohar, Baoquan He, and
106
kernel test robot) on v9 of this series[11].
122
kernel test robot) on v9 of this series[11].
107
- [PATCH V9 1/7] was splited into two [PATCH V10 1/8] and [PATCH V10 2/8].
123
- [PATCH V9 1/7] was splited into two [PATCH V10 1/8] and [PATCH V10 2/8].
...
...
230
- Refactored patches to ensure no warnings during individual patch
246
- Refactored patches to ensure no warnings during individual patch
231
compilation.
247
compilation.
232
- Used virt_to_page instead of phys_to_page.
248
- Used virt_to_page instead of phys_to_page.
233
- Updated patch descriptions as necessary.
249
- Updated patch descriptions as necessary.
234
250
235
steven chen (8):
251
236
ima: rename variable the ser_file "file" to "ima_kexec_file"
252
steven chen (9):
253
ima: rename variable the set_file "file" to "ima_kexec_file"
237
ima: define and call ima_alloc_kexec_file_buf()
254
ima: define and call ima_alloc_kexec_file_buf()
238
kexec: define functions to map and unmap segments
255
kexec: define functions to map and unmap segments
239
ima: kexec: skip IMA segment validation after kexec soft reboot
256
ima: kexec: skip IMA segment validation after kexec soft reboot
240
ima: kexec: define functions to copy IMA log at soft boot
257
ima: kexec: define functions to copy IMA log at soft boot
241
ima: kexec: move IMA log copy from kexec load to execute
258
ima: kexec: move IMA log copy from kexec load to execute
259
ima: verify if the segment size has changed
242
ima: make the kexec extra memory configurable
260
ima: make the kexec extra memory configurable
243
ima: measure kexec load and exec events as critical data
261
ima: measure kexec load and exec events as critical data
244
262
245
include/linux/ima.h | 3 +
263
include/linux/ima.h | 3 +
246
include/linux/kexec.h | 9 ++
264
include/linux/kexec.h | 9 ++
247
kernel/kexec_core.c | 54 ++++++++
265
kernel/kexec_core.c | 54 ++++++++
248
kernel/kexec_file.c | 32 +++++
266
kernel/kexec_file.c | 33 ++++-
249
security/integrity/ima/Kconfig | 10 ++
267
security/integrity/ima/Kconfig | 10 ++
250
security/integrity/ima/ima.h | 6 +
268
security/integrity/ima/ima.h | 6 +
251
security/integrity/ima/ima_kexec.c | 206 ++++++++++++++++++++++++-----
269
security/integrity/ima/ima_kexec.c | 193 ++++++++++++++++++++++++-----
252
security/integrity/ima/ima_queue.c | 5 +
270
security/integrity/ima/ima_queue.c | 5 +
253
8 files changed, 292 insertions(+), 33 deletions(-)
271
8 files changed, 279 insertions(+), 34 deletions(-)
254
272
255
--
273
--
256
2.25.1
274
2.25.1
257
275
diff view generated by jsdifflib
1
The name of the local variable "file" of type seq_file defined in the
1
The current kernel behavior is IMA measurements snapshot is taken at
2
ima_dump_measurement_list function is too generic. To better reflect the
2
kexec 'load' and not at kexec 'execute'. IMA log is then carried
3
purpose of the variable, rename it to "ima_kexec_file". This change will
3
over to the new kernel after kexec 'execute'. However, the time gap
4
help improve code readability and maintainability by making the variable's
4
between kexec load and kexec reboot can be very long. During this
5
role more explicit.
5
time window, new events extended into TPM PCRs miss the chance
6
to be carried over to the second kernel.
7
8
To address the above, the following approach is proposed:
9
- Allocate the necessary buffer during the kexec load phase.
10
- Populate this buffer with the IMA measurements during
11
the kexec execute phase.
6
12
7
The variable ima_kexec_file is indeed the memory allocated for copying IMA
13
In the current implementation, a local variable "file" of type seq_file
8
measurement records. The ima_dump_measurement_list function calculates the
14
is used in the API ima_dump_measurement_list() to store the IMA measurements
9
actual memory occupied by the IMA logs and compares it with the allocated
15
to be carried over across kexec system call. To make this buffer accessible
10
memory. If there is enough memory, it copies all IMA measurement records;
16
at kexec 'execute' time, rename it to "ima_kexec_file" before making it
11
otherwise, it does not copy any records, which would result in a failure
17
a file variable to better reflect its purpose.
12
of remote attestation.
18
19
Renaming the local variable "file" of type seq_file defined in the
20
ima_dump_measurement_list function to "ima_kexec_file" will improve code
21
readability and maintainability by making the variable's role more explicit.
13
22
14
Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
23
Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
15
Signed-off-by: steven chen <chenste@linux.microsoft.com>
24
Signed-off-by: steven chen <chenste@linux.microsoft.com>
25
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
16
---
26
---
17
security/integrity/ima/ima_kexec.c | 39 ++++++++++++++++++------------
27
security/integrity/ima/ima_kexec.c | 31 +++++++++++++++---------------
18
1 file changed, 24 insertions(+), 15 deletions(-)
28
1 file changed, 16 insertions(+), 15 deletions(-)
19
29
20
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
30
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
21
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
22
--- a/security/integrity/ima/ima_kexec.c
32
--- a/security/integrity/ima/ima_kexec.c
23
+++ b/security/integrity/ima/ima_kexec.c
33
+++ b/security/integrity/ima/ima_kexec.c
24
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@
25
#include "ima.h"
26
27
#ifdef CONFIG_IMA_KEXEC
28
+/*
29
+ * Copy the measurement list to the allocated memory
30
+ * compare the size of IMA measurement list with the size of the allocated memory
31
+ * if the size of the allocated memory is not less than the size of IMA measurement list
32
+ * copy the measurement list to the allocated memory.
33
+ * else
34
+ * return error
35
+ */
36
static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
35
static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
37
                 unsigned long segment_size)
36
                 unsigned long segment_size)
38
{
37
{
39
+    struct seq_file ima_kexec_file;
38
+    struct seq_file ima_kexec_file;
40
    struct ima_queue_entry *qe;
39
    struct ima_queue_entry *qe;
...
...
diff view generated by jsdifflib
1
In the current implementation, the ima_dump_measurement_list() API is
2
called during the kexec "load" phase, where a buffer is allocated and
3
the measurement records are copied. Due to this, new events added after
4
kexec load but before kexec execute are not carried over to the new kernel
5
during kexec operation
6
7
To allow the buffer allocation and population to be separated into distinct
8
steps, make the function local seq_file "ima_kexec_file" to a file variable.
9
1
Carrying the IMA measurement list across kexec requires allocating a
10
Carrying the IMA measurement list across kexec requires allocating a
2
buffer and copying the measurement records. Separate allocating the
11
buffer and copying the measurement records. Separate allocating the
3
buffer and copying the measurement records into separate functions in
12
buffer and copying the measurement records into separate functions in
4
order to allocate the buffer at kexec 'load' and copy the measurements
13
order to allocate the buffer at kexec 'load' and copy the measurements
5
at kexec 'execute'.
14
at kexec 'execute'.
6
15
7
This patch includes the following changes:
8
- Refactor ima_dump_measurement_list() to move the memory allocation
9
to a separate function ima_alloc_kexec_file_buf() which allocates
10
buffer of size 'kexec_segment_size' at kexec 'load'.
11
- Make the local variable ima_kexec_file in ima_dump_measurement_list()
12
a local static to the file, so that it can be accessed from
13
ima_alloc_kexec_file_buf().
14
- Make necessary changes to the function ima_add_kexec_buffer() to call
15
the above two functions.
16
17
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
16
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
18
Signed-off-by: steven chen <chenste@linux.microsoft.com>
17
Signed-off-by: steven chen <chenste@linux.microsoft.com>
19
---
18
---
20
security/integrity/ima/ima_kexec.c | 67 +++++++++++++++++++++++++-----
19
security/integrity/ima/ima_kexec.c | 46 +++++++++++++++++++++++-------
21
1 file changed, 56 insertions(+), 11 deletions(-)
20
1 file changed, 35 insertions(+), 11 deletions(-)
22
21
23
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
22
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
24
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
25
--- a/security/integrity/ima/ima_kexec.c
24
--- a/security/integrity/ima/ima_kexec.c
26
+++ b/security/integrity/ima/ima_kexec.c
25
+++ b/security/integrity/ima/ima_kexec.c
27
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
28
#include "ima.h"
27
#include "ima.h"
29
28
30
#ifdef CONFIG_IMA_KEXEC
29
#ifdef CONFIG_IMA_KEXEC
31
+static struct seq_file ima_kexec_file;
30
+static struct seq_file ima_kexec_file;
32
+
31
+
33
+static void ima_reset_kexec_file(struct seq_file *sf)
32
+static void ima_free_kexec_file_buf(struct seq_file *sf)
34
+{
33
+{
34
+    vfree(sf->buf);
35
+    sf->buf = NULL;
35
+    sf->buf = NULL;
36
+    sf->size = 0;
36
+    sf->size = 0;
37
+    sf->read_pos = 0;
37
+    sf->read_pos = 0;
38
+    sf->count = 0;
38
+    sf->count = 0;
39
+}
39
+}
40
+
40
+
41
+static void ima_free_kexec_file_buf(struct seq_file *sf)
42
+{
43
+    vfree(sf->buf);
44
+    ima_reset_kexec_file(sf);
45
+}
46
+
47
+static int ima_alloc_kexec_file_buf(size_t segment_size)
41
+static int ima_alloc_kexec_file_buf(size_t segment_size)
48
+{
42
+{
49
+    /*
50
+     * kexec 'load' may be called multiple times.
51
+     * Free and realloc the buffer only if the segment_size is
52
+     * changed from the previous kexec 'load' call.
53
+     */
54
+    if (ima_kexec_file.buf && ima_kexec_file.size == segment_size)
55
+        goto out;
56
+
57
+    ima_free_kexec_file_buf(&ima_kexec_file);
43
+    ima_free_kexec_file_buf(&ima_kexec_file);
58
+
44
+
59
+    /* segment size can't change between kexec load and execute */
45
+    /* segment size can't change between kexec load and execute */
60
+    ima_kexec_file.buf = vmalloc(segment_size);
46
+    ima_kexec_file.buf = vmalloc(segment_size);
61
+    if (!ima_kexec_file.buf)
47
+    if (!ima_kexec_file.buf)
62
+        return -ENOMEM;
48
+        return -ENOMEM;
63
+
49
+
64
+    ima_kexec_file.size = segment_size;
50
+    ima_kexec_file.size = segment_size;
65
+
66
+out:
67
+    ima_kexec_file.read_pos = 0;
51
+    ima_kexec_file.read_pos = 0;
68
+    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
52
+    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
69
+
53
+
70
+    return 0;
54
+    return 0;
71
+}
55
+}
72
+
56
+
73
/*
74
* Copy the measurement list to the allocated memory
75
* compare the size of IMA measurement list with the size of the allocated memory
76
@@ -XXX,XX +XXX,XX @@
77
static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
57
static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
78
                 unsigned long segment_size)
58
                 unsigned long segment_size)
79
{
59
{
80
-    struct seq_file ima_kexec_file;
60
-    struct seq_file ima_kexec_file;
81
    struct ima_queue_entry *qe;
61
    struct ima_queue_entry *qe;
...
...
119
+    }
99
+    }
120
+
100
+
121
    ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
101
    ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
122
                 kexec_segment_size);
102
                 kexec_segment_size);
123
    if (!kexec_buffer) {
103
    if (!kexec_buffer) {
124
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
125
    image->ima_buffer_size = kexec_segment_size;
126
    image->ima_buffer = kexec_buffer;
127
128
+    /*
129
+     * kexec owns kexec_buffer after kexec_add_buffer() is called
130
+     * and it will vfree() that buffer.
131
+     */
132
+    ima_reset_kexec_file(&ima_kexec_file);
133
+
134
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
135
         kbuf.mem);
136
}
137
--
104
--
138
2.25.1
105
2.25.1
diff view generated by jsdifflib
1
Currently, the kernel behavior during kexec load is to fetch the IMA
1
Currently, the kernel behavior during kexec load is to fetch the IMA
2
measurements log from TPM PCRs and store it in a buffer. When a kexec
2
measurements logs and store logs in kernel memory. When a kexec reboot is
3
reboot is triggered, this stored log buffer is carried over to the second
3
triggered, these stored logs in the kernel memory are carried over to the
4
kernel. However, the time gap between kexec load and kexec reboot can be
4
second kernel. However, the time gap between kexec load and kexec reboot
5
very long. During this time window, new events extended into TPM PCRs miss
5
can be very long. During this time window, new events extended into TPM
6
the chance to be carried over to the second kernel. This results in a
6
PCRs miss the chance to be carried over to the second kernel. This results
7
mismatch between TPM PCR quotes and the actual IMA measurements list after
7
in a mismatch between TPM PCR quotes and the actual IMA measurements list
8
kexec reboot, leading to remote attestation failure.
8
after kexec reboot, leading to remote attestation failure.
9
9
10
To solve this problem, the new design defers reading TPM PCRs content into
10
To solve this problem, the new design defers reading the IMA measurements
11
the kexec buffer to the kexec reboot phase, while still allocating the
11
logs into the kexec buffer to the kexec reboot phase, while still allocating
12
necessary buffer at kexec load time because it is not appropriate to
12
the necessary buffer at kexec load time because it is not appropriate to
13
allocate memory at the kexec reboot moment.
13
allocate memory at the kexec reboot moment.
14
14
15
The content of memory segments carried over to the new kernel during the
15
The content of memory segments carried over to the new kernel during the
16
kexec system call can be changed at the kexec 'execute' stage, but the size
16
kexec system call can be changed at the kexec 'execute' stage, but the size
17
of the memory segments cannot be changed at the kexec 'execute' stage.
17
of the memory segments cannot be changed at the kexec 'execute' stage.
...
...
39
Cc: Eric Biederman <ebiederm@xmission.com>
39
Cc: Eric Biederman <ebiederm@xmission.com>
40
Cc: Baoquan He <bhe@redhat.com>
40
Cc: Baoquan He <bhe@redhat.com>
41
Cc: Vivek Goyal <vgoyal@redhat.com>
41
Cc: Vivek Goyal <vgoyal@redhat.com>
42
Cc: Dave Young <dyoung@redhat.com>
42
Cc: Dave Young <dyoung@redhat.com>
43
Signed-off-by: steven chen <chenste@linux.microsoft.com>
43
Signed-off-by: steven chen <chenste@linux.microsoft.com>
44
Acked-by: Baoquan He <bhe@redhat.com>
44
---
45
---
45
include/linux/kexec.h | 6 +++++
46
include/linux/kexec.h | 6 +++++
46
kernel/kexec_core.c | 54 +++++++++++++++++++++++++++++++++++++++++++
47
kernel/kexec_core.c | 54 +++++++++++++++++++++++++++++++++++++++++++
47
2 files changed, 60 insertions(+)
48
2 files changed, 60 insertions(+)
48
49
...
...
diff view generated by jsdifflib
1
The kexec_calculate_store_digests() function calculates and stores the
2
digest of the segment during the kexec_file_load syscall, where the
3
IMA segment is also allocated.
4
1
With this series, the IMA segment will be updated with the measurement
5
With this series, the IMA segment will be updated with the measurement
2
log at the kexec execute stage when a soft reboot is initiated.
6
log at the kexec execute stage when a soft reboot is initiated.
3
Therefore, the digests should be updated for the IMA segment in the
7
Therefore, the digests should be updated for the IMA segment in the
4
normal case.
8
normal case.
5
9
...
...
33
Cc: Vivek Goyal <vgoyal@redhat.com>
37
Cc: Vivek Goyal <vgoyal@redhat.com>
34
Cc: Dave Young <dyoung@redhat.com>
38
Cc: Dave Young <dyoung@redhat.com>
35
Signed-off-by: steven chen <chenste@linux.microsoft.com>
39
Signed-off-by: steven chen <chenste@linux.microsoft.com>
36
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
40
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
37
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
41
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
42
Acked-by: Baoquan He <bhe@redhat.com>
38
---
43
---
39
include/linux/kexec.h | 3 +++
44
include/linux/kexec.h | 3 +++
40
kernel/kexec_file.c | 22 ++++++++++++++++++++++
45
kernel/kexec_file.c | 22 ++++++++++++++++++++++
41
security/integrity/ima/ima_kexec.c | 3 +++
46
security/integrity/ima/ima_kexec.c | 3 +++
42
3 files changed, 28 insertions(+)
47
3 files changed, 28 insertions(+)
...
...
112
    image->ima_buffer_size = kexec_segment_size;
117
    image->ima_buffer_size = kexec_segment_size;
113
    image->ima_buffer = kexec_buffer;
118
    image->ima_buffer = kexec_buffer;
114
+    image->ima_segment_index = image->nr_segments - 1;
119
+    image->ima_segment_index = image->nr_segments - 1;
115
+    image->is_ima_segment_index_set = true;
120
+    image->is_ima_segment_index_set = true;
116
121
117
    /*
122
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
118
     * kexec owns kexec_buffer after kexec_add_buffer() is called
123
         kbuf.mem);
119
--
124
--
120
2.25.1
125
2.25.1
diff view generated by jsdifflib
...
...
12
Kernel image has been loaded for kexec. ima_kexec_post_load() maps the
12
Kernel image has been loaded for kexec. ima_kexec_post_load() maps the
13
IMA buffer to a segment in the newly loaded Kernel. It also registers
13
IMA buffer to a segment in the newly loaded Kernel. It also registers
14
the reboot notifier_block to trigger ima_update_kexec_buffer() at
14
the reboot notifier_block to trigger ima_update_kexec_buffer() at
15
kexec 'execute'.
15
kexec 'execute'.
16
16
17
Set the priority of register_reboot_notifier to INT_MIN to ensure that the
18
IMA log copy operation will happen at the end of the operation chain, which
19
is crucial for maintaining the integrity of the logs
20
17
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
21
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
18
Cc: Eric Biederman <ebiederm@xmission.com>
22
Cc: Eric Biederman <ebiederm@xmission.com>
19
Cc: Baoquan He <bhe@redhat.com>
23
Cc: Baoquan He <bhe@redhat.com>
20
Cc: Vivek Goyal <vgoyal@redhat.com>
24
Cc: Vivek Goyal <vgoyal@redhat.com>
21
Cc: Dave Young <dyoung@redhat.com>
25
Cc: Dave Young <dyoung@redhat.com>
22
Signed-off-by: steven chen <chenste@linux.microsoft.com>
26
Signed-off-by: steven chen <chenste@linux.microsoft.com>
23
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
27
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
24
Signed-off-by: steven chen <chenste@linux.microsoft.com>
25
---
28
---
26
include/linux/ima.h | 3 ++
29
include/linux/ima.h | 3 ++
27
security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++
30
security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++
28
2 files changed, 50 insertions(+)
31
2 files changed, 50 insertions(+)
29
32
...
...
56
#ifdef CONFIG_IMA_KEXEC
59
#ifdef CONFIG_IMA_KEXEC
57
+static bool ima_kexec_update_registered;
60
+static bool ima_kexec_update_registered;
58
static struct seq_file ima_kexec_file;
61
static struct seq_file ima_kexec_file;
59
+static void *ima_kexec_buffer;
62
+static void *ima_kexec_buffer;
60
63
61
static void ima_reset_kexec_file(struct seq_file *sf)
64
static void ima_free_kexec_file_buf(struct seq_file *sf)
62
{
65
{
63
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
66
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
64
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
67
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
65
         kbuf.mem);
68
         kbuf.mem);
66
}
69
}
...
...
74
+    return NOTIFY_OK;
77
+    return NOTIFY_OK;
75
+}
78
+}
76
+
79
+
77
+static struct notifier_block update_buffer_nb = {
80
+static struct notifier_block update_buffer_nb = {
78
+    .notifier_call = ima_update_kexec_buffer,
81
+    .notifier_call = ima_update_kexec_buffer,
79
+    .priority = 1,
82
+    .priority = INT_MIN
80
+};
83
+};
81
+
84
+
82
+/*
85
+/*
83
+ * Create a mapping for the source pages that contain the IMA buffer
86
+ * Create a mapping for the source pages that contain the IMA buffer
84
+ * so we can update it later.
87
+ * so we can update it later.
...
...
diff view generated by jsdifflib
1
ima_dump_measurement_list() is called during kexec 'load', which may
1
ima_dump_measurement_list() is called during kexec 'load', which may
2
result in loss of IMA measurements during kexec soft reboot. Due to
2
result in loss of IMA measurements during kexec soft reboot. Due to
3
missed measurements that only occurred after kexec 'load', this function
3
missed measurements that only occurred after kexec 'load', this function
4
needs to be called during kexec 'execute'.
4
needs to be called during kexec 'execute'.
5
5
6
This patch includes the following changes:
6
Make the kexec_segment_size variable a local static variable within the
7
- Implement kimage_file_post_load() function to be invoked after the new
7
file, so it can be accessed during both kexec 'load' and 'execute'.
8
kernel image has been loaded for kexec.
8
9
- Call kimage_file_post_load() from kexec_file_load() syscall only for
9
Implement the kexec_post_load() function to be invoked after the new kernel
10
kexec soft reboot scenarios and not for KEXEC_FILE_ON_CRASH. It will
10
image has been loaded for kexec. Instead of calling machine_kexec_post_load()
11
map the IMA segment, and register reboot notifier for the function
11
directly from the kexec_file_load() syscall, call kexec_post_load(), which in
12
ima_update_kexec_buffer() which would copy the IMA log at kexec soft
12
turn calls machine_kexec_post_load() to maintain the original image processing.
13
reboot.
13
14
- Make kexec_segment_size variable local static to the file so that it
14
Invoke ima_kexec_post_load() within the kexec_post_load() API only for kexec
15
becomes accessible both during kexec 'load' and 'execute'.
15
soft reboot scenarios, excluding KEXEC_FILE_ON_CRASH.
16
- Move ima_dump_measurement_list() call from ima_add_kexec_buffer()
16
17
to ima_update_kexec_buffer().
17
Register a reboot notifier for the ima_update_kexec_buffer() API within
18
- Copy the measurement list as much as possible.
18
ima_kexec_post_load() to ensure it is called upon receiving a reboot
19
- Remove ima_reset_kexec_file() call from ima_add_kexec_buffer(), now
19
notification.
20
that the buffer is being copied at kexec 'execute', and resetting the
20
21
file at kexec 'load' would corrupt the buffer.
21
Move the ima_dump_measurement_list() call from ima_add_kexec_buffer() to
22
ima_update_kexec_buffer() to copy the IMA log at the kexec 'execute' stage.
23
24
When there is insufficient memory to copy all the measurement logs, copy as
25
much of the measurement list as possible.
22
26
23
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
27
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
24
Cc: Eric Biederman <ebiederm@xmission.com>
28
Cc: Eric Biederman <ebiederm@xmission.com>
25
Cc: Baoquan He <bhe@redhat.com>
29
Cc: Baoquan He <bhe@redhat.com>
26
Cc: Vivek Goyal <vgoyal@redhat.com>
30
Cc: Vivek Goyal <vgoyal@redhat.com>
27
Cc: Dave Young <dyoung@redhat.com>
31
Cc: Dave Young <dyoung@redhat.com>
28
Signed-off-by: steven chen <chenste@linux.microsoft.com>
32
Signed-off-by: steven chen <chenste@linux.microsoft.com>
29
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
33
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
30
---
34
---
31
kernel/kexec_file.c | 10 ++++++
35
kernel/kexec_file.c | 11 +++++++-
32
security/integrity/ima/ima_kexec.c | 51 ++++++++++++++++++------------
36
security/integrity/ima/ima_kexec.c | 43 ++++++++++++++++++++----------
33
2 files changed, 40 insertions(+), 21 deletions(-)
37
2 files changed, 39 insertions(+), 15 deletions(-)
34
38
35
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
39
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
36
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
37
--- a/kernel/kexec_file.c
41
--- a/kernel/kexec_file.c
38
+++ b/kernel/kexec_file.c
42
+++ b/kernel/kexec_file.c
39
@@ -XXX,XX +XXX,XX @@ kimage_validate_signature(struct kimage *image)
43
@@ -XXX,XX +XXX,XX @@ kimage_validate_signature(struct kimage *image)
40
}
44
}
41
#endif
45
#endif
42
46
43
+static void kimage_file_post_load(struct kimage *image)
47
+static int kexec_post_load(struct kimage *image, unsigned long flags)
44
+{
48
+{
45
+#ifdef CONFIG_IMA_KEXEC
49
+#ifdef CONFIG_IMA_KEXEC
46
+    ima_kexec_post_load(image);
50
+    if (!(flags & KEXEC_FILE_ON_CRASH))
51
+        ima_kexec_post_load(image);
47
+#endif
52
+#endif
53
+    return machine_kexec_post_load(image);
48
+}
54
+}
49
+
55
+
50
/*
56
/*
51
* In file mode list of segments is prepared by kernel. Copy relevant
57
* In file mode list of segments is prepared by kernel. Copy relevant
52
* data from user space, do error checking, prepare segment list
58
* data from user space, do error checking, prepare segment list
53
@@ -XXX,XX +XXX,XX @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
59
@@ -XXX,XX +XXX,XX @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
54
60
55
    kimage_terminate(image);
61
    kimage_terminate(image);
56
62
57
+    if (!(flags & KEXEC_FILE_ON_CRASH))
63
-    ret = machine_kexec_post_load(image);
58
+        kimage_file_post_load(image);
64
+    ret = kexec_post_load(image, flags);
59
+
60
    ret = machine_kexec_post_load(image);
61
    if (ret)
65
    if (ret)
62
        goto out;
66
        goto out;
67
63
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
68
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
64
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
65
--- a/security/integrity/ima/ima_kexec.c
70
--- a/security/integrity/ima/ima_kexec.c
66
+++ b/security/integrity/ima/ima_kexec.c
71
+++ b/security/integrity/ima/ima_kexec.c
67
@@ -XXX,XX +XXX,XX @@
72
@@ -XXX,XX +XXX,XX @@
68
#ifdef CONFIG_IMA_KEXEC
73
#ifdef CONFIG_IMA_KEXEC
69
static bool ima_kexec_update_registered;
74
static bool ima_kexec_update_registered;
70
static struct seq_file ima_kexec_file;
75
static struct seq_file ima_kexec_file;
71
+static size_t kexec_segment_size;
76
+static size_t kexec_segment_size;
72
static void *ima_kexec_buffer;
77
static void *ima_kexec_buffer;
73
78
74
static void ima_reset_kexec_file(struct seq_file *sf)
79
static void ima_free_kexec_file_buf(struct seq_file *sf)
75
@@ -XXX,XX +XXX,XX @@ static int ima_alloc_kexec_file_buf(size_t segment_size)
76
* if the size of the allocated memory is not less than the size of IMA measurement list
77
* copy the measurement list to the allocated memory.
78
* else
79
- * return error
80
+ * copy the measurement list as much as possible.
81
*/
82
static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
83
                 unsigned long segment_size)
84
@@ -XXX,XX +XXX,XX @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
80
@@ -XXX,XX +XXX,XX @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
85
        }
81
        }
86
    }
82
    }
87
83
88
-    if (ret < 0)
84
-    if (ret < 0)
...
...
123
-    }
119
-    }
124
-
120
-
125
    kbuf.buffer = kexec_buffer;
121
    kbuf.buffer = kexec_buffer;
126
    kbuf.bufsz = kexec_buffer_size;
122
    kbuf.bufsz = kexec_buffer_size;
127
    kbuf.memsz = kexec_segment_size;
123
    kbuf.memsz = kexec_segment_size;
128
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
129
    image->ima_segment_index = image->nr_segments - 1;
130
    image->is_ima_segment_index_set = true;
131
132
-    /*
133
-     * kexec owns kexec_buffer after kexec_add_buffer() is called
134
-     * and it will vfree() that buffer.
135
-     */
136
-    ima_reset_kexec_file(&ima_kexec_file);
137
-
138
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
139
         kbuf.mem);
140
}
141
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
124
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
142
static int ima_update_kexec_buffer(struct notifier_block *self,
125
static int ima_update_kexec_buffer(struct notifier_block *self,
143
                 unsigned long action, void *data)
126
                 unsigned long action, void *data)
144
{
127
{
145
-    return NOTIFY_OK;
128
-    return NOTIFY_OK;
...
...
diff view generated by jsdifflib
New patch
1
kexec 'load' may be called multiple times. Free and realloc the buffer
2
only if the segment_size is changed from the previous kexec 'load' call.
1
3
4
Signed-off-by: steven chen <chenste@linux.microsoft.com>
5
---
6
security/integrity/ima/ima_kexec.c | 10 ++++++++++
7
1 file changed, 10 insertions(+)
8
9
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/security/integrity/ima/ima_kexec.c
12
+++ b/security/integrity/ima/ima_kexec.c
13
@@ -XXX,XX +XXX,XX @@ static void ima_free_kexec_file_buf(struct seq_file *sf)
14
15
static int ima_alloc_kexec_file_buf(size_t segment_size)
16
{
17
+    /*
18
+     * kexec 'load' may be called multiple times.
19
+     * Free and realloc the buffer only if the segment_size is
20
+     * changed from the previous kexec 'load' call.
21
+     */
22
+    if (ima_kexec_file.buf && ima_kexec_file.size == segment_size)
23
+        goto out;
24
+
25
    ima_free_kexec_file_buf(&ima_kexec_file);
26
27
    /* segment size can't change between kexec load and execute */
28
@@ -XXX,XX +XXX,XX @@ static int ima_alloc_kexec_file_buf(size_t segment_size)
29
        return -ENOMEM;
30
31
    ima_kexec_file.size = segment_size;
32
+
33
+out:
34
    ima_kexec_file.read_pos = 0;
35
    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
36
37
--
38
2.25.1
diff view generated by jsdifflib
1
The extra memory allocated for carrying the IMA measurement list across
1
The extra memory allocated for carrying the IMA measurement list across
2
kexec is hard-coded as half a PAGE. Make it configurable.
2
kexec is hard-coded as half a PAGE. Make it configurable.
3
3
4
Define a Kconfig option, IMA_KEXEC_EXTRA_MEMORY_KB, to configure the
4
Define a Kconfig option, IMA_KEXEC_EXTRA_MEMORY_KB, to configure the
5
extra memory (in kb) to be allocated for IMA measurements added during
5
extra memory (in kb) to be allocated for IMA measurements added during
6
kexec soft reboot. Ensure the default value of the option is set such
6
kexec soft reboot. Ensure the default value of the option is set such
7
that extra half a page of memory for additional measurements is allocated
7
that extra half a page of memory for additional measurements is allocated
8
for the additional measurements.
8
for the additional measurements.
9
9
10
Update ima_add_kexec_buffer() function to allocate memory based on the
10
Update ima_add_kexec_buffer() function to allocate memory based on the
11
Kconfig option value, rather than the currently hard-coded one.
11
Kconfig option value, rather than the currently hard-coded one.
12
12
13
Suggested-by: Stefan Berger <stefanb@linux.ibm.com>
13
Suggested-by: Stefan Berger <stefanb@linux.ibm.com>
14
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
14
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
15
Signed-off-by: steven chen <chenste@linux.microsoft.com>
15
Signed-off-by: steven chen <chenste@linux.microsoft.com>
16
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
16
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
17
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
17
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
18
---
18
---
19
security/integrity/ima/Kconfig | 10 ++++++++++
19
security/integrity/ima/Kconfig | 10 ++++++++++
20
security/integrity/ima/ima_kexec.c | 16 +++++++++++-----
20
security/integrity/ima/ima_kexec.c | 16 +++++++++++-----
21
2 files changed, 21 insertions(+), 5 deletions(-)
21
2 files changed, 21 insertions(+), 5 deletions(-)
22
22
23
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
23
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
24
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
25
--- a/security/integrity/ima/Kconfig
25
--- a/security/integrity/ima/Kconfig
26
+++ b/security/integrity/ima/Kconfig
26
+++ b/security/integrity/ima/Kconfig
27
@@ -XXX,XX +XXX,XX @@ config IMA_DISABLE_HTABLE
27
@@ -XXX,XX +XXX,XX @@ config IMA_DISABLE_HTABLE
28
    help
28
    help
29
     This option disables htable to allow measurement of duplicate records.
29
     This option disables htable to allow measurement of duplicate records.
30
30
31
+config IMA_KEXEC_EXTRA_MEMORY_KB
31
+config IMA_KEXEC_EXTRA_MEMORY_KB
32
+    int "Extra memory for IMA measurements added during kexec soft reboot"
32
+    int "Extra memory for IMA measurements added during kexec soft reboot"
33
+    depends on IMA_KEXEC
33
+    depends on IMA_KEXEC
34
+    default 0
34
+    default 0
35
+    help
35
+    help
36
+     IMA_KEXEC_EXTRA_MEMORY_KB determines the extra memory to be
36
+     IMA_KEXEC_EXTRA_MEMORY_KB determines the extra memory to be
37
+     allocated (in kb) for IMA measurements added during kexec soft reboot.
37
+     allocated (in kb) for IMA measurements added during kexec soft reboot.
38
+     If set to the default value of 0, an extra half page of memory for those
38
+     If set to the default value of 0, an extra half page of memory for those
39
+     additional measurements will be allocated.
39
+     additional measurements will be allocated.
40
+
40
+
41
endif
41
endif
42
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
42
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
43
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
44
--- a/security/integrity/ima/ima_kexec.c
44
--- a/security/integrity/ima/ima_kexec.c
45
+++ b/security/integrity/ima/ima_kexec.c
45
+++ b/security/integrity/ima/ima_kexec.c
46
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
46
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
47
                 .buf_min = 0, .buf_max = ULONG_MAX,
47
                 .buf_min = 0, .buf_max = ULONG_MAX,
48
                 .top_down = true };
48
                 .top_down = true };
49
    unsigned long binary_runtime_size;
49
    unsigned long binary_runtime_size;
50
+    unsigned long extra_memory;
50
+    unsigned long extra_memory;
51
51
52
    /* use more understandable variable names than defined in kbuf */
52
    /* use more understandable variable names than defined in kbuf */
53
    size_t kexec_buffer_size = 0;
53
    size_t kexec_buffer_size = 0;
54
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
54
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
55
    int ret;
55
    int ret;
56
56
57
    /*
57
    /*
58
-     * Reserve an extra half page of memory for additional measurements
58
-     * Reserve an extra half page of memory for additional measurements
59
-     * added during the kexec load.
59
-     * added during the kexec load.
60
+     * Reserve extra memory for measurements added during kexec.
60
+     * Reserve extra memory for measurements added during kexec.
61
     */
61
     */
62
-    binary_runtime_size = ima_get_binary_runtime_size();
62
-    binary_runtime_size = ima_get_binary_runtime_size();
63
+    if (CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB <= 0)
63
+    if (CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB <= 0)
64
+        extra_memory = PAGE_SIZE / 2;
64
+        extra_memory = PAGE_SIZE / 2;
65
+    else
65
+    else
66
+        extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
66
+        extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
67
+
67
+
68
+    binary_runtime_size = ima_get_binary_runtime_size() + extra_memory;
68
+    binary_runtime_size = ima_get_binary_runtime_size() + extra_memory;
69
+
69
+
70
    if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
70
    if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
71
        kexec_segment_size = ULONG_MAX;
71
        kexec_segment_size = ULONG_MAX;
72
    else
72
    else
73
-        kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
73
-        kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
74
-                     PAGE_SIZE / 2, PAGE_SIZE);
74
-                     PAGE_SIZE / 2, PAGE_SIZE);
75
+        kexec_segment_size = ALIGN(binary_runtime_size, PAGE_SIZE);
75
+        kexec_segment_size = ALIGN(binary_runtime_size, PAGE_SIZE);
76
+
76
+
77
    if ((kexec_segment_size == ULONG_MAX) ||
77
    if ((kexec_segment_size == ULONG_MAX) ||
78
     ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) {
78
     ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) {
79
        pr_err("Binary measurement list too large.\n");
79
        pr_err("Binary measurement list too large.\n");
80
--
80
--
81
2.25.1
81
2.25.1
diff view generated by jsdifflib
...
...
70
+
70
+
71
static bool ima_kexec_update_registered;
71
static bool ima_kexec_update_registered;
72
static struct seq_file ima_kexec_file;
72
static struct seq_file ima_kexec_file;
73
static size_t kexec_segment_size;
73
static size_t kexec_segment_size;
74
@@ -XXX,XX +XXX,XX @@ static void ima_free_kexec_file_buf(struct seq_file *sf)
74
@@ -XXX,XX +XXX,XX @@ static void ima_free_kexec_file_buf(struct seq_file *sf)
75
    ima_reset_kexec_file(sf);
75
    sf->count = 0;
76
}
76
}
77
77
78
+void ima_measure_kexec_event(const char *event_name)
78
+void ima_measure_kexec_event(const char *event_name)
79
+{
79
+{
80
+    char ima_kexec_event[IMA_KEXEC_EVENT_LEN];
80
+    char ima_kexec_event[IMA_KEXEC_EVENT_LEN];
...
...
diff view generated by jsdifflib