Skip to content

Commit d54e17b

Browse files
committed
Merge branch 'next-integrity.defer-measuring-keys' into next-integrity
From patch set cover letter: The IMA subsystem supports measuring asymmetric keys when the key is created or updated[1]. But keys created or updated before a custom IMA policy is loaded are currently not measured. This includes keys added, for instance, to either the .ima or .builtin_trusted_keys keyrings, which happens early in the boot process. Measuring the early boot keys, by design, requires loading a custom IMA policy. This change adds support for queuing keys created or updated before a custom IMA policy is loaded. The queued keys are processed when a custom policy is loaded. Keys created or updated after a custom policy is loaded are measured immediately (not queued). In the case when a custom policy is not loaded within 5 minutes of IMA initialization, the queued keys are freed. [1] https://lore.kernel.org/linux-integrity/[email protected]/
2 parents 5c7bac9 + 5b3014b commit d54e17b

File tree

7 files changed

+220
-1
lines changed

7 files changed

+220
-1
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: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,30 @@ 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+
void ima_init_key_queue(void);
219+
bool ima_should_queue_key(void);
220+
bool ima_queue_key(struct key *keyring, const void *payload,
221+
size_t payload_len);
222+
void ima_process_queued_keys(void);
223+
#else
224+
static inline void ima_init_key_queue(void) {}
225+
static inline bool ima_should_queue_key(void) { return false; }
226+
static inline bool ima_queue_key(struct key *keyring,
227+
const void *payload,
228+
size_t payload_len) { return false; }
229+
static inline void ima_process_queued_keys(void) {}
230+
#endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
231+
208232
/* LIM API function definitions */
209233
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
210234
int mask, enum ima_hooks func, int *pcr,

security/integrity/ima/ima_asymmetric_keys.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,21 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
3030
const void *payload, size_t payload_len,
3131
unsigned long flags, bool create)
3232
{
33+
bool queued = false;
34+
3335
/* Only asymmetric keys are handled by this hook. */
3436
if (key->type != &key_type_asymmetric)
3537
return;
3638

3739
if (!payload || (payload_len == 0))
3840
return;
3941

42+
if (ima_should_queue_key())
43+
queued = ima_queue_key(keyring, payload, payload_len);
44+
45+
if (queued)
46+
return;
47+
4048
/*
4149
* keyring->description points to the name of the keyring
4250
* (such as ".builtin_trusted_keys", ".ima", etc.) to

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_policy.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,9 @@ void ima_update_policy(void)
809809
kfree(arch_policy_entry);
810810
}
811811
ima_update_policy_flag();
812+
813+
/* Custom IMA policy has been loaded */
814+
ima_process_queued_keys();
812815
}
813816

814817
/* Keep the enumeration in sync with the policy_tokens! */
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
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 <linux/workqueue.h>
14+
#include <keys/asymmetric-type.h>
15+
#include "ima.h"
16+
17+
/*
18+
* Flag to indicate whether a key can be processed
19+
* right away or should be queued for processing later.
20+
*/
21+
static bool ima_process_keys;
22+
23+
/*
24+
* To synchronize access to the list of keys that need to be measured
25+
*/
26+
static DEFINE_MUTEX(ima_keys_lock);
27+
static LIST_HEAD(ima_keys);
28+
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+
59+
static void ima_free_key_entry(struct ima_key_entry *entry)
60+
{
61+
if (entry) {
62+
kfree(entry->payload);
63+
kfree(entry->keyring_name);
64+
kfree(entry);
65+
}
66+
}
67+
68+
static struct ima_key_entry *ima_alloc_key_entry(struct key *keyring,
69+
const void *payload,
70+
size_t payload_len)
71+
{
72+
int rc = 0;
73+
struct ima_key_entry *entry;
74+
75+
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
76+
if (entry) {
77+
entry->payload = kmemdup(payload, payload_len, GFP_KERNEL);
78+
entry->keyring_name = kstrdup(keyring->description,
79+
GFP_KERNEL);
80+
entry->payload_len = payload_len;
81+
}
82+
83+
if ((entry == NULL) || (entry->payload == NULL) ||
84+
(entry->keyring_name == NULL)) {
85+
rc = -ENOMEM;
86+
goto out;
87+
}
88+
89+
INIT_LIST_HEAD(&entry->list);
90+
91+
out:
92+
if (rc) {
93+
ima_free_key_entry(entry);
94+
entry = NULL;
95+
}
96+
97+
return entry;
98+
}
99+
100+
bool ima_queue_key(struct key *keyring, const void *payload,
101+
size_t payload_len)
102+
{
103+
bool queued = false;
104+
struct ima_key_entry *entry;
105+
106+
entry = ima_alloc_key_entry(keyring, payload, payload_len);
107+
if (!entry)
108+
return false;
109+
110+
mutex_lock(&ima_keys_lock);
111+
if (!ima_process_keys) {
112+
list_add_tail(&entry->list, &ima_keys);
113+
queued = true;
114+
}
115+
mutex_unlock(&ima_keys_lock);
116+
117+
if (!queued)
118+
ima_free_key_entry(entry);
119+
120+
return queued;
121+
}
122+
123+
/*
124+
* ima_process_queued_keys() - process keys queued for measurement
125+
*
126+
* This function sets ima_process_keys to true and processes queued keys.
127+
* From here on keys will be processed right away (not queued).
128+
*/
129+
void ima_process_queued_keys(void)
130+
{
131+
struct ima_key_entry *entry, *tmp;
132+
bool process = false;
133+
134+
if (ima_process_keys)
135+
return;
136+
137+
/*
138+
* Since ima_process_keys is set to true, any new key will be
139+
* processed immediately and not be queued to ima_keys list.
140+
* First one setting the ima_process_keys flag to true will
141+
* process the queued keys.
142+
*/
143+
mutex_lock(&ima_keys_lock);
144+
if (!ima_process_keys) {
145+
ima_process_keys = true;
146+
process = true;
147+
}
148+
mutex_unlock(&ima_keys_lock);
149+
150+
if (!process)
151+
return;
152+
153+
if (!timer_expired)
154+
cancel_delayed_work_sync(&ima_keys_delayed_work);
155+
156+
list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
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);
163+
list_del(&entry->list);
164+
ima_free_key_entry(entry);
165+
}
166+
}
167+
168+
inline bool ima_should_queue_key(void)
169+
{
170+
return !ima_process_keys;
171+
}

0 commit comments

Comments
 (0)