1
The current kernel behavior is IMA measurements snapshot is taken at
1
The current kernel behavior is IMA measurements snapshot is taken at
2
kexec 'load' and not at kexec 'execute'. IMA log is then carried
2
kexec 'load' and not at kexec 'execute'. IMA log is then carried
3
over to the new kernel after kexec 'execute'.
3
over to the new kernel after kexec 'execute'.
4
4
5
New events can be measured during/after the IMA log snapshot at kexec
5
Currently, the kernel behavior during kexec load is to fetch the IMA
6
'load' and before the system boots to the new kernel. In this scenario,
6
measurements log from TPM PCRs and store it in a buffer. When a kexec
7
the TPM PCRs are extended with these events, but they are not carried
7
reboot is triggered, this stored log buffer is carried over to the second
8
over to the new kernel after kexec soft reboot since the snapshot is
8
kernel. However, the time gap between kexec load and kexec reboot can be
9
already taken. This results in mismatch between TPM PCR quotes and the
9
very long. During this time window, new events extended into TPM PCRs miss
10
actual IMA measurements list after kexec soft reboot, which in turn
10
the chance to be carried over to the second kernel. This results in
11
results in remote attestation failure.
11
mismatch between TPM PCR quotes and the actual IMA measurements list after
12
kexec soft reboot, which in turn results in remote attestation failure.
12
13
13
To solve this problem -
14
To solve this problem -
14
- allocate the necessary buffer at kexec 'load' time,
15
- allocate the necessary buffer at kexec 'load' time,
15
- populate the buffer with the IMA measurements at kexec 'execute' time,
16
- populate the buffer with the IMA measurements at kexec 'execute' time,
16
- and measure two new IMA events 'kexec_load' and 'kexec_execute' as
17
- and measure two new IMA events 'kexec_load' and 'kexec_execute' as
...
...
19
The solution details include:
20
The solution details include:
20
- refactoring the existing code to allocate a buffer to hold IMA
21
- refactoring the existing code to allocate a buffer to hold IMA
21
measurements at kexec 'load', and dump the measurements at kexec
22
measurements at kexec 'load', and dump the measurements at kexec
22
'execute'
23
'execute'
23
24
24
- IMA functionality to suspend and resume measurements as needed during
25
buffer copy at kexec 'execute',
26
27
- kexec functionality for mapping the segments from the current kernel
25
- kexec functionality for mapping the segments from the current kernel
28
to the subsequent one,
26
to the subsequent one,
29
27
30
- necessary changes to the kexec_file_load syscall, enabling it to call
28
- necessary changes to the kexec_file_load syscall, enabling it to call
31
the ima functions,
29
the ima functions,
32
30
33
- registering a reboot notifier which gets called during kexec
31
- registering a reboot notifier which gets called during kexec 'execute',
34
'execute',
35
32
36
- introducing a new Kconfig option to configure the extra memory to be
33
- introducing a new Kconfig option to configure the extra memory to be
37
allocated for passing IMA log from the current Kernel to the next,
34
allocated for passing IMA log from the current Kernel to the next,
38
35
39
- introducing two new events to be measured by IMA during kexec, to
36
- introducing two new events to be measured by IMA during kexec, to
40
help diagnose if the IMA log was copied fully or partially, from the
37
help diagnose if the IMA log was copied fully or partially, from the
41
current Kernel to the next,
38
current Kernel to the next,
42
39
43
- excluding IMA segment while calculating and storing digest in function
40
- excluding IMA segment while calculating and storing digest in function
44
kexec_calculate_store_digests(), since IMA segment can be modified
41
kexec_calculate_store_digests(), since IMA segment can be modified
45
after the digest is computed during kexec 'load'. This will ensure
42
after the digest is computed during kexec 'load'. This will ensure
46
that the segment is not added to the 'purgatory_sha_regions', and thus
43
that the segment is not added to the 'purgatory_sha_regions', and thus
...
...
60
57
61
V5 of this series is available here[7] for reference.
58
V5 of this series is available here[7] for reference.
62
59
63
V6 of this series is available here[8] for reference.
60
V6 of this series is available here[8] for reference.
64
61
62
V7 of this series is available here[9] for reference.
63
64
V8 of this series is available here[10] for reference.
65
66
V9 of this series is available here[11] for reference.
67
68
V10 of this series is available here[12] for reference.
69
65
References:
70
References:
66
-----------
71
-----------
67
72
68
[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
69
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/
...
...
86
[7] [PATCH v5 0/8] ima: kexec: measure events between kexec load and execute
91
[7] [PATCH v5 0/8] ima: kexec: measure events between kexec load and execute
87
https://lore.kernel.org/all/20240214153827.1087657-1-tusharsu@linux.microsoft.com/
92
https://lore.kernel.org/all/20240214153827.1087657-1-tusharsu@linux.microsoft.com/
88
93
89
[8] [PATCH v6 0/7] ima: kexec: measure events between kexec load and execute
94
[8] [PATCH v6 0/7] ima: kexec: measure events between kexec load and execute
90
https://lore.kernel.org/all/20250124225547.22684-1-chenste@linux.microsoft.com/
95
https://lore.kernel.org/all/20250124225547.22684-1-chenste@linux.microsoft.com/
96
97
[9] [PATCH v7 0/7] ima: kexec: measure events between kexec load and execute
98
https://lore.kernel.org/all/20250203232033.64123-1-chenste@linux.microsoft.com/
99
100
[10] [PATCH v8 0/7] ima: kexec: measure events between kexec load and execute
101
https://lore.kernel.org/all/20250218225502.747963-1-chenste@linux.microsoft.com/
102
103
[11] [PATCH v9 0/7] ima: kexec: measure events between kexec load and execute
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.
119
120
Change Log v10:
121
- Incorporated feedback from the community (Mimi Zohar, Baoquan He, and
122
kernel test robot) on v9 of this series[11].
123
- [PATCH V9 1/7] was splited into two [PATCH V10 1/8] and [PATCH V10 2/8].
124
Per Mimi comment on [PATCH V9 1/7].
125
- Verified all the patches are bisect-safe by booting into each
126
patch and verifying multiple kexec 'load' operations work,
127
and also verifying kexec soft reboot works, and IMA log gets
128
carried over for each patch.
129
130
Change Log v9:
131
- Incorporated feedback from the community (Stefan Berger, Mimi Zohar,
132
and kernel test robot) on v8 of this series[10].
133
- Rebased the patch series to mainline 6.14.0-rc3.
134
- Verified all the patches are bisect-safe by booting into each
135
patch and verifying multiple kexec 'load' operations work,
136
and also verifying kexec soft reboot works, and IMA log gets
137
carried over for each patch.
138
139
Change Log v8:
140
- Incorporated feedback from the community (Stefan Berger, Mimi Zohar)
141
on v7 of this series[9].
142
- Rebased the patch series to mainline 6.14.0-rc1.
143
- Verified all the patches are bisect-safe by booting into each
144
patch and verifying multiple kexec 'load' operations work,
145
and also verifying kexec soft reboot works, and IMA log gets
146
carried over for each patch.
91
147
92
Change Log v7:
148
Change Log v7:
93
- Incorporated feedback from the community (Stefan Berger, Tyler Hicks)
149
- Incorporated feedback from the community (Stefan Berger, Tyler Hicks)
94
on v6 of this series[8].
150
on v6 of this series[8].
95
- Verified all the patches are bisect-safe by booting into each
151
- Verified all the patches are bisect-safe by booting into each
...
...
190
- Refactored patches to ensure no warnings during individual patch
246
- Refactored patches to ensure no warnings during individual patch
191
compilation.
247
compilation.
192
- Used virt_to_page instead of phys_to_page.
248
- Used virt_to_page instead of phys_to_page.
193
- Updated patch descriptions as necessary.
249
- Updated patch descriptions as necessary.
194
250
195
steven chen (7):
251
196
ima: define and call ima_alloc_kexec_file_buf
252
steven chen (9):
253
ima: rename variable the set_file "file" to "ima_kexec_file"
254
ima: define and call ima_alloc_kexec_file_buf()
197
kexec: define functions to map and unmap segments
255
kexec: define functions to map and unmap segments
198
ima: kexec: skip IMA segment validation after kexec soft reboot
256
ima: kexec: skip IMA segment validation after kexec soft reboot
199
ima: kexec: define functions to copy IMA log at soft boot
257
ima: kexec: define functions to copy IMA log at soft boot
200
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
201
ima: make the kexec extra memory configurable
260
ima: make the kexec extra memory configurable
202
ima: measure kexec load and exec events as critical data
261
ima: measure kexec load and exec events as critical data
203
262
204
include/linux/ima.h | 3 +
263
include/linux/ima.h | 3 +
205
include/linux/kexec.h | 10 ++
264
include/linux/kexec.h | 9 ++
206
kernel/kexec_core.c | 54 ++++++++
265
kernel/kexec_core.c | 54 ++++++++
207
kernel/kexec_file.c | 31 +++++
266
kernel/kexec_file.c | 33 ++++-
208
security/integrity/ima/Kconfig | 10 ++
267
security/integrity/ima/Kconfig | 10 ++
209
security/integrity/ima/ima.h | 1 +
268
security/integrity/ima/ima.h | 6 +
210
security/integrity/ima/ima_kexec.c | 208 ++++++++++++++++++++++++-----
269
security/integrity/ima/ima_kexec.c | 193 ++++++++++++++++++++++++-----
211
security/integrity/ima/ima_queue.c | 4 +-
270
security/integrity/ima/ima_queue.c | 5 +
212
8 files changed, 284 insertions(+), 37 deletions(-)
271
8 files changed, 279 insertions(+), 34 deletions(-)
213
272
214
--
273
--
215
2.25.1
274
2.25.1
216
275
diff view generated by jsdifflib
New patch
1
The current kernel behavior is IMA measurements snapshot is taken at
2
kexec 'load' and not at kexec 'execute'. IMA log is then carried
3
over to the new kernel after kexec 'execute'. However, the time gap
4
between kexec load and kexec reboot can be very long. During this
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.
1
12
13
In the current implementation, a local variable "file" of type seq_file
14
is used in the API ima_dump_measurement_list() to store the IMA measurements
15
to be carried over across kexec system call. To make this buffer accessible
16
at kexec 'execute' time, rename it to "ima_kexec_file" before making it
17
a file variable to better reflect its purpose.
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.
22
23
Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
24
Signed-off-by: steven chen <chenste@linux.microsoft.com>
25
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
26
---
27
security/integrity/ima/ima_kexec.c | 31 +++++++++++++++---------------
28
1 file changed, 16 insertions(+), 15 deletions(-)
29
30
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/security/integrity/ima/ima_kexec.c
33
+++ b/security/integrity/ima/ima_kexec.c
34
@@ -XXX,XX +XXX,XX @@
35
static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
36
                 unsigned long segment_size)
37
{
38
+    struct seq_file ima_kexec_file;
39
    struct ima_queue_entry *qe;
40
-    struct seq_file file;
41
    struct ima_kexec_hdr khdr;
42
    int ret = 0;
43
44
    /* segment size can't change between kexec load and execute */
45
-    file.buf = vmalloc(segment_size);
46
-    if (!file.buf) {
47
+    ima_kexec_file.buf = vmalloc(segment_size);
48
+    if (!ima_kexec_file.buf) {
49
        ret = -ENOMEM;
50
        goto out;
51
    }
52
53
-    file.file = NULL;
54
-    file.size = segment_size;
55
-    file.read_pos = 0;
56
-    file.count = sizeof(khdr);    /* reserved space */
57
+    ima_kexec_file.file = NULL;
58
+    ima_kexec_file.size = segment_size;
59
+    ima_kexec_file.read_pos = 0;
60
+    ima_kexec_file.count = sizeof(khdr);    /* reserved space */
61
62
    memset(&khdr, 0, sizeof(khdr));
63
    khdr.version = 1;
64
    /* This is an append-only list, no need to hold the RCU read lock */
65
    list_for_each_entry_rcu(qe, &ima_measurements, later, true) {
66
-        if (file.count < file.size) {
67
+        if (ima_kexec_file.count < ima_kexec_file.size) {
68
            khdr.count++;
69
-            ima_measurements_show(&file, qe);
70
+            ima_measurements_show(&ima_kexec_file, qe);
71
        } else {
72
            ret = -EINVAL;
73
            break;
74
@@ -XXX,XX +XXX,XX @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
75
     * fill in reserved space with some buffer details
76
     * (eg. version, buffer size, number of measurements)
77
     */
78
-    khdr.buffer_size = file.count;
79
+    khdr.buffer_size = ima_kexec_file.count;
80
    if (ima_canonical_fmt) {
81
        khdr.version = cpu_to_le16(khdr.version);
82
        khdr.count = cpu_to_le64(khdr.count);
83
        khdr.buffer_size = cpu_to_le64(khdr.buffer_size);
84
    }
85
-    memcpy(file.buf, &khdr, sizeof(khdr));
86
+    memcpy(ima_kexec_file.buf, &khdr, sizeof(khdr));
87
88
    print_hex_dump_debug("ima dump: ", DUMP_PREFIX_NONE, 16, 1,
89
-             file.buf, file.count < 100 ? file.count : 100,
90
+             ima_kexec_file.buf, ima_kexec_file.count < 100 ?
91
+             ima_kexec_file.count : 100,
92
             true);
93
94
-    *buffer_size = file.count;
95
-    *buffer = file.buf;
96
+    *buffer_size = ima_kexec_file.count;
97
+    *buffer = ima_kexec_file.buf;
98
out:
99
    if (ret == -EINVAL)
100
-        vfree(file.buf);
101
+        vfree(ima_kexec_file.buf);
102
    return ret;
103
}
104
105
--
106
2.25.1
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(). Compare actual memory required to ensure
14
there is enough memory for the entire measurement record.
15
- Copy as many measurement events as possible.
16
- Make necessary changes to the function ima_add_kexec_buffer() to call
17
the above two functions.
18
- Compared the memory size allocated with memory size of the entire
19
measurement record. If there is not enough memory, it will copy as many
20
IMA measurement records as possible, and this situation will result
21
in a failure of remote attestation.
22
23
Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
24
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
25
Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
26
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
16
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
27
Signed-off-by: steven chen <chenste@linux.microsoft.com>
17
Signed-off-by: steven chen <chenste@linux.microsoft.com>
28
---
18
---
29
security/integrity/ima/ima.h | 1 +
19
security/integrity/ima/ima_kexec.c | 46 +++++++++++++++++++++++-------
30
security/integrity/ima/ima_kexec.c | 105 +++++++++++++++++++++--------
20
1 file changed, 35 insertions(+), 11 deletions(-)
31
security/integrity/ima/ima_queue.c | 4 +-
32
3 files changed, 80 insertions(+), 30 deletions(-)
33
21
34
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/security/integrity/ima/ima.h
37
+++ b/security/integrity/ima/ima.h
38
@@ -XXX,XX +XXX,XX @@ bool ima_template_has_modsig(const struct ima_template_desc *ima_template);
39
int ima_restore_measurement_entry(struct ima_template_entry *entry);
40
int ima_restore_measurement_list(loff_t bufsize, void *buf);
41
int ima_measurements_show(struct seq_file *m, void *v);
42
+int ima_get_binary_runtime_entry_size(struct ima_template_entry *entry);
43
unsigned long ima_get_binary_runtime_size(void);
44
int ima_init_template(void);
45
void ima_init_template_list(void);
46
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
47
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
48
--- a/security/integrity/ima/ima_kexec.c
24
--- a/security/integrity/ima/ima_kexec.c
49
+++ b/security/integrity/ima/ima_kexec.c
25
+++ b/security/integrity/ima/ima_kexec.c
50
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
51
#include "ima.h"
27
#include "ima.h"
52
28
53
#ifdef CONFIG_IMA_KEXEC
29
#ifdef CONFIG_IMA_KEXEC
54
+static struct seq_file ima_kexec_file;
30
+static struct seq_file ima_kexec_file;
55
+
31
+
56
+static void ima_reset_kexec_file(struct seq_file *sf)
32
+static void ima_free_kexec_file_buf(struct seq_file *sf)
57
+{
33
+{
34
+    vfree(sf->buf);
58
+    sf->buf = NULL;
35
+    sf->buf = NULL;
59
+    sf->size = 0;
36
+    sf->size = 0;
60
+    sf->read_pos = 0;
37
+    sf->read_pos = 0;
61
+    sf->count = 0;
38
+    sf->count = 0;
62
+}
39
+}
63
+
40
+
64
+static void ima_free_kexec_file_buf(struct seq_file *sf)
65
+{
66
+    vfree(sf->buf);
67
+    ima_reset_kexec_file(sf);
68
+}
69
+
70
+static int ima_alloc_kexec_file_buf(size_t segment_size)
41
+static int ima_alloc_kexec_file_buf(size_t segment_size)
71
+{
42
+{
72
+    /*
73
+     * kexec 'load' may be called multiple times.
74
+     * Free and realloc the buffer only if the segment_size is
75
+     * changed from the previous kexec 'load' call.
76
+     */
77
+    if (ima_kexec_file.buf &&
78
+        (ima_kexec_file.size == segment_size)) {
79
+        goto out;
80
+    }
81
+
82
+    ima_free_kexec_file_buf(&ima_kexec_file);
43
+    ima_free_kexec_file_buf(&ima_kexec_file);
83
+
44
+
84
+    /* segment size can't change between kexec load and execute */
45
+    /* segment size can't change between kexec load and execute */
85
+    ima_kexec_file.buf = vmalloc(segment_size);
46
+    ima_kexec_file.buf = vmalloc(segment_size);
86
+    if (!ima_kexec_file.buf)
47
+    if (!ima_kexec_file.buf)
87
+        return -ENOMEM;
48
+        return -ENOMEM;
88
+
49
+
89
+    ima_kexec_file.size = segment_size;
50
+    ima_kexec_file.size = segment_size;
90
+
91
+out:
92
+    ima_kexec_file.read_pos = 0;
51
+    ima_kexec_file.read_pos = 0;
93
+    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
52
+    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
94
+
53
+
95
+    return 0;
54
+    return 0;
96
+}
55
+}
97
+
56
+
98
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,
99
                 unsigned long segment_size)
58
                 unsigned long segment_size)
100
{
59
{
60
-    struct seq_file ima_kexec_file;
101
    struct ima_queue_entry *qe;
61
    struct ima_queue_entry *qe;
102
-    struct seq_file file;
103
    struct ima_kexec_hdr khdr;
62
    struct ima_kexec_hdr khdr;
104
    int ret = 0;
63
    int ret = 0;
105
+    size_t entry_size = 0;
64
106
65
    /* segment size can't change between kexec load and execute */
107
-    /* segment size can't change between kexec load and execute */
66
-    ima_kexec_file.buf = vmalloc(segment_size);
108
-    file.buf = vmalloc(segment_size);
67
    if (!ima_kexec_file.buf) {
109
-    if (!file.buf) {
110
-        ret = -ENOMEM;
68
-        ret = -ENOMEM;
111
-        goto out;
69
-        goto out;
112
+    if (!ima_kexec_file.buf) {
113
+        pr_err("Kexec file buf not allocated\n");
70
+        pr_err("Kexec file buf not allocated\n");
114
+        return -EINVAL;
71
+        return -EINVAL;
115
    }
72
    }
116
73
117
-    file.file = NULL;
74
-    ima_kexec_file.file = NULL;
118
-    file.size = segment_size;
75
-    ima_kexec_file.size = segment_size;
119
-    file.read_pos = 0;
76
-    ima_kexec_file.read_pos = 0;
120
-    file.count = sizeof(khdr);    /* reserved space */
77
-    ima_kexec_file.count = sizeof(khdr);    /* reserved space */
121
-
78
-
122
    memset(&khdr, 0, sizeof(khdr));
79
    memset(&khdr, 0, sizeof(khdr));
123
    khdr.version = 1;
80
    khdr.version = 1;
124
+
81
    /* This is an append-only list, no need to hold the RCU read lock */
125
+    /* Copy as many IMA measurements list records as possible */
82
@@ -XXX,XX +XXX,XX @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
126
    list_for_each_entry_rcu(qe, &ima_measurements, later) {
83
    *buffer_size = ima_kexec_file.count;
127
-        if (file.count < file.size) {
84
    *buffer = ima_kexec_file.buf;
128
+        entry_size += ima_get_binary_runtime_entry_size(qe->entry);
85
out:
129
+        if (entry_size <= segment_size) {
130
            khdr.count++;
131
-            ima_measurements_show(&file, qe);
132
+            ima_measurements_show(&ima_kexec_file, qe);
133
        } else {
134
            ret = -EINVAL;
135
+            pr_err("IMA log file is too big for Kexec buf\n");
136
            break;
137
        }
138
    }
139
140
-    if (ret < 0)
141
-        goto out;
142
-
143
    /*
144
     * fill in reserved space with some buffer details
145
     * (eg. version, buffer size, number of measurements)
146
     */
147
-    khdr.buffer_size = file.count;
148
+    khdr.buffer_size = ima_kexec_file.count;
149
    if (ima_canonical_fmt) {
150
        khdr.version = cpu_to_le16(khdr.version);
151
        khdr.count = cpu_to_le64(khdr.count);
152
        khdr.buffer_size = cpu_to_le64(khdr.buffer_size);
153
    }
154
-    memcpy(file.buf, &khdr, sizeof(khdr));
155
+    memcpy(ima_kexec_file.buf, &khdr, sizeof(khdr));
156
157
    print_hex_dump_debug("ima dump: ", DUMP_PREFIX_NONE, 16, 1,
158
-             file.buf, file.count < 100 ? file.count : 100,
159
+             ima_kexec_file.buf, ima_kexec_file.count < 100 ?
160
+             ima_kexec_file.count : 100,
161
             true);
162
163
-    *buffer_size = file.count;
164
-    *buffer = file.buf;
165
-out:
166
-    if (ret == -EINVAL)
86
-    if (ret == -EINVAL)
167
-        vfree(file.buf);
87
-        vfree(ima_kexec_file.buf);
168
+    *buffer_size = ima_kexec_file.count;
169
+    *buffer = ima_kexec_file.buf;
170
+
171
    return ret;
88
    return ret;
172
}
89
}
173
174
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
175
176
    /* use more understandable variable names than defined in kbuf */
177
    void *kexec_buffer = NULL;
178
-    size_t kexec_buffer_size;
179
+    size_t kexec_buffer_size = 0;
180
    size_t kexec_segment_size;
181
    int ret;
182
90
183
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
91
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
184
        return;
92
        return;
185
    }
93
    }
186
94
187
-    ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
188
-                 kexec_segment_size);
189
-    if (!kexec_buffer) {
190
+    ret = ima_alloc_kexec_file_buf(kexec_segment_size);
95
+    ret = ima_alloc_kexec_file_buf(kexec_segment_size);
191
+    if (ret < 0) {
96
+    if (ret < 0) {
192
        pr_err("Not enough memory for the kexec measurement buffer.\n");
97
+        pr_err("Not enough memory for the kexec measurement buffer.\n");
193
        return;
194
    }
195
196
+    ret = ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
197
+                    kexec_segment_size);
198
+    if (ret < 0) {
199
+        pr_err("Failed to dump IMA measurements. Error:%d.\n", ret);
200
+        return;
98
+        return;
201
+    }
99
+    }
202
+
100
+
203
    kbuf.buffer = kexec_buffer;
101
    ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
204
    kbuf.bufsz = kexec_buffer_size;
102
                 kexec_segment_size);
205
    kbuf.memsz = kexec_segment_size;
103
    if (!kexec_buffer) {
206
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
207
    image->ima_buffer_size = kexec_segment_size;
208
    image->ima_buffer = kexec_buffer;
209
210
+    /*
211
+     * kexec owns kexec_buffer after kexec_add_buffer() is called
212
+     * and it will vfree() that buffer.
213
+     */
214
+    ima_reset_kexec_file(&ima_kexec_file);
215
+
216
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
217
         kbuf.mem);
218
}
219
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
220
index XXXXXXX..XXXXXXX 100644
221
--- a/security/integrity/ima/ima_queue.c
222
+++ b/security/integrity/ima/ima_queue.c
223
@@ -XXX,XX +XXX,XX @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
224
* binary_runtime_measurement list entry, which contains a
225
* couple of variable length fields (e.g template name and data).
226
*/
227
-static int get_binary_runtime_size(struct ima_template_entry *entry)
228
+int ima_get_binary_runtime_entry_size(struct ima_template_entry *entry)
229
{
230
    int size = 0;
231
232
@@ -XXX,XX +XXX,XX @@ static int ima_add_digest_entry(struct ima_template_entry *entry,
233
    if (binary_runtime_size != ULONG_MAX) {
234
        int size;
235
236
-        size = get_binary_runtime_size(entry);
237
+        size = ima_get_binary_runtime_entry_size(entry);
238
        binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
239
         binary_runtime_size + size : ULONG_MAX;
240
    }
241
--
104
--
242
2.25.1
105
2.25.1
diff view generated by jsdifflib
1
Currently, the mechanism to map and unmap segments to the kimage
1
Currently, the kernel behavior during kexec load is to fetch the IMA
2
structure is not available to the subsystems outside of kexec. This
2
measurements logs and store logs in kernel memory. When a kexec reboot is
3
functionality is needed when IMA is allocating the memory segments
3
triggered, these stored logs in the kernel memory are carried over to the
4
during kexec 'load' operation. Implement functions to map and unmap
4
second kernel. However, the time gap between kexec load and kexec reboot
5
segments to kimage.
5
can be very long. During this time window, new events extended into TPM
6
PCRs miss the chance to be carried over to the second kernel. This results
7
in a mismatch between TPM PCR quotes and the actual IMA measurements list
8
after kexec reboot, leading to remote attestation failure.
6
9
7
Implement kimage_map_segment() to enable mapping of IMA buffer source
10
To solve this problem, the new design defers reading the IMA measurements
8
pages to the kimage structure post kexec 'load'. This function,
11
logs into the kexec buffer to the kexec reboot phase, while still allocating
9
accepting a kimage pointer, an address, and a size, will gather the
12
the necessary buffer at kexec load time because it is not appropriate to
10
source pages within the specified address range, create an array of page
13
allocate memory at the kexec reboot moment.
11
pointers, and map these to a contiguous virtual address range. The
12
function returns the start of this range if successful, or NULL if
13
unsuccessful.
14
14
15
Implement kimage_unmap_segment() for unmapping segments
15
The content of memory segments carried over to the new kernel during the
16
using vunmap().
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.
18
19
To copy IMA measurement logs during the kexec operation, IMA allocates
20
memory at the kexec 'load' stage and map the segments to the kimage
21
structure. The mapped address will then be used to copy IMA measurements
22
during the kexec 'execute' stage.
23
24
Currently, the mechanism to map and unmap segments to the kimage structure
25
is not available to subsystems outside of kexec.
26
27
Implement kimage_map_segment() to enable IMA to map the measurement log
28
list to the kimage structure during the kexec 'load' stage. This function
29
takes a kimage pointer, a memory address, and a size, then gathers the
30
source pages within the specified address range, creates an array of page
31
pointers, and maps these to a contiguous virtual address range. The
32
function returns the start virtual address of this range if successful,
33
or NULL on failure.
34
35
Implement kimage_unmap_segment() for unmapping segments using vunmap().
17
36
18
From: Tushar Sugandhi <tusharsu@linux.microsoft.com>
37
From: Tushar Sugandhi <tusharsu@linux.microsoft.com>
19
Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
20
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
21
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
22
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
38
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
39
Cc: Eric Biederman <ebiederm@xmission.com>
40
Cc: Baoquan He <bhe@redhat.com>
41
Cc: Vivek Goyal <vgoyal@redhat.com>
42
Cc: Dave Young <dyoung@redhat.com>
23
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>
24
---
45
---
25
include/linux/kexec.h | 7 ++++++
46
include/linux/kexec.h | 6 +++++
26
kernel/kexec_core.c | 54 +++++++++++++++++++++++++++++++++++++++++++
47
kernel/kexec_core.c | 54 +++++++++++++++++++++++++++++++++++++++++++
27
2 files changed, 61 insertions(+)
48
2 files changed, 60 insertions(+)
28
49
29
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
50
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
30
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
31
--- a/include/linux/kexec.h
52
--- a/include/linux/kexec.h
32
+++ b/include/linux/kexec.h
53
+++ b/include/linux/kexec.h
33
@@ -XXX,XX +XXX,XX @@ extern bool kexec_file_dbg_print;
54
@@ -XXX,XX +XXX,XX @@ extern bool kexec_file_dbg_print;
34
#define kexec_dprintk(fmt, arg...) \
55
#define kexec_dprintk(fmt, arg...) \
35
do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
56
do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
36
57
37
+extern void *kimage_map_segment(struct kimage *image,
58
+extern void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size);
38
+                    unsigned long addr, unsigned long size);
39
+extern void kimage_unmap_segment(void *buffer);
59
+extern void kimage_unmap_segment(void *buffer);
40
#else /* !CONFIG_KEXEC_CORE */
60
#else /* !CONFIG_KEXEC_CORE */
41
struct pt_regs;
61
struct pt_regs;
42
struct task_struct;
62
struct task_struct;
43
@@ -XXX,XX +XXX,XX @@ static inline void __crash_kexec(struct pt_regs *regs) { }
63
+struct kimage;
64
static inline void __crash_kexec(struct pt_regs *regs) { }
44
static inline void crash_kexec(struct pt_regs *regs) { }
65
static inline void crash_kexec(struct pt_regs *regs) { }
45
static inline int kexec_should_crash(struct task_struct *p) { return 0; }
66
static inline int kexec_should_crash(struct task_struct *p) { return 0; }
46
static inline int kexec_crash_loaded(void) { return 0; }
67
static inline int kexec_crash_loaded(void) { return 0; }
47
+static inline void *kimage_map_segment(struct kimage *image,
68
+static inline void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size)
48
+                    unsigned long addr, unsigned long size)
49
+{ return NULL; }
69
+{ return NULL; }
50
+static inline void kimage_unmap_segment(void *buffer) { }
70
+static inline void kimage_unmap_segment(void *buffer) { }
51
#define kexec_in_progress false
71
#define kexec_in_progress false
52
#endif /* CONFIG_KEXEC_CORE */
72
#endif /* CONFIG_KEXEC_CORE */
53
73
...
...
60
}
80
}
61
81
62
+void *kimage_map_segment(struct kimage *image,
82
+void *kimage_map_segment(struct kimage *image,
63
+             unsigned long addr, unsigned long size)
83
+             unsigned long addr, unsigned long size)
64
+{
84
+{
85
+    unsigned long src_page_addr, dest_page_addr = 0;
65
+    unsigned long eaddr = addr + size;
86
+    unsigned long eaddr = addr + size;
66
+    unsigned long src_page_addr, dest_page_addr;
87
+    kimage_entry_t *ptr, entry;
88
+    struct page **src_pages;
67
+    unsigned int npages;
89
+    unsigned int npages;
68
+    struct page **src_pages;
90
+    void *vaddr = NULL;
69
+    int i;
91
+    int i;
70
+    kimage_entry_t *ptr, entry;
71
+    void *vaddr = NULL;
72
+
92
+
73
+    /*
93
+    /*
74
+     * Collect the source pages and map them in a contiguous VA range.
94
+     * Collect the source pages and map them in a contiguous VA range.
75
+     */
95
+     */
76
+    npages = PFN_UP(eaddr) - PFN_DOWN(addr);
96
+    npages = PFN_UP(eaddr) - PFN_DOWN(addr);
...
...
80
+        return NULL;
100
+        return NULL;
81
+    }
101
+    }
82
+
102
+
83
+    i = 0;
103
+    i = 0;
84
+    for_each_kimage_entry(image, ptr, entry) {
104
+    for_each_kimage_entry(image, ptr, entry) {
85
+        if (entry & IND_DESTINATION)
105
+        if (entry & IND_DESTINATION) {
86
+            dest_page_addr = entry & PAGE_MASK;
106
+            dest_page_addr = entry & PAGE_MASK;
87
+        else if (entry & IND_SOURCE) {
107
+        } else if (entry & IND_SOURCE) {
88
+            if (dest_page_addr >= addr && dest_page_addr < eaddr) {
108
+            if (dest_page_addr >= addr && dest_page_addr < eaddr) {
89
+                src_page_addr = entry & PAGE_MASK;
109
+                src_page_addr = entry & PAGE_MASK;
90
+                src_pages[i++] =
110
+                src_pages[i++] =
91
+                    virt_to_page(__va(src_page_addr));
111
+                    virt_to_page(__va(src_page_addr));
92
+                if (i == npages)
112
+                if (i == npages)
...
...
diff view generated by jsdifflib
1
kexec_calculate_store_digests() calculates and stores the digest of the
1
The kexec_calculate_store_digests() function calculates and stores the
2
segment at kexec_file_load syscall where the IMA segment is also
2
digest of the segment during the kexec_file_load syscall, where the
3
allocated. With this series, the IMA segment will be updated with the
3
IMA segment is also allocated.
4
measurement log at kexec excute stage when soft reboot is initiated.
4
5
Therefore, it may fail digest verification in verify_sha256_digest()
5
With this series, the IMA segment will be updated with the measurement
6
after kexec soft reboot into the new kernel. Therefore, the digest
6
log at the kexec execute stage when a soft reboot is initiated.
7
Therefore, the digests should be updated for the IMA segment in the
8
normal case.
9
10
The content of memory segments carried over to the new kernel during the
11
kexec systemcall can be changed at kexec 'execute' stage, but the size
12
and the location of the memory segments cannot be changed at kexec
13
'execute' stage.
14
15
However, during the kexec execute stage, if kexec_calculate_store_digests()
16
API is called to update the digest, it does not reuse the same memory
17
segment allocated during the kexec 'load' stage and the new memory segment
18
required cannot be transferred/mapped to the new kernel.
19
20
As a result, digest verification will fail in verify_sha256_digest()
21
after a kexec soft reboot into the new kernel. Therefore, the digest
7
calculation/verification of the IMA segment needs to be skipped.
22
calculation/verification of the IMA segment needs to be skipped.
8
23
9
Skip IMA segment from calculating and storing digest in function
24
To address this, skip the calculation and storage of the digest for the
10
kexec_calculate_store_digests() so that it is not added to the
25
IMA segment in kexec_calculate_store_digests() so that it is not added
11
'purgatory_sha_regions'.
26
to the purgatory_sha_regions.
12
27
13
Since verify_sha256_digest() only verifies 'purgatory_sha_regions',
28
Since verify_sha256_digest() only verifies 'purgatory_sha_regions',
14
no change is needed in verify_sha256_digest() in this context.
29
no change is needed in verify_sha256_digest() in this context.
15
30
16
With this change, the IMA segment is not included in the digest
31
With this change, the IMA segment is not included in the digest
17
calculation, storage, and verification.
32
calculation, storage, and verification.
18
33
19
Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
20
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
34
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
35
Cc: Eric Biederman <ebiederm@xmission.com>
36
Cc: Baoquan He <bhe@redhat.com>
37
Cc: Vivek Goyal <vgoyal@redhat.com>
38
Cc: Dave Young <dyoung@redhat.com>
21
Signed-off-by: steven chen <chenste@linux.microsoft.com>
39
Signed-off-by: steven chen <chenste@linux.microsoft.com>
40
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
41
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
42
Acked-by: Baoquan He <bhe@redhat.com>
22
---
43
---
23
include/linux/kexec.h | 3 +++
44
include/linux/kexec.h | 3 +++
24
kernel/kexec_file.c | 23 +++++++++++++++++++++++
45
kernel/kexec_file.c | 22 ++++++++++++++++++++++
25
security/integrity/ima/ima_kexec.c | 3 +++
46
security/integrity/ima/ima_kexec.c | 3 +++
26
3 files changed, 29 insertions(+)
47
3 files changed, 28 insertions(+)
27
48
28
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
49
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
29
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
30
--- a/include/linux/kexec.h
51
--- a/include/linux/kexec.h
31
+++ b/include/linux/kexec.h
52
+++ b/include/linux/kexec.h
...
...
46
@@ -XXX,XX +XXX,XX @@ void set_kexec_sig_enforced(void)
67
@@ -XXX,XX +XXX,XX @@ void set_kexec_sig_enforced(void)
47
}
68
}
48
#endif
69
#endif
49
70
50
+#ifdef CONFIG_IMA_KEXEC
71
+#ifdef CONFIG_IMA_KEXEC
51
+static bool check_ima_segment_index(struct kimage *image, int i)
72
+static bool check_ima_segment_index(struct kimage *image, int i)
52
+{
73
+{
53
+    if (image->is_ima_segment_index_set &&
74
+    if (image->is_ima_segment_index_set && i == image->ima_segment_index)
54
+            i == image->ima_segment_index)
55
+        return true;
75
+        return true;
56
+    else
76
+    else
57
+        return false;
77
+        return false;
58
+}
78
+}
59
+#else
79
+#else
...
...
97
    image->ima_buffer_size = kexec_segment_size;
117
    image->ima_buffer_size = kexec_segment_size;
98
    image->ima_buffer = kexec_buffer;
118
    image->ima_buffer = kexec_buffer;
99
+    image->ima_segment_index = image->nr_segments - 1;
119
+    image->ima_segment_index = image->nr_segments - 1;
100
+    image->is_ima_segment_index_set = true;
120
+    image->is_ima_segment_index_set = true;
101
121
102
    /*
122
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
103
     * kexec owns kexec_buffer after kexec_add_buffer() is called
123
         kbuf.mem);
104
--
124
--
105
2.25.1
125
2.25.1
diff view generated by jsdifflib
1
IMA log is copied to the new Kernel during kexec 'load' using
1
The IMA log is currently copied to the new kernel during kexec 'load'
2
ima_dump_measurement_list(). The log copy at kexec 'load' may result in
2
using ima_dump_measurement_list(). However, the log copied at kexec
3
loss of IMA measurements during kexec soft reboot. It needs to be copied
3
'load' may result in loss of IMA measurements that only occurred after
4
over during kexec 'execute'. Setup the needed infrastructure to move the
4
kexec "load'. Therefore, the log needs to be copied during kexec
5
IMA log copy from kexec 'load' to 'execute'.
5
'execute'. Setup the needed infrastructure to move the IMA log copy from
6
kexec 'load' to 'execute'.
6
7
7
Define a new IMA hook ima_update_kexec_buffer() as a stub function.
8
Define a new IMA hook ima_update_kexec_buffer() as a stub function.
8
It will be used to call ima_dump_measurement_list() during kexec
9
It will be used to call ima_dump_measurement_list() during kexec 'execute'.
9
'execute'.
10
10
11
Implement ima_kexec_post_load() function to be invoked after the new
11
Implement ima_kexec_post_load() function to be invoked after the new
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
exec 'execute'.
15
kexec 'execute'.
16
16
17
Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
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
21
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
22
Cc: Eric Biederman <ebiederm@xmission.com>
23
Cc: Baoquan He <bhe@redhat.com>
24
Cc: Vivek Goyal <vgoyal@redhat.com>
25
Cc: Dave Young <dyoung@redhat.com>
26
Signed-off-by: steven chen <chenste@linux.microsoft.com>
18
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
27
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
19
Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
20
Reviewed-by: "Petr Tesařík" <petr@tesarici.cz>
21
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
22
Signed-off-by: steven chen <chenste@linux.microsoft.com>
23
---
28
---
24
include/linux/ima.h | 3 ++
29
include/linux/ima.h | 3 ++
25
security/integrity/ima/ima_kexec.c | 46 ++++++++++++++++++++++++++++++
30
security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++
26
2 files changed, 49 insertions(+)
31
2 files changed, 50 insertions(+)
27
32
28
diff --git a/include/linux/ima.h b/include/linux/ima.h
33
diff --git a/include/linux/ima.h b/include/linux/ima.h
29
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
30
--- a/include/linux/ima.h
35
--- a/include/linux/ima.h
31
+++ b/include/linux/ima.h
36
+++ b/include/linux/ima.h
...
...
50
+#include <linux/reboot.h>
55
+#include <linux/reboot.h>
51
+#include <asm/page.h>
56
+#include <asm/page.h>
52
#include "ima.h"
57
#include "ima.h"
53
58
54
#ifdef CONFIG_IMA_KEXEC
59
#ifdef CONFIG_IMA_KEXEC
60
+static bool ima_kexec_update_registered;
55
static struct seq_file ima_kexec_file;
61
static struct seq_file ima_kexec_file;
56
+static void *ima_kexec_buffer;
62
+static void *ima_kexec_buffer;
57
+static bool ima_kexec_update_registered;
63
58
64
static void ima_free_kexec_file_buf(struct seq_file *sf)
59
static void ima_reset_kexec_file(struct seq_file *sf)
60
{
65
{
61
@@ -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)
62
    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",
63
         kbuf.mem);
68
         kbuf.mem);
64
}
69
}
...
...
70
+                 unsigned long action, void *data)
75
+                 unsigned long action, void *data)
71
+{
76
+{
72
+    return NOTIFY_OK;
77
+    return NOTIFY_OK;
73
+}
78
+}
74
+
79
+
75
+struct notifier_block update_buffer_nb = {
80
+static struct notifier_block update_buffer_nb = {
76
+    .notifier_call = ima_update_kexec_buffer,
81
+    .notifier_call = ima_update_kexec_buffer,
82
+    .priority = INT_MIN
77
+};
83
+};
78
+
84
+
79
+/*
85
+/*
80
+ * 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
81
+ * so we can update it later.
87
+ * so we can update it later.
...
...
107
#endif /* IMA_KEXEC */
113
#endif /* IMA_KEXEC */
108
114
109
/*
115
/*
110
--
116
--
111
2.25.1
117
2.25.1
112
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. It needs
2
result in loss of IMA measurements during kexec soft reboot. Due to
3
to be called during kexec 'execute'.
3
missed measurements that only occurred after kexec 'load', this function
4
needs to be called during kexec 'execute'.
4
5
5
This patch includes the following changes:
6
Make the kexec_segment_size variable a local static variable within the
6
- 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'.
7
Kernel image has been loaded for kexec.
8
8
- 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
9
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()
10
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
11
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.
12
reboot.
13
13
- Make kexec_segment_size variable local static to the file, for it to be
14
Invoke ima_kexec_post_load() within the kexec_post_load() API only for kexec
14
accessible both during kexec 'load' and 'execute'.
15
soft reboot scenarios, excluding KEXEC_FILE_ON_CRASH.
15
- Move ima_dump_measurement_list() call from ima_add_kexec_buffer()
16
16
to ima_update_kexec_buffer().
17
Register a reboot notifier for the ima_update_kexec_buffer() API within
17
- Remove ima_reset_kexec_file() call from ima_add_kexec_buffer(), now
18
ima_kexec_post_load() to ensure it is called upon receiving a reboot
18
that the buffer is being copied at kexec 'execute', and resetting the
19
notification.
19
file at kexec 'load' will corrupt the buffer.
20
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.
20
26
21
Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
22
Reviewed-by: Tyler Hicks <code@tyhicks.com>
23
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
27
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
28
Cc: Eric Biederman <ebiederm@xmission.com>
29
Cc: Baoquan He <bhe@redhat.com>
30
Cc: Vivek Goyal <vgoyal@redhat.com>
31
Cc: Dave Young <dyoung@redhat.com>
24
Signed-off-by: steven chen <chenste@linux.microsoft.com>
32
Signed-off-by: steven chen <chenste@linux.microsoft.com>
33
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
25
---
34
---
26
kernel/kexec_file.c | 8 ++++++
35
kernel/kexec_file.c | 11 +++++++-
27
security/integrity/ima/ima_kexec.c | 43 +++++++++++++++++++-----------
36
security/integrity/ima/ima_kexec.c | 43 ++++++++++++++++++++----------
28
2 files changed, 36 insertions(+), 15 deletions(-)
37
2 files changed, 39 insertions(+), 15 deletions(-)
29
38
30
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
31
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
32
--- a/kernel/kexec_file.c
41
--- a/kernel/kexec_file.c
33
+++ b/kernel/kexec_file.c
42
+++ b/kernel/kexec_file.c
34
@@ -XXX,XX +XXX,XX @@ kimage_validate_signature(struct kimage *image)
43
@@ -XXX,XX +XXX,XX @@ kimage_validate_signature(struct kimage *image)
35
}
44
}
36
#endif
45
#endif
37
46
38
+static void kimage_file_post_load(struct kimage *image)
47
+static int kexec_post_load(struct kimage *image, unsigned long flags)
39
+{
48
+{
40
+    ima_kexec_post_load(image);
49
+#ifdef CONFIG_IMA_KEXEC
50
+    if (!(flags & KEXEC_FILE_ON_CRASH))
51
+        ima_kexec_post_load(image);
52
+#endif
53
+    return machine_kexec_post_load(image);
41
+}
54
+}
42
+
55
+
43
/*
56
/*
44
* 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
45
* data from user space, do error checking, prepare segment list
58
* data from user space, do error checking, prepare segment list
46
@@ -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,
47
60
48
    kimage_terminate(image);
61
    kimage_terminate(image);
49
62
50
+    if (!(flags & KEXEC_FILE_ON_CRASH))
63
-    ret = machine_kexec_post_load(image);
51
+        kimage_file_post_load(image);
64
+    ret = kexec_post_load(image, flags);
52
+
53
    ret = machine_kexec_post_load(image);
54
    if (ret)
65
    if (ret)
55
        goto out;
66
        goto out;
67
56
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
57
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
58
--- a/security/integrity/ima/ima_kexec.c
70
--- a/security/integrity/ima/ima_kexec.c
59
+++ b/security/integrity/ima/ima_kexec.c
71
+++ b/security/integrity/ima/ima_kexec.c
60
@@ -XXX,XX +XXX,XX @@
72
@@ -XXX,XX +XXX,XX @@
61
#ifdef CONFIG_IMA_KEXEC
73
#ifdef CONFIG_IMA_KEXEC
74
static bool ima_kexec_update_registered;
62
static struct seq_file ima_kexec_file;
75
static struct seq_file ima_kexec_file;
76
+static size_t kexec_segment_size;
63
static void *ima_kexec_buffer;
77
static void *ima_kexec_buffer;
64
+static size_t kexec_segment_size;
78
65
static bool ima_kexec_update_registered;
79
static void ima_free_kexec_file_buf(struct seq_file *sf)
66
80
@@ -XXX,XX +XXX,XX @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
67
static void ima_reset_kexec_file(struct seq_file *sf)
81
        }
82
    }
83
84
-    if (ret < 0)
85
-        goto out;
86
-
87
    /*
88
     * fill in reserved space with some buffer details
89
     * (eg. version, buffer size, number of measurements)
90
@@ -XXX,XX +XXX,XX @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
91
92
    *buffer_size = ima_kexec_file.count;
93
    *buffer = ima_kexec_file.buf;
94
-out:
95
+
96
    return ret;
97
}
98
68
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
99
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
100
    unsigned long binary_runtime_size;
101
69
    /* use more understandable variable names than defined in kbuf */
102
    /* use more understandable variable names than defined in kbuf */
103
+    size_t kexec_buffer_size = 0;
70
    void *kexec_buffer = NULL;
104
    void *kexec_buffer = NULL;
71
    size_t kexec_buffer_size = 0;
105
-    size_t kexec_buffer_size;
72
-    size_t kexec_segment_size;
106
-    size_t kexec_segment_size;
73
    int ret;
107
    int ret;
74
108
75
    /*
109
    /*
76
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
110
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
77
        return;
111
        return;
78
    }
112
    }
79
113
80
-    ret = ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
114
-    ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
81
-                    kexec_segment_size);
115
-                 kexec_segment_size);
82
-    if (ret < 0) {
116
-    if (!kexec_buffer) {
83
-        pr_err("Failed to dump IMA measurements. Error:%d.\n", ret);
117
-        pr_err("Not enough memory for the kexec measurement buffer.\n");
84
-        return;
118
-        return;
85
-    }
119
-    }
86
-
120
-
87
    kbuf.buffer = kexec_buffer;
121
    kbuf.buffer = kexec_buffer;
88
    kbuf.bufsz = kexec_buffer_size;
122
    kbuf.bufsz = kexec_buffer_size;
89
    kbuf.memsz = kexec_segment_size;
123
    kbuf.memsz = kexec_segment_size;
90
@@ -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)
91
    image->ima_segment_index = image->nr_segments - 1;
92
    image->is_ima_segment_index_set = true;
93
94
-    /*
95
-     * kexec owns kexec_buffer after kexec_add_buffer() is called
96
-     * and it will vfree() that buffer.
97
-     */
98
-    ima_reset_kexec_file(&ima_kexec_file);
99
-
100
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
101
         kbuf.mem);
102
}
103
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
104
static int ima_update_kexec_buffer(struct notifier_block *self,
125
static int ima_update_kexec_buffer(struct notifier_block *self,
105
                 unsigned long action, void *data)
126
                 unsigned long action, void *data)
106
{
127
{
107
-    return NOTIFY_OK;
128
-    return NOTIFY_OK;
108
+    void *buf = NULL;
109
+    size_t buf_size = 0;
129
+    size_t buf_size = 0;
110
+    int ret = NOTIFY_OK;
130
+    int ret = NOTIFY_OK;
131
+    void *buf = NULL;
111
+
132
+
112
+    if (!kexec_in_progress) {
133
+    if (!kexec_in_progress) {
113
+        pr_info("No kexec in progress.\n");
134
+        pr_info("No kexec in progress.\n");
114
+        return ret;
135
+        return ret;
115
+    }
136
+    }
116
+
137
+
117
+    if (!ima_kexec_buffer) {
138
+    if (!ima_kexec_buffer) {
118
+        pr_err("Kexec buffer not set.\n");
139
+        pr_err("Kexec buffer not set.\n");
119
+        return ret;
140
+        return ret;
120
+    }
141
+    }
121
+
142
+
122
+    ret = ima_dump_measurement_list(&buf_size, &buf,
143
+    ret = ima_dump_measurement_list(&buf_size, &buf, kexec_segment_size);
123
+                    kexec_segment_size);
124
+
144
+
125
+    if (ret)
145
+    if (ret)
126
+        pr_err("Dump measurements failed. Error:%d\n", ret);
146
+        pr_err("Dump measurements failed. Error:%d\n", ret);
127
+
147
+
128
+    if (buf_size != 0)
148
+    if (buf_size != 0)
...
...
132
+    ima_kexec_buffer = NULL;
152
+    ima_kexec_buffer = NULL;
133
+
153
+
134
+    return ret;
154
+    return ret;
135
}
155
}
136
156
137
struct notifier_block update_buffer_nb = {
157
static struct notifier_block update_buffer_nb = {
138
--
158
--
139
2.25.1
159
2.25.1
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
...
...
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
From: Tushar Sugandhi <tusharsu@linux.microsoft.com>
14
Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
15
Suggested-by: Stefan Berger <stefanb@linux.ibm.com>
13
Suggested-by: Stefan Berger <stefanb@linux.ibm.com>
16
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
14
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
17
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>
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, 20 insertions(+), 6 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
...
...
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, an extra half a 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
-
50
+    unsigned long extra_memory;
51
+    unsigned long extra_size;
51
52
    /* use more understandable variable names than defined in kbuf */
52
    /* use more understandable variable names than defined in kbuf */
53
    void *kexec_buffer = NULL;
54
    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)
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_size = PAGE_SIZE / 2;
64
+        extra_memory = PAGE_SIZE / 2;
65
+    else
65
+    else
66
+        extra_size = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
66
+        extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
67
+    binary_runtime_size = ima_get_binary_runtime_size() + extra_size;
67
+
68
+    binary_runtime_size = ima_get_binary_runtime_size() + extra_memory;
68
+
69
+
69
    if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
70
    if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
70
        kexec_segment_size = ULONG_MAX;
71
        kexec_segment_size = ULONG_MAX;
71
    else
72
    else
72
-        kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
73
-        kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
...
...
diff view generated by jsdifflib
...
...
15
reboot, and not a cold-boot. And the absence of 'kexec_execute' event
15
reboot, and not a cold-boot. And the absence of 'kexec_execute' event
16
after kexec soft reboot implies missing events in that window which
16
after kexec soft reboot implies missing events in that window which
17
results in inconsistency with TPM PCR quotes, necessitating a cold boot
17
results in inconsistency with TPM PCR quotes, necessitating a cold boot
18
for a successful remote attestation.
18
for a successful remote attestation.
19
19
20
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
20
These critical data events are displayed as hex encoded ascii in the
21
Author: Tushar Sugandhi <tusharsu@linux.microsoft.com>
21
ascii_runtime_measurement_list. Verifying the critical data hash requires
22
calculating the hash of the decoded ascii string.
23
24
For example, to verify the 'kexec_load' data hash:
25
26
sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements
27
| grep kexec_load | cut -d' ' -f 6 | xxd -r -p | sha256sum
28
29
30
To verify the 'kexec_execute' data hash:
31
32
sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements
33
| grep kexec_execute | cut -d' ' -f 6 | xxd -r -p | sha256sum
34
22
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
35
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
23
Signed-off-by: steven chen <chenste@linux.microsoft.com>
36
Signed-off-by: steven chen <chenste@linux.microsoft.com>
37
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
24
---
38
---
25
security/integrity/ima/ima_kexec.c | 23 +++++++++++++++++++++++
39
security/integrity/ima/ima.h | 6 ++++++
26
1 file changed, 23 insertions(+)
40
security/integrity/ima/ima_kexec.c | 21 +++++++++++++++++++++
41
security/integrity/ima/ima_queue.c | 5 +++++
42
3 files changed, 32 insertions(+)
27
43
44
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/security/integrity/ima/ima.h
47
+++ b/security/integrity/ima/ima.h
48
@@ -XXX,XX +XXX,XX @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
49
                 unsigned long flags, bool create);
50
#endif
51
52
+#ifdef CONFIG_IMA_KEXEC
53
+void ima_measure_kexec_event(const char *event_name);
54
+#else
55
+static inline void ima_measure_kexec_event(const char *event_name) {}
56
+#endif
57
+
58
/*
59
* The default binary_runtime_measurements list format is defined as the
60
* platform native format. The canonical format is defined as little-endian.
28
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
61
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
29
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
30
--- a/security/integrity/ima/ima_kexec.c
63
--- a/security/integrity/ima/ima_kexec.c
31
+++ b/security/integrity/ima/ima_kexec.c
64
+++ b/security/integrity/ima/ima_kexec.c
32
@@ -XXX,XX +XXX,XX @@
65
@@ -XXX,XX +XXX,XX @@
33
#include "ima.h"
66
#include "ima.h"
34
67
35
#ifdef CONFIG_IMA_KEXEC
68
#ifdef CONFIG_IMA_KEXEC
36
+#define IMA_KEXEC_EVENT_LEN 256
69
+#define IMA_KEXEC_EVENT_LEN 256
37
+
70
+
71
static bool ima_kexec_update_registered;
38
static struct seq_file ima_kexec_file;
72
static struct seq_file ima_kexec_file;
39
static void *ima_kexec_buffer;
40
static size_t kexec_segment_size;
73
static size_t kexec_segment_size;
41
@@ -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)
42
    ima_reset_kexec_file(sf);
75
    sf->count = 0;
43
}
76
}
44
77
45
+static void ima_measure_kexec_event(const char *event_name)
78
+void ima_measure_kexec_event(const char *event_name)
46
+{
79
+{
47
+    char ima_kexec_event[IMA_KEXEC_EVENT_LEN];
80
+    char ima_kexec_event[IMA_KEXEC_EVENT_LEN];
48
+    size_t buf_size = 0;
81
+    size_t buf_size = 0;
49
+    long len;
82
+    long len;
83
+    int n;
50
+
84
+
51
+    buf_size = ima_get_binary_runtime_size();
85
+    buf_size = ima_get_binary_runtime_size();
52
+    len = atomic_long_read(&ima_htable.len);
86
+    len = atomic_long_read(&ima_htable.len);
53
+
87
+
54
+    scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN,
88
+    n = scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN,
55
+            "kexec_segment_size=%lu;ima_binary_runtime_size=%lu;"
89
+         "kexec_segment_size=%lu;ima_binary_runtime_size=%lu;"
56
+            "ima_runtime_measurements_count=%ld;",
90
+         "ima_runtime_measurements_count=%ld;",
57
+                kexec_segment_size, buf_size, len);
91
+         kexec_segment_size, buf_size, len);
58
+
92
+
59
+    ima_measure_critical_data("ima_kexec", event_name, ima_kexec_event,
93
+    ima_measure_critical_data("ima_kexec", event_name, ima_kexec_event, n, false, NULL, 0);
60
+                    strlen(ima_kexec_event), false, NULL, 0);
61
+}
94
+}
62
+
95
+
63
static int ima_alloc_kexec_file_buf(size_t segment_size)
96
static int ima_alloc_kexec_file_buf(size_t segment_size)
64
{
97
{
65
    /*
98
    /*
...
...
69
    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
102
    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
70
+    ima_measure_kexec_event("kexec_load");
103
+    ima_measure_kexec_event("kexec_load");
71
104
72
    return 0;
105
    return 0;
73
}
106
}
74
@@ -XXX,XX +XXX,XX @@ static int ima_update_kexec_buffer(struct notifier_block *self,
107
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
75
        return ret;
108
index XXXXXXX..XXXXXXX 100644
76
    }
109
--- a/security/integrity/ima/ima_queue.c
77
110
+++ b/security/integrity/ima/ima_queue.c
78
+    ima_measure_kexec_event("kexec_execute");
111
@@ -XXX,XX +XXX,XX @@ static int ima_reboot_notifier(struct notifier_block *nb,
112
             unsigned long action,
113
             void *data)
114
{
115
+#ifdef CONFIG_IMA_KEXEC
116
+    if (action == SYS_RESTART && data && !strcmp(data, "kexec reboot"))
117
+        ima_measure_kexec_event("kexec_execute");
118
+#endif
79
+
119
+
80
    ret = ima_dump_measurement_list(&buf_size, &buf,
120
    ima_measurements_suspend();
81
                    kexec_segment_size);
121
82
122
    return NOTIFY_DONE;
83
--
123
--
84
2.25.1
124
2.25.1
diff view generated by jsdifflib