|
16 | 16 | */
|
17 | 17 |
|
18 | 18 | #include <linux/rculist.h>
|
| 19 | +#include <linux/reboot.h> |
19 | 20 | #include <linux/slab.h>
|
20 | 21 | #include "ima.h"
|
21 | 22 |
|
@@ -44,6 +45,12 @@ struct ima_h_table ima_htable = {
|
44 | 45 | */
|
45 | 46 | static DEFINE_MUTEX(ima_extend_list_mutex);
|
46 | 47 |
|
| 48 | +/* |
| 49 | + * Used internally by the kernel to suspend measurements. |
| 50 | + * Protected by ima_extend_list_mutex. |
| 51 | + */ |
| 52 | +static bool ima_measurements_suspended; |
| 53 | + |
47 | 54 | /* lookup up the digest value in the hash table, and return the entry */
|
48 | 55 | static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
|
49 | 56 | int pcr)
|
@@ -168,6 +175,18 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
|
168 | 175 | int result = 0, tpmresult = 0;
|
169 | 176 |
|
170 | 177 | mutex_lock(&ima_extend_list_mutex);
|
| 178 | + |
| 179 | + /* |
| 180 | + * Avoid appending to the measurement log when the TPM subsystem has |
| 181 | + * been shut down while preparing for system reboot. |
| 182 | + */ |
| 183 | + if (ima_measurements_suspended) { |
| 184 | + audit_cause = "measurements_suspended"; |
| 185 | + audit_info = 0; |
| 186 | + result = -ENODEV; |
| 187 | + goto out; |
| 188 | + } |
| 189 | + |
171 | 190 | if (!violation && !IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE)) {
|
172 | 191 | if (ima_lookup_digest_entry(digest, entry->pcr)) {
|
173 | 192 | audit_cause = "hash_exists";
|
@@ -211,6 +230,31 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry)
|
211 | 230 | return result;
|
212 | 231 | }
|
213 | 232 |
|
| 233 | +static void ima_measurements_suspend(void) |
| 234 | +{ |
| 235 | + mutex_lock(&ima_extend_list_mutex); |
| 236 | + ima_measurements_suspended = true; |
| 237 | + mutex_unlock(&ima_extend_list_mutex); |
| 238 | +} |
| 239 | + |
| 240 | +static int ima_reboot_notifier(struct notifier_block *nb, |
| 241 | + unsigned long action, |
| 242 | + void *data) |
| 243 | +{ |
| 244 | + ima_measurements_suspend(); |
| 245 | + |
| 246 | + return NOTIFY_DONE; |
| 247 | +} |
| 248 | + |
| 249 | +static struct notifier_block ima_reboot_nb = { |
| 250 | + .notifier_call = ima_reboot_notifier, |
| 251 | +}; |
| 252 | + |
| 253 | +void __init ima_init_reboot_notifier(void) |
| 254 | +{ |
| 255 | + register_reboot_notifier(&ima_reboot_nb); |
| 256 | +} |
| 257 | + |
214 | 258 | int __init ima_init_digests(void)
|
215 | 259 | {
|
216 | 260 | u16 digest_size;
|
|
0 commit comments