Skip to content

Commit 254ef95

Browse files
stefanbergermimizohar
authored andcommitted
ima: Suspend PCR extends and log appends when rebooting
To avoid the following types of error messages due to a failure by the TPM driver to use the TPM, suspend TPM PCR extensions and the appending of entries to the IMA log once IMA's reboot notifier has been called. This avoids trying to use the TPM after the TPM subsystem has been shut down. [111707.685315][ T1] ima: Error Communicating to TPM chip, result: -19 [111707.685960][ T1] ima: Error Communicating to TPM chip, result: -19 Synchronization with the ima_extend_list_mutex to set ima_measurements_suspended ensures that the TPM subsystem is not shut down when IMA holds the mutex while appending to the log and extending the PCR. The alternative of reading the system_state variable would not provide this guarantee. This error could be observed on a ppc64 machine running SuSE Linux where processes are still accessing files after devices have been shut down. Suspending the IMA log and PCR extensions shortly before reboot does not seem to open a significant measurement gap since neither TPM quoting would work for attestation nor that new log entries could be written to anywhere after devices have been shut down. However, there's a time window between the invocation of the reboot notifier and the shutdown of devices. This includes all subsequently invoked reboot notifiers as well as kernel_restart_prepare() where __usermodehelper_disable() waits for all running_helpers to exit. During this time window IMA could now miss log entries even though attestation would still work. The reboot of the system shortly after may make this small gap insignificant. Signed-off-by: Tushar Sugandhi <[email protected]> Signed-off-by: Stefan Berger <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Mimi Zohar <[email protected]>
1 parent fac04ef commit 254ef95

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

security/integrity/ima/ima.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ unsigned long ima_get_binary_runtime_size(void);
278278
int ima_init_template(void);
279279
void ima_init_template_list(void);
280280
int __init ima_init_digests(void);
281+
void __init ima_init_reboot_notifier(void);
281282
int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
282283
void *lsm_data);
283284

security/integrity/ima/ima_init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ int __init ima_init(void)
152152

153153
ima_init_key_queue();
154154

155+
ima_init_reboot_notifier();
156+
155157
ima_measure_critical_data("kernel_info", "kernel_version",
156158
UTS_RELEASE, strlen(UTS_RELEASE), false,
157159
NULL, 0);

security/integrity/ima/ima_queue.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
#include <linux/rculist.h>
19+
#include <linux/reboot.h>
1920
#include <linux/slab.h>
2021
#include "ima.h"
2122

@@ -44,6 +45,12 @@ struct ima_h_table ima_htable = {
4445
*/
4546
static DEFINE_MUTEX(ima_extend_list_mutex);
4647

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+
4754
/* lookup up the digest value in the hash table, and return the entry */
4855
static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
4956
int pcr)
@@ -168,6 +175,18 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
168175
int result = 0, tpmresult = 0;
169176

170177
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+
171190
if (!violation && !IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE)) {
172191
if (ima_lookup_digest_entry(digest, entry->pcr)) {
173192
audit_cause = "hash_exists";
@@ -211,6 +230,31 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry)
211230
return result;
212231
}
213232

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+
214258
int __init ima_init_digests(void)
215259
{
216260
u16 digest_size;

0 commit comments

Comments
 (0)