]>
Commit | Line | Data |
---|---|---|
9f81a2ed LR |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2019 Microsoft Corporation | |
4 | * | |
5 | * Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com) | |
6 | * | |
7 | * File: ima_queue_keys.c | |
8 | * Enables deferred processing of keys | |
9 | */ | |
10 | ||
a2d2329e | 11 | #include <linux/user_namespace.h> |
5b3014b9 | 12 | #include <linux/workqueue.h> |
9f81a2ed LR |
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 | ||
5b3014b9 LR |
28 | /* |
29 | * If custom IMA policy is not loaded then keys queued up | |
30 | * for measurement should be freed. This worker is used | |
31 | * for handling this scenario. | |
32 | */ | |
33 | static long ima_key_queue_timeout = 300000; /* 5 Minutes */ | |
34 | static void ima_keys_handler(struct work_struct *work); | |
35 | static DECLARE_DELAYED_WORK(ima_keys_delayed_work, ima_keys_handler); | |
36 | static bool timer_expired; | |
37 | ||
38 | /* | |
39 | * This worker function frees keys that may still be | |
40 | * queued up in case custom IMA policy was not loaded. | |
41 | */ | |
42 | static void ima_keys_handler(struct work_struct *work) | |
43 | { | |
44 | timer_expired = true; | |
45 | ima_process_queued_keys(); | |
46 | } | |
47 | ||
48 | /* | |
49 | * This function sets up a worker to free queued keys in case | |
50 | * custom IMA policy was never loaded. | |
51 | */ | |
52 | void ima_init_key_queue(void) | |
53 | { | |
54 | schedule_delayed_work(&ima_keys_delayed_work, | |
55 | msecs_to_jiffies(ima_key_queue_timeout)); | |
56 | } | |
57 | ||
9f81a2ed LR |
58 | static void ima_free_key_entry(struct ima_key_entry *entry) |
59 | { | |
60 | if (entry) { | |
61 | kfree(entry->payload); | |
62 | kfree(entry->keyring_name); | |
63 | kfree(entry); | |
64 | } | |
65 | } | |
66 | ||
67 | static struct ima_key_entry *ima_alloc_key_entry(struct key *keyring, | |
68 | const void *payload, | |
69 | size_t payload_len) | |
70 | { | |
71 | int rc = 0; | |
34e980bb | 72 | const char *audit_cause = "ENOMEM"; |
9f81a2ed LR |
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) { | |
34e980bb LR |
93 | integrity_audit_message(AUDIT_INTEGRITY_PCR, NULL, |
94 | keyring->description, | |
95 | func_measure_str(KEY_CHECK), | |
96 | audit_cause, rc, 0, rc); | |
9f81a2ed LR |
97 | ima_free_key_entry(entry); |
98 | entry = NULL; | |
99 | } | |
100 | ||
101 | return entry; | |
102 | } | |
103 | ||
104 | bool ima_queue_key(struct key *keyring, const void *payload, | |
105 | size_t payload_len) | |
106 | { | |
107 | bool queued = false; | |
108 | struct ima_key_entry *entry; | |
109 | ||
110 | entry = ima_alloc_key_entry(keyring, payload, payload_len); | |
111 | if (!entry) | |
112 | return false; | |
113 | ||
114 | mutex_lock(&ima_keys_lock); | |
115 | if (!ima_process_keys) { | |
116 | list_add_tail(&entry->list, &ima_keys); | |
117 | queued = true; | |
118 | } | |
119 | mutex_unlock(&ima_keys_lock); | |
120 | ||
121 | if (!queued) | |
122 | ima_free_key_entry(entry); | |
123 | ||
124 | return queued; | |
125 | } | |
126 | ||
127 | /* | |
128 | * ima_process_queued_keys() - process keys queued for measurement | |
129 | * | |
130 | * This function sets ima_process_keys to true and processes queued keys. | |
131 | * From here on keys will be processed right away (not queued). | |
132 | */ | |
133 | void ima_process_queued_keys(void) | |
134 | { | |
135 | struct ima_key_entry *entry, *tmp; | |
136 | bool process = false; | |
137 | ||
138 | if (ima_process_keys) | |
139 | return; | |
140 | ||
141 | /* | |
142 | * Since ima_process_keys is set to true, any new key will be | |
143 | * processed immediately and not be queued to ima_keys list. | |
144 | * First one setting the ima_process_keys flag to true will | |
145 | * process the queued keys. | |
146 | */ | |
147 | mutex_lock(&ima_keys_lock); | |
148 | if (!ima_process_keys) { | |
149 | ima_process_keys = true; | |
150 | process = true; | |
151 | } | |
152 | mutex_unlock(&ima_keys_lock); | |
153 | ||
154 | if (!process) | |
155 | return; | |
156 | ||
5b3014b9 LR |
157 | if (!timer_expired) |
158 | cancel_delayed_work_sync(&ima_keys_delayed_work); | |
9f81a2ed LR |
159 | |
160 | list_for_each_entry_safe(entry, tmp, &ima_keys, list) { | |
5b3014b9 | 161 | if (!timer_expired) |
a2d2329e CB |
162 | process_buffer_measurement(&init_user_ns, NULL, |
163 | entry->payload, | |
5b3014b9 LR |
164 | entry->payload_len, |
165 | entry->keyring_name, | |
166 | KEY_CHECK, 0, | |
167 | entry->keyring_name); | |
9f81a2ed LR |
168 | list_del(&entry->list); |
169 | ima_free_key_entry(entry); | |
170 | } | |
171 | } | |
172 | ||
173 | inline bool ima_should_queue_key(void) | |
174 | { | |
175 | return !ima_process_keys; | |
176 | } |