Skip to content

Commit 5b3014b

Browse files
nramasmimizohar
authored andcommitted
IMA: Defined delayed workqueue to free the queued keys
Keys queued for measurement should be freed if a custom IMA policy was not loaded. Otherwise, the keys will remain queued forever consuming kernel memory. This patch defines a delayed workqueue to handle the above scenario. The workqueue handler is setup to execute 5 minutes after IMA initialization is completed. If a custom IMA policy is loaded before the workqueue handler is scheduled to execute, the workqueue task is cancelled and any queued keys are processed for measurement. But if a custom policy was not loaded then the queued keys are just freed when the delayed workqueue handler is run. Signed-off-by: Lakshmi Ramasubramanian <[email protected]> Reported-by: kernel test robot <[email protected]> # sleeping function called from invalid context Reported-by: kbuild test robot <[email protected]> # redefinition of ima_init_key_queue() function. Signed-off-by: Mimi Zohar <[email protected]>
1 parent 450d0fd commit 5b3014b

File tree

3 files changed

+48
-6
lines changed

3 files changed

+48
-6
lines changed

security/integrity/ima/ima.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,13 @@ struct ima_key_entry {
215215
size_t payload_len;
216216
char *keyring_name;
217217
};
218+
void ima_init_key_queue(void);
218219
bool ima_should_queue_key(void);
219220
bool ima_queue_key(struct key *keyring, const void *payload,
220221
size_t payload_len);
221222
void ima_process_queued_keys(void);
222223
#else
224+
static inline void ima_init_key_queue(void) {}
223225
static inline bool ima_should_queue_key(void) { return false; }
224226
static inline bool ima_queue_key(struct key *keyring,
225227
const void *payload,

security/integrity/ima/ima_init.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,11 @@ int __init ima_init(void)
131131

132132
ima_init_policy();
133133

134-
return ima_fs_init();
134+
rc = ima_fs_init();
135+
if (rc != 0)
136+
return rc;
137+
138+
ima_init_key_queue();
139+
140+
return rc;
135141
}

security/integrity/ima/ima_queue_keys.c

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1212

13+
#include <linux/workqueue.h>
1314
#include <keys/asymmetric-type.h>
1415
#include "ima.h"
1516

@@ -25,6 +26,36 @@ static bool ima_process_keys;
2526
static DEFINE_MUTEX(ima_keys_lock);
2627
static LIST_HEAD(ima_keys);
2728

29+
/*
30+
* If custom IMA policy is not loaded then keys queued up
31+
* for measurement should be freed. This worker is used
32+
* for handling this scenario.
33+
*/
34+
static long ima_key_queue_timeout = 300000; /* 5 Minutes */
35+
static void ima_keys_handler(struct work_struct *work);
36+
static DECLARE_DELAYED_WORK(ima_keys_delayed_work, ima_keys_handler);
37+
static bool timer_expired;
38+
39+
/*
40+
* This worker function frees keys that may still be
41+
* queued up in case custom IMA policy was not loaded.
42+
*/
43+
static void ima_keys_handler(struct work_struct *work)
44+
{
45+
timer_expired = true;
46+
ima_process_queued_keys();
47+
}
48+
49+
/*
50+
* This function sets up a worker to free queued keys in case
51+
* custom IMA policy was never loaded.
52+
*/
53+
void ima_init_key_queue(void)
54+
{
55+
schedule_delayed_work(&ima_keys_delayed_work,
56+
msecs_to_jiffies(ima_key_queue_timeout));
57+
}
58+
2859
static void ima_free_key_entry(struct ima_key_entry *entry)
2960
{
3061
if (entry) {
@@ -119,13 +150,16 @@ void ima_process_queued_keys(void)
119150
if (!process)
120151
return;
121152

153+
if (!timer_expired)
154+
cancel_delayed_work_sync(&ima_keys_delayed_work);
122155

123156
list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
124-
process_buffer_measurement(entry->payload,
125-
entry->payload_len,
126-
entry->keyring_name,
127-
KEY_CHECK, 0,
128-
entry->keyring_name);
157+
if (!timer_expired)
158+
process_buffer_measurement(entry->payload,
159+
entry->payload_len,
160+
entry->keyring_name,
161+
KEY_CHECK, 0,
162+
entry->keyring_name);
129163
list_del(&entry->list);
130164
ima_free_key_entry(entry);
131165
}

0 commit comments

Comments
 (0)