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 | |
11 | #include <linux/user_namespace.h> |
12 | #include <linux/workqueue.h> |
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 | /* |
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(dwork: &ima_keys_delayed_work, |
55 | delay: msecs_to_jiffies(m: ima_key_queue_timeout)); |
56 | } |
57 | |
58 | static void ima_free_key_entry(struct ima_key_entry *entry) |
59 | { |
60 | if (entry) { |
61 | kfree(objp: entry->payload); |
62 | kfree(objp: entry->keyring_name); |
63 | kfree(objp: 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; |
72 | const char *audit_cause = "ENOMEM" ; |
73 | struct ima_key_entry *entry; |
74 | |
75 | entry = kzalloc(size: sizeof(*entry), GFP_KERNEL); |
76 | if (entry) { |
77 | entry->payload = kmemdup(p: payload, size: payload_len, GFP_KERNEL); |
78 | entry->keyring_name = kstrdup(s: 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(list: &entry->list); |
90 | |
91 | out: |
92 | if (rc) { |
93 | integrity_audit_message(AUDIT_INTEGRITY_PCR, NULL, |
94 | fname: keyring->description, |
95 | op: func_measure_str(func: KEY_CHECK), |
96 | cause: audit_cause, result: rc, info: 0, errno: rc); |
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(new: &entry->list, head: &ima_keys); |
117 | queued = true; |
118 | } |
119 | mutex_unlock(lock: &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(lock: &ima_keys_lock); |
153 | |
154 | if (!process) |
155 | return; |
156 | |
157 | if (!timer_expired) |
158 | cancel_delayed_work_sync(dwork: &ima_keys_delayed_work); |
159 | |
160 | list_for_each_entry_safe(entry, tmp, &ima_keys, list) { |
161 | if (!timer_expired) |
162 | process_buffer_measurement(idmap: &nop_mnt_idmap, NULL, |
163 | buf: entry->payload, |
164 | size: entry->payload_len, |
165 | eventname: entry->keyring_name, |
166 | func: KEY_CHECK, pcr: 0, |
167 | func_data: entry->keyring_name, |
168 | buf_hash: false, NULL, digest_len: 0); |
169 | list_del(entry: &entry->list); |
170 | ima_free_key_entry(entry); |
171 | } |
172 | } |
173 | |
174 | inline bool ima_should_queue_key(void) |
175 | { |
176 | return !ima_process_keys; |
177 | } |
178 | |