Skip to content

Commit 9f81a2e

Browse files
nramasmimizohar
authored andcommitted
IMA: Define workqueue for early boot key measurements
Measuring keys requires a custom IMA policy to be loaded. Keys created or updated before a custom IMA policy is loaded should be queued and will be processed after a custom policy is loaded. This patch defines a workqueue for queuing keys when a custom IMA policy has not yet been loaded. An intermediate Kconfig boolean option namely IMA_QUEUE_EARLY_BOOT_KEYS is used to declare the workqueue functions. A flag namely ima_process_keys is used to check if the key should be queued or should be processed immediately. Signed-off-by: Lakshmi Ramasubramanian <[email protected]> Signed-off-by: Mimi Zohar <[email protected]>
1 parent 5c7bac9 commit 9f81a2e

File tree

4 files changed

+166
-0
lines changed

4 files changed

+166
-0
lines changed

security/integrity/ima/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,9 @@ config IMA_MEASURE_ASYMMETRIC_KEYS
316316
depends on IMA
317317
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
318318
default y
319+
320+
config IMA_QUEUE_EARLY_BOOT_KEYS
321+
bool
322+
depends on IMA_MEASURE_ASYMMETRIC_KEYS
323+
depends on SYSTEM_TRUSTED_KEYRING
324+
default y

security/integrity/ima/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
1313
ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
1414
obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
1515
obj-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o
16+
obj-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o

security/integrity/ima/ima.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,28 @@ extern const char *const func_tokens[];
205205

206206
struct modsig;
207207

208+
#ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS
209+
/*
210+
* To track keys that need to be measured.
211+
*/
212+
struct ima_key_entry {
213+
struct list_head list;
214+
void *payload;
215+
size_t payload_len;
216+
char *keyring_name;
217+
};
218+
bool ima_should_queue_key(void);
219+
bool ima_queue_key(struct key *keyring, const void *payload,
220+
size_t payload_len);
221+
void ima_process_queued_keys(void);
222+
#else
223+
static inline bool ima_should_queue_key(void) { return false; }
224+
static inline bool ima_queue_key(struct key *keyring,
225+
const void *payload,
226+
size_t payload_len) { return false; }
227+
static inline void ima_process_queued_keys(void) {}
228+
#endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
229+
208230
/* LIM API function definitions */
209231
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
210232
int mask, enum ima_hooks func, int *pcr,
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (C) 2019 Microsoft Corporation
4+
*
5+
* Author: Lakshmi Ramasubramanian ([email protected])
6+
*
7+
* File: ima_queue_keys.c
8+
* Enables deferred processing of keys
9+
*/
10+
11+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12+
13+
#include <keys/asymmetric-type.h>
14+
#include "ima.h"
15+
16+
/*
17+
* Flag to indicate whether a key can be processed
18+
* right away or should be queued for processing later.
19+
*/
20+
static bool ima_process_keys;
21+
22+
/*
23+
* To synchronize access to the list of keys that need to be measured
24+
*/
25+
static DEFINE_MUTEX(ima_keys_lock);
26+
static LIST_HEAD(ima_keys);
27+
28+
static void ima_free_key_entry(struct ima_key_entry *entry)
29+
{
30+
if (entry) {
31+
kfree(entry->payload);
32+
kfree(entry->keyring_name);
33+
kfree(entry);
34+
}
35+
}
36+
37+
static struct ima_key_entry *ima_alloc_key_entry(struct key *keyring,
38+
const void *payload,
39+
size_t payload_len)
40+
{
41+
int rc = 0;
42+
struct ima_key_entry *entry;
43+
44+
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
45+
if (entry) {
46+
entry->payload = kmemdup(payload, payload_len, GFP_KERNEL);
47+
entry->keyring_name = kstrdup(keyring->description,
48+
GFP_KERNEL);
49+
entry->payload_len = payload_len;
50+
}
51+
52+
if ((entry == NULL) || (entry->payload == NULL) ||
53+
(entry->keyring_name == NULL)) {
54+
rc = -ENOMEM;
55+
goto out;
56+
}
57+
58+
INIT_LIST_HEAD(&entry->list);
59+
60+
out:
61+
if (rc) {
62+
ima_free_key_entry(entry);
63+
entry = NULL;
64+
}
65+
66+
return entry;
67+
}
68+
69+
bool ima_queue_key(struct key *keyring, const void *payload,
70+
size_t payload_len)
71+
{
72+
bool queued = false;
73+
struct ima_key_entry *entry;
74+
75+
entry = ima_alloc_key_entry(keyring, payload, payload_len);
76+
if (!entry)
77+
return false;
78+
79+
mutex_lock(&ima_keys_lock);
80+
if (!ima_process_keys) {
81+
list_add_tail(&entry->list, &ima_keys);
82+
queued = true;
83+
}
84+
mutex_unlock(&ima_keys_lock);
85+
86+
if (!queued)
87+
ima_free_key_entry(entry);
88+
89+
return queued;
90+
}
91+
92+
/*
93+
* ima_process_queued_keys() - process keys queued for measurement
94+
*
95+
* This function sets ima_process_keys to true and processes queued keys.
96+
* From here on keys will be processed right away (not queued).
97+
*/
98+
void ima_process_queued_keys(void)
99+
{
100+
struct ima_key_entry *entry, *tmp;
101+
bool process = false;
102+
103+
if (ima_process_keys)
104+
return;
105+
106+
/*
107+
* Since ima_process_keys is set to true, any new key will be
108+
* processed immediately and not be queued to ima_keys list.
109+
* First one setting the ima_process_keys flag to true will
110+
* process the queued keys.
111+
*/
112+
mutex_lock(&ima_keys_lock);
113+
if (!ima_process_keys) {
114+
ima_process_keys = true;
115+
process = true;
116+
}
117+
mutex_unlock(&ima_keys_lock);
118+
119+
if (!process)
120+
return;
121+
122+
123+
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);
129+
list_del(&entry->list);
130+
ima_free_key_entry(entry);
131+
}
132+
}
133+
134+
inline bool ima_should_queue_key(void)
135+
{
136+
return !ima_process_keys;
137+
}

0 commit comments

Comments
 (0)