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
...
...
32
- 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
33
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,
34
35
35
- 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
36
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
37
current Kernel to the next,
38
current Kernel to the next,
38
39
39
- excluding IMA segment while calculating and storing digest in function
40
- excluding IMA segment while calculating and storing digest in function
40
kexec_calculate_store_digests(), since IMA segment can be modified
41
kexec_calculate_store_digests(), since IMA segment can be modified
41
after the digest is computed during kexec 'load'. This will ensure
42
after the digest is computed during kexec 'load'. This will ensure
42
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
...
...
56
57
57
V5 of this series is available here[7] for reference.
58
V5 of this series is available here[7] for reference.
58
59
59
V6 of this series is available here[8] for reference.
60
V6 of this series is available here[8] for reference.
60
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
61
References:
70
References:
62
-----------
71
-----------
63
72
64
[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
65
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/
...
...
85
[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
86
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/
87
96
88
[9] [PATCH v7 0/7] ima: kexec: measure events between kexec load and execute
97
[9] [PATCH v7 0/7] ima: kexec: measure events between kexec load and execute
89
https://lore.kernel.org/all/20250203232033.64123-1-chenste@linux.microsoft.com/
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.
90
138
91
Change Log v8:
139
Change Log v8:
92
- Incorporated feedback from the community (Stefan Berger, Mimi Zohar)
140
- Incorporated feedback from the community (Stefan Berger, Mimi Zohar)
93
on v7 of this series[9].
141
on v7 of this series[9].
94
- Rebased the patch series to mainline 6.14.0-rc1.
142
- Rebased the patch series to mainline 6.14.0-rc1.
...
...
198
- Refactored patches to ensure no warnings during individual patch
246
- Refactored patches to ensure no warnings during individual patch
199
compilation.
247
compilation.
200
- Used virt_to_page instead of phys_to_page.
248
- Used virt_to_page instead of phys_to_page.
201
- Updated patch descriptions as necessary.
249
- Updated patch descriptions as necessary.
202
250
203
steven chen (7):
251
204
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()
205
kexec: define functions to map and unmap segments
255
kexec: define functions to map and unmap segments
206
ima: kexec: skip IMA segment validation after kexec soft reboot
256
ima: kexec: skip IMA segment validation after kexec soft reboot
207
ima: kexec: define functions to copy IMA log at soft boot
257
ima: kexec: define functions to copy IMA log at soft boot
208
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
209
ima: make the kexec extra memory configurable
260
ima: make the kexec extra memory configurable
210
ima: measure kexec load and exec events as critical data
261
ima: measure kexec load and exec events as critical data
211
262
212
include/linux/ima.h | 3 +
263
include/linux/ima.h | 3 +
213
include/linux/kexec.h | 8 ++
264
include/linux/kexec.h | 9 ++
214
kernel/kexec_core.c | 54 ++++++++
265
kernel/kexec_core.c | 54 ++++++++
215
kernel/kexec_file.c | 30 +++++
266
kernel/kexec_file.c | 33 ++++-
216
security/integrity/ima/Kconfig | 10 ++
267
security/integrity/ima/Kconfig | 10 ++
217
security/integrity/ima/ima.h | 7 +
268
security/integrity/ima/ima.h | 6 +
218
security/integrity/ima/ima_kexec.c | 203 ++++++++++++++++++++++++-----
269
security/integrity/ima/ima_kexec.c | 193 ++++++++++++++++++++++++-----
219
security/integrity/ima/ima_queue.c | 9 +-
270
security/integrity/ima/ima_queue.c | 5 +
220
8 files changed, 287 insertions(+), 37 deletions(-)
271
8 files changed, 279 insertions(+), 34 deletions(-)
221
272
222
--
273
--
223
2.25.1
274
2.25.1
224
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
Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
25
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
16
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
26
Signed-off-by: steven chen <chenste@linux.microsoft.com>
17
Signed-off-by: steven chen <chenste@linux.microsoft.com>
27
---
18
---
28
security/integrity/ima/ima.h | 1 +
19
security/integrity/ima/ima_kexec.c | 46 +++++++++++++++++++++++-------
29
security/integrity/ima/ima_kexec.c | 102 +++++++++++++++++++++--------
20
1 file changed, 35 insertions(+), 11 deletions(-)
30
security/integrity/ima/ima_queue.c | 4 +-
31
3 files changed, 77 insertions(+), 30 deletions(-)
32
21
33
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/security/integrity/ima/ima.h
36
+++ b/security/integrity/ima/ima.h
37
@@ -XXX,XX +XXX,XX @@ bool ima_template_has_modsig(const struct ima_template_desc *ima_template);
38
int ima_restore_measurement_entry(struct ima_template_entry *entry);
39
int ima_restore_measurement_list(loff_t bufsize, void *buf);
40
int ima_measurements_show(struct seq_file *m, void *v);
41
+int ima_get_binary_runtime_entry_size(struct ima_template_entry *entry);
42
unsigned long ima_get_binary_runtime_size(void);
43
int ima_init_template(void);
44
void ima_init_template_list(void);
45
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
46
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
47
--- a/security/integrity/ima/ima_kexec.c
24
--- a/security/integrity/ima/ima_kexec.c
48
+++ b/security/integrity/ima/ima_kexec.c
25
+++ b/security/integrity/ima/ima_kexec.c
49
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
50
#include "ima.h"
27
#include "ima.h"
51
28
52
#ifdef CONFIG_IMA_KEXEC
29
#ifdef CONFIG_IMA_KEXEC
53
+static struct seq_file ima_kexec_file;
30
+static struct seq_file ima_kexec_file;
54
+
31
+
55
+static void ima_reset_kexec_file(struct seq_file *sf)
32
+static void ima_free_kexec_file_buf(struct seq_file *sf)
56
+{
33
+{
34
+    vfree(sf->buf);
57
+    sf->buf = NULL;
35
+    sf->buf = NULL;
58
+    sf->size = 0;
36
+    sf->size = 0;
59
+    sf->read_pos = 0;
37
+    sf->read_pos = 0;
60
+    sf->count = 0;
38
+    sf->count = 0;
61
+}
39
+}
62
+
40
+
63
+static void ima_free_kexec_file_buf(struct seq_file *sf)
64
+{
65
+    vfree(sf->buf);
66
+    ima_reset_kexec_file(sf);
67
+}
68
+
69
+static int ima_alloc_kexec_file_buf(size_t segment_size)
41
+static int ima_alloc_kexec_file_buf(size_t segment_size)
70
+{
42
+{
71
+    /*
72
+     * kexec 'load' may be called multiple times.
73
+     * Free and realloc the buffer only if the segment_size is
74
+     * changed from the previous kexec 'load' call.
75
+     */
76
+    if (ima_kexec_file.buf && ima_kexec_file.size == segment_size)
77
+        goto out;
78
+
79
+    ima_free_kexec_file_buf(&ima_kexec_file);
43
+    ima_free_kexec_file_buf(&ima_kexec_file);
80
+
44
+
81
+    /* segment size can't change between kexec load and execute */
45
+    /* segment size can't change between kexec load and execute */
82
+    ima_kexec_file.buf = vmalloc(segment_size);
46
+    ima_kexec_file.buf = vmalloc(segment_size);
83
+    if (!ima_kexec_file.buf)
47
+    if (!ima_kexec_file.buf)
84
+        return -ENOMEM;
48
+        return -ENOMEM;
85
+
49
+
86
+    ima_kexec_file.size = segment_size;
50
+    ima_kexec_file.size = segment_size;
87
+
88
+out:
89
+    ima_kexec_file.read_pos = 0;
51
+    ima_kexec_file.read_pos = 0;
90
+    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
52
+    ima_kexec_file.count = sizeof(struct ima_kexec_hdr);    /* reserved space */
91
+
53
+
92
+    return 0;
54
+    return 0;
93
+}
55
+}
94
+
56
+
95
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,
96
                 unsigned long segment_size)
58
                 unsigned long segment_size)
97
{
59
{
60
-    struct seq_file ima_kexec_file;
98
    struct ima_queue_entry *qe;
61
    struct ima_queue_entry *qe;
99
-    struct seq_file file;
100
    struct ima_kexec_hdr khdr;
62
    struct ima_kexec_hdr khdr;
101
    int ret = 0;
63
    int ret = 0;
102
+    size_t entry_size = 0;
64
103
65
    /* segment size can't change between kexec load and execute */
104
-    /* segment size can't change between kexec load and execute */
66
-    ima_kexec_file.buf = vmalloc(segment_size);
105
-    file.buf = vmalloc(segment_size);
67
    if (!ima_kexec_file.buf) {
106
-    if (!file.buf) {
107
-        ret = -ENOMEM;
68
-        ret = -ENOMEM;
108
-        goto out;
69
-        goto out;
109
+    if (!ima_kexec_file.buf) {
110
+        pr_err("Kexec file buf not allocated\n");
70
+        pr_err("Kexec file buf not allocated\n");
111
+        return -EINVAL;
71
+        return -EINVAL;
112
    }
72
    }
113
73
114
-    file.file = NULL;
74
-    ima_kexec_file.file = NULL;
115
-    file.size = segment_size;
75
-    ima_kexec_file.size = segment_size;
116
-    file.read_pos = 0;
76
-    ima_kexec_file.read_pos = 0;
117
-    file.count = sizeof(khdr);    /* reserved space */
77
-    ima_kexec_file.count = sizeof(khdr);    /* reserved space */
118
-
78
-
119
    memset(&khdr, 0, sizeof(khdr));
79
    memset(&khdr, 0, sizeof(khdr));
120
    khdr.version = 1;
80
    khdr.version = 1;
121
    /* This is an append-only list, no need to hold the RCU read lock */
81
    /* This is an append-only list, no need to hold the RCU read lock */
122
+    /* 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,
123
    list_for_each_entry_rcu(qe, &ima_measurements, later, true) {
83
    *buffer_size = ima_kexec_file.count;
124
-        if (file.count < file.size) {
84
    *buffer = ima_kexec_file.buf;
125
+        entry_size += ima_get_binary_runtime_entry_size(qe->entry);
85
out:
126
+        if (entry_size <= segment_size) {
127
            khdr.count++;
128
-            ima_measurements_show(&file, qe);
129
+            ima_measurements_show(&ima_kexec_file, qe);
130
        } else {
131
            ret = -EINVAL;
132
+            pr_err("IMA log file is too big for Kexec buf\n");
133
            break;
134
        }
135
    }
136
137
-    if (ret < 0)
138
-        goto out;
139
-
140
    /*
141
     * fill in reserved space with some buffer details
142
     * (eg. version, buffer size, number of measurements)
143
     */
144
-    khdr.buffer_size = file.count;
145
+    khdr.buffer_size = ima_kexec_file.count;
146
    if (ima_canonical_fmt) {
147
        khdr.version = cpu_to_le16(khdr.version);
148
        khdr.count = cpu_to_le64(khdr.count);
149
        khdr.buffer_size = cpu_to_le64(khdr.buffer_size);
150
    }
151
-    memcpy(file.buf, &khdr, sizeof(khdr));
152
+    memcpy(ima_kexec_file.buf, &khdr, sizeof(khdr));
153
154
    print_hex_dump_debug("ima dump: ", DUMP_PREFIX_NONE, 16, 1,
155
-             file.buf, file.count < 100 ? file.count : 100,
156
+             ima_kexec_file.buf, ima_kexec_file.count < 100 ?
157
+             ima_kexec_file.count : 100,
158
             true);
159
160
-    *buffer_size = file.count;
161
-    *buffer = file.buf;
162
-out:
163
-    if (ret == -EINVAL)
86
-    if (ret == -EINVAL)
164
-        vfree(file.buf);
87
-        vfree(ima_kexec_file.buf);
165
+    *buffer_size = ima_kexec_file.count;
166
+    *buffer = ima_kexec_file.buf;
167
+
168
    return ret;
88
    return ret;
169
}
89
}
170
171
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
172
173
    /* use more understandable variable names than defined in kbuf */
174
    void *kexec_buffer = NULL;
175
-    size_t kexec_buffer_size;
176
+    size_t kexec_buffer_size = 0;
177
    size_t kexec_segment_size;
178
    int ret;
179
90
180
@@ -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)
181
        return;
92
        return;
182
    }
93
    }
183
94
184
-    ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
185
-                 kexec_segment_size);
186
-    if (!kexec_buffer) {
187
+    ret = ima_alloc_kexec_file_buf(kexec_segment_size);
95
+    ret = ima_alloc_kexec_file_buf(kexec_segment_size);
188
+    if (ret < 0) {
96
+    if (ret < 0) {
189
        pr_err("Not enough memory for the kexec measurement buffer.\n");
97
+        pr_err("Not enough memory for the kexec measurement buffer.\n");
190
        return;
191
    }
192
193
+    ret = ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
194
+                    kexec_segment_size);
195
+    if (ret < 0) {
196
+        pr_err("Failed to dump IMA measurements. Error:%d.\n", ret);
197
+        return;
98
+        return;
198
+    }
99
+    }
199
+
100
+
200
    kbuf.buffer = kexec_buffer;
101
    ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
201
    kbuf.bufsz = kexec_buffer_size;
102
                 kexec_segment_size);
202
    kbuf.memsz = kexec_segment_size;
103
    if (!kexec_buffer) {
203
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
204
    image->ima_buffer_size = kexec_segment_size;
205
    image->ima_buffer = kexec_buffer;
206
207
+    /*
208
+     * kexec owns kexec_buffer after kexec_add_buffer() is called
209
+     * and it will vfree() that buffer.
210
+     */
211
+    ima_reset_kexec_file(&ima_kexec_file);
212
+
213
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
214
         kbuf.mem);
215
}
216
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
217
index XXXXXXX..XXXXXXX 100644
218
--- a/security/integrity/ima/ima_queue.c
219
+++ b/security/integrity/ima/ima_queue.c
220
@@ -XXX,XX +XXX,XX @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
221
* binary_runtime_measurement list entry, which contains a
222
* couple of variable length fields (e.g template name and data).
223
*/
224
-static int get_binary_runtime_size(struct ima_template_entry *entry)
225
+int ima_get_binary_runtime_entry_size(struct ima_template_entry *entry)
226
{
227
    int size = 0;
228
229
@@ -XXX,XX +XXX,XX @@ static int ima_add_digest_entry(struct ima_template_entry *entry,
230
    if (binary_runtime_size != ULONG_MAX) {
231
        int size;
232
233
-        size = get_binary_runtime_size(entry);
234
+        size = ima_get_binary_runtime_entry_size(entry);
235
        binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
236
         binary_runtime_size + size : ULONG_MAX;
237
    }
238
--
104
--
239
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
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>
21
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>
22
---
45
---
23
include/linux/kexec.h | 5 ++++
46
include/linux/kexec.h | 6 +++++
24
kernel/kexec_core.c | 54 +++++++++++++++++++++++++++++++++++++++++++
47
kernel/kexec_core.c | 54 +++++++++++++++++++++++++++++++++++++++++++
25
2 files changed, 59 insertions(+)
48
2 files changed, 60 insertions(+)
26
49
27
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
28
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
29
--- a/include/linux/kexec.h
52
--- a/include/linux/kexec.h
30
+++ b/include/linux/kexec.h
53
+++ b/include/linux/kexec.h
...
...
35
+extern void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size);
58
+extern void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size);
36
+extern void kimage_unmap_segment(void *buffer);
59
+extern void kimage_unmap_segment(void *buffer);
37
#else /* !CONFIG_KEXEC_CORE */
60
#else /* !CONFIG_KEXEC_CORE */
38
struct pt_regs;
61
struct pt_regs;
39
struct task_struct;
62
struct task_struct;
40
@@ -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) { }
41
static inline void crash_kexec(struct pt_regs *regs) { }
65
static inline void crash_kexec(struct pt_regs *regs) { }
42
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; }
43
static inline int kexec_crash_loaded(void) { return 0; }
67
static inline int kexec_crash_loaded(void) { return 0; }
44
+static inline void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size)
68
+static inline void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size)
45
+{ return NULL; }
69
+{ return NULL; }
...
...
56
}
80
}
57
81
58
+void *kimage_map_segment(struct kimage *image,
82
+void *kimage_map_segment(struct kimage *image,
59
+             unsigned long addr, unsigned long size)
83
+             unsigned long addr, unsigned long size)
60
+{
84
+{
85
+    unsigned long src_page_addr, dest_page_addr = 0;
61
+    unsigned long eaddr = addr + size;
86
+    unsigned long eaddr = addr + size;
62
+    unsigned long src_page_addr, dest_page_addr;
87
+    kimage_entry_t *ptr, entry;
88
+    struct page **src_pages;
63
+    unsigned int npages;
89
+    unsigned int npages;
64
+    struct page **src_pages;
90
+    void *vaddr = NULL;
65
+    int i;
91
+    int i;
66
+    kimage_entry_t *ptr, entry;
67
+    void *vaddr = NULL;
68
+
92
+
69
+    /*
93
+    /*
70
+     * 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.
71
+     */
95
+     */
72
+    npages = PFN_UP(eaddr) - PFN_DOWN(addr);
96
+    npages = PFN_UP(eaddr) - PFN_DOWN(addr);
...
...
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 execute 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 the calculating and storing digest of the IMA segment in
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
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>
20
Signed-off-by: steven chen <chenste@linux.microsoft.com>
39
Signed-off-by: steven chen <chenste@linux.microsoft.com>
21
Reviewed-by: Stefan Berger <stefanb@linux.ibm.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 | 22 ++++++++++++++++++++++
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, 28 insertions(+)
47
3 files changed, 28 insertions(+)
...
...
96
    image->ima_buffer_size = kexec_segment_size;
117
    image->ima_buffer_size = kexec_segment_size;
97
    image->ima_buffer = kexec_buffer;
118
    image->ima_buffer = kexec_buffer;
98
+    image->ima_segment_index = image->nr_segments - 1;
119
+    image->ima_segment_index = image->nr_segments - 1;
99
+    image->is_ima_segment_index_set = true;
120
+    image->is_ima_segment_index_set = true;
100
121
101
    /*
122
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
102
     * kexec owns kexec_buffer after kexec_add_buffer() is called
123
         kbuf.mem);
103
--
124
--
104
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
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
16
20
17
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
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>
18
Signed-off-by: steven chen <chenste@linux.microsoft.com>
26
Signed-off-by: steven chen <chenste@linux.microsoft.com>
27
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
19
---
28
---
20
include/linux/ima.h | 3 ++
29
include/linux/ima.h | 3 ++
21
security/integrity/ima/ima_kexec.c | 46 ++++++++++++++++++++++++++++++
30
security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++
22
2 files changed, 49 insertions(+)
31
2 files changed, 50 insertions(+)
23
32
24
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
25
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
26
--- a/include/linux/ima.h
35
--- a/include/linux/ima.h
27
+++ b/include/linux/ima.h
36
+++ b/include/linux/ima.h
...
...
46
+#include <linux/reboot.h>
55
+#include <linux/reboot.h>
47
+#include <asm/page.h>
56
+#include <asm/page.h>
48
#include "ima.h"
57
#include "ima.h"
49
58
50
#ifdef CONFIG_IMA_KEXEC
59
#ifdef CONFIG_IMA_KEXEC
60
+static bool ima_kexec_update_registered;
51
static struct seq_file ima_kexec_file;
61
static struct seq_file ima_kexec_file;
52
+static void *ima_kexec_buffer;
62
+static void *ima_kexec_buffer;
53
+static bool ima_kexec_update_registered;
63
54
64
static void ima_free_kexec_file_buf(struct seq_file *sf)
55
static void ima_reset_kexec_file(struct seq_file *sf)
56
{
65
{
57
@@ -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)
58
    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",
59
         kbuf.mem);
68
         kbuf.mem);
60
}
69
}
...
...
66
+                 unsigned long action, void *data)
75
+                 unsigned long action, void *data)
67
+{
76
+{
68
+    return NOTIFY_OK;
77
+    return NOTIFY_OK;
69
+}
78
+}
70
+
79
+
71
+struct notifier_block update_buffer_nb = {
80
+static struct notifier_block update_buffer_nb = {
72
+    .notifier_call = ima_update_kexec_buffer,
81
+    .notifier_call = ima_update_kexec_buffer,
82
+    .priority = INT_MIN
73
+};
83
+};
74
+
84
+
75
+/*
85
+/*
76
+ * 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
77
+ * 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. 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
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>
22
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>
23
---
34
---
24
kernel/kexec_file.c | 8 ++++++
35
kernel/kexec_file.c | 11 +++++++-
25
security/integrity/ima/ima_kexec.c | 43 +++++++++++++++++++-----------
36
security/integrity/ima/ima_kexec.c | 43 ++++++++++++++++++++----------
26
2 files changed, 36 insertions(+), 15 deletions(-)
37
2 files changed, 39 insertions(+), 15 deletions(-)
27
38
28
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
29
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
30
--- a/kernel/kexec_file.c
41
--- a/kernel/kexec_file.c
31
+++ b/kernel/kexec_file.c
42
+++ b/kernel/kexec_file.c
32
@@ -XXX,XX +XXX,XX @@ kimage_validate_signature(struct kimage *image)
43
@@ -XXX,XX +XXX,XX @@ kimage_validate_signature(struct kimage *image)
33
}
44
}
34
#endif
45
#endif
35
46
36
+static void kimage_file_post_load(struct kimage *image)
47
+static int kexec_post_load(struct kimage *image, unsigned long flags)
37
+{
48
+{
38
+    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);
39
+}
54
+}
40
+
55
+
41
/*
56
/*
42
* 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
43
* data from user space, do error checking, prepare segment list
58
* data from user space, do error checking, prepare segment list
44
@@ -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,
45
60
46
    kimage_terminate(image);
61
    kimage_terminate(image);
47
62
48
+    if (!(flags & KEXEC_FILE_ON_CRASH))
63
-    ret = machine_kexec_post_load(image);
49
+        kimage_file_post_load(image);
64
+    ret = kexec_post_load(image, flags);
50
+
51
    ret = machine_kexec_post_load(image);
52
    if (ret)
65
    if (ret)
53
        goto out;
66
        goto out;
67
54
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
55
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
56
--- a/security/integrity/ima/ima_kexec.c
70
--- a/security/integrity/ima/ima_kexec.c
57
+++ b/security/integrity/ima/ima_kexec.c
71
+++ b/security/integrity/ima/ima_kexec.c
58
@@ -XXX,XX +XXX,XX @@
72
@@ -XXX,XX +XXX,XX @@
59
#ifdef CONFIG_IMA_KEXEC
73
#ifdef CONFIG_IMA_KEXEC
74
static bool ima_kexec_update_registered;
60
static struct seq_file ima_kexec_file;
75
static struct seq_file ima_kexec_file;
76
+static size_t kexec_segment_size;
61
static void *ima_kexec_buffer;
77
static void *ima_kexec_buffer;
62
+static size_t kexec_segment_size;
78
63
static bool ima_kexec_update_registered;
79
static void ima_free_kexec_file_buf(struct seq_file *sf)
64
80
@@ -XXX,XX +XXX,XX @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
65
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
66
@@ -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
67
    /* 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;
68
    void *kexec_buffer = NULL;
104
    void *kexec_buffer = NULL;
69
    size_t kexec_buffer_size = 0;
105
-    size_t kexec_buffer_size;
70
-    size_t kexec_segment_size;
106
-    size_t kexec_segment_size;
71
    int ret;
107
    int ret;
72
108
73
    /*
109
    /*
74
@@ -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)
75
        return;
111
        return;
76
    }
112
    }
77
113
78
-    ret = ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
114
-    ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
79
-                    kexec_segment_size);
115
-                 kexec_segment_size);
80
-    if (ret < 0) {
116
-    if (!kexec_buffer) {
81
-        pr_err("Failed to dump IMA measurements. Error:%d.\n", ret);
117
-        pr_err("Not enough memory for the kexec measurement buffer.\n");
82
-        return;
118
-        return;
83
-    }
119
-    }
84
-
120
-
85
    kbuf.buffer = kexec_buffer;
121
    kbuf.buffer = kexec_buffer;
86
    kbuf.bufsz = kexec_buffer_size;
122
    kbuf.bufsz = kexec_buffer_size;
87
    kbuf.memsz = kexec_segment_size;
123
    kbuf.memsz = kexec_segment_size;
88
@@ -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)
89
    image->ima_segment_index = image->nr_segments - 1;
90
    image->is_ima_segment_index_set = true;
91
92
-    /*
93
-     * kexec owns kexec_buffer after kexec_add_buffer() is called
94
-     * and it will vfree() that buffer.
95
-     */
96
-    ima_reset_kexec_file(&ima_kexec_file);
97
-
98
    kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
99
         kbuf.mem);
100
}
101
@@ -XXX,XX +XXX,XX @@ void ima_add_kexec_buffer(struct kimage *image)
102
static int ima_update_kexec_buffer(struct notifier_block *self,
125
static int ima_update_kexec_buffer(struct notifier_block *self,
103
                 unsigned long action, void *data)
126
                 unsigned long action, void *data)
104
{
127
{
105
-    return NOTIFY_OK;
128
-    return NOTIFY_OK;
106
+    void *buf = NULL;
107
+    size_t buf_size = 0;
129
+    size_t buf_size = 0;
108
+    int ret = NOTIFY_OK;
130
+    int ret = NOTIFY_OK;
131
+    void *buf = NULL;
109
+
132
+
110
+    if (!kexec_in_progress) {
133
+    if (!kexec_in_progress) {
111
+        pr_info("No kexec in progress.\n");
134
+        pr_info("No kexec in progress.\n");
112
+        return ret;
135
+        return ret;
113
+    }
136
+    }
114
+
137
+
115
+    if (!ima_kexec_buffer) {
138
+    if (!ima_kexec_buffer) {
116
+        pr_err("Kexec buffer not set.\n");
139
+        pr_err("Kexec buffer not set.\n");
117
+        return ret;
140
+        return ret;
118
+    }
141
+    }
119
+
142
+
120
+    ret = ima_dump_measurement_list(&buf_size, &buf,
143
+    ret = ima_dump_measurement_list(&buf_size, &buf, kexec_segment_size);
121
+                    kexec_segment_size);
122
+
144
+
123
+    if (ret)
145
+    if (ret)
124
+        pr_err("Dump measurements failed. Error:%d\n", ret);
146
+        pr_err("Dump measurements failed. Error:%d\n", ret);
125
+
147
+
126
+    if (buf_size != 0)
148
+    if (buf_size != 0)
...
...
130
+    ima_kexec_buffer = NULL;
152
+    ima_kexec_buffer = NULL;
131
+
153
+
132
+    return ret;
154
+    return ret;
133
}
155
}
134
156
135
struct notifier_block update_buffer_nb = {
157
static struct notifier_block update_buffer_nb = {
136
--
158
--
137
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
...
...
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
---
18
---
18
security/integrity/ima/Kconfig | 10 ++++++++++
19
security/integrity/ima/Kconfig | 10 ++++++++++
19
security/integrity/ima/ima_kexec.c | 16 ++++++++++------
20
security/integrity/ima/ima_kexec.c | 16 +++++++++++-----
20
2 files changed, 20 insertions(+), 6 deletions(-)
21
2 files changed, 21 insertions(+), 5 deletions(-)
21
22
22
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
23
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
24
--- a/security/integrity/ima/Kconfig
25
--- a/security/integrity/ima/Kconfig
25
+++ b/security/integrity/ima/Kconfig
26
+++ b/security/integrity/ima/Kconfig
...
...
44
+++ b/security/integrity/ima/ima_kexec.c
45
+++ b/security/integrity/ima/ima_kexec.c
45
@@ -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)
46
                 .buf_min = 0, .buf_max = ULONG_MAX,
47
                 .buf_min = 0, .buf_max = ULONG_MAX,
47
                 .top_down = true };
48
                 .top_down = true };
48
    unsigned long binary_runtime_size;
49
    unsigned long binary_runtime_size;
49
-
50
+    unsigned long extra_memory;
50
+    unsigned long extra_memory;
51
51
    /* use more understandable variable names than defined in kbuf */
52
    /* use more understandable variable names than defined in kbuf */
52
    void *kexec_buffer = NULL;
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
    int ret;
55
    int ret;
55
56
56
    /*
57
    /*
57
-     * Reserve an extra half page of memory for additional measurements
58
-     * Reserve an extra half page of memory for additional measurements
58
-     * added during the kexec load.
59
-     * added during the kexec load.
...
...
61
-    binary_runtime_size = ima_get_binary_runtime_size();
62
-    binary_runtime_size = ima_get_binary_runtime_size();
62
+    if (CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB <= 0)
63
+    if (CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB <= 0)
63
+        extra_memory = PAGE_SIZE / 2;
64
+        extra_memory = PAGE_SIZE / 2;
64
+    else
65
+    else
65
+        extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
66
+        extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
67
+
66
+    binary_runtime_size = ima_get_binary_runtime_size() + extra_memory;
68
+    binary_runtime_size = ima_get_binary_runtime_size() + extra_memory;
67
+
69
+
68
    if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
70
    if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
69
        kexec_segment_size = ULONG_MAX;
71
        kexec_segment_size = ULONG_MAX;
70
    else
72
    else
...
...
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
The 'kexec_load' event IMA log can be found using the following command:
20
These critical data events are displayed as hex encoded ascii in the
21
sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements |
21
ascii_runtime_measurement_list. Verifying the critical data hash requires
22
grep kexec_load
22
calculating the hash of the decoded ascii string.
23
23
24
The 'kexec_load' event IMA log can be found using the following command:
24
For example, to verify the 'kexec_load' data hash:
25
sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements |
25
26
grep kexec_execute
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
27
34
28
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
35
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
29
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>
30
---
38
---
31
security/integrity/ima/ima.h | 6 ++++++
39
security/integrity/ima/ima.h | 6 ++++++
32
security/integrity/ima/ima_kexec.c | 21 +++++++++++++++++++++
40
security/integrity/ima/ima_kexec.c | 21 +++++++++++++++++++++
33
security/integrity/ima/ima_queue.c | 5 +++++
41
security/integrity/ima/ima_queue.c | 5 +++++
34
3 files changed, 32 insertions(+)
42
3 files changed, 32 insertions(+)
...
...
58
#include "ima.h"
66
#include "ima.h"
59
67
60
#ifdef CONFIG_IMA_KEXEC
68
#ifdef CONFIG_IMA_KEXEC
61
+#define IMA_KEXEC_EVENT_LEN 256
69
+#define IMA_KEXEC_EVENT_LEN 256
62
+
70
+
71
static bool ima_kexec_update_registered;
63
static struct seq_file ima_kexec_file;
72
static struct seq_file ima_kexec_file;
64
static void *ima_kexec_buffer;
65
static size_t kexec_segment_size;
73
static size_t kexec_segment_size;
66
@@ -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)
67
    ima_reset_kexec_file(sf);
75
    sf->count = 0;
68
}
76
}
69
77
70
+void ima_measure_kexec_event(const char *event_name)
78
+void ima_measure_kexec_event(const char *event_name)
71
+{
79
+{
72
+    char ima_kexec_event[IMA_KEXEC_EVENT_LEN];
80
+    char ima_kexec_event[IMA_KEXEC_EVENT_LEN];
73
+    size_t buf_size = 0;
81
+    size_t buf_size = 0;
74
+    long len;
82
+    long len;
83
+    int n;
75
+
84
+
76
+    buf_size = ima_get_binary_runtime_size();
85
+    buf_size = ima_get_binary_runtime_size();
77
+    len = atomic_long_read(&ima_htable.len);
86
+    len = atomic_long_read(&ima_htable.len);
78
+
87
+
79
+    scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN,
88
+    n = scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN,
80
+         "kexec_segment_size=%lu;ima_binary_runtime_size=%lu;"
89
+         "kexec_segment_size=%lu;ima_binary_runtime_size=%lu;"
81
+         "ima_runtime_measurements_count=%ld;",
90
+         "ima_runtime_measurements_count=%ld;",
82
+         kexec_segment_size, buf_size, len);
91
+         kexec_segment_size, buf_size, len);
83
+
92
+
84
+    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);
85
+                 strlen(ima_kexec_event), false, NULL, 0);
86
+}
94
+}
87
+
95
+
88
static int ima_alloc_kexec_file_buf(size_t segment_size)
96
static int ima_alloc_kexec_file_buf(size_t segment_size)
89
{
97
{
90
    /*
98
    /*
...
...
diff view generated by jsdifflib