Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2#include <linux/key.h>
3#include <linux/keyctl.h>
4#include <keys/user-type.h>
5#include <linux/crash_dump.h>
6#include <linux/cc_platform.h>
7#include <linux/configfs.h>
8#include <linux/module.h>
9
10#define KEY_NUM_MAX 128 /* maximum dm crypt keys */
11#define KEY_SIZE_MAX 256 /* maximum dm crypt key size */
12#define KEY_DESC_MAX_LEN 128 /* maximum dm crypt key description size */
13
14static unsigned int key_count;
15
16struct dm_crypt_key {
17 unsigned int key_size;
18 char key_desc[KEY_DESC_MAX_LEN];
19 u8 data[KEY_SIZE_MAX];
20};
21
22static struct keys_header {
23 unsigned int total_keys;
24 struct dm_crypt_key keys[] __counted_by(total_keys);
25} *keys_header;
26
27static size_t get_keys_header_size(size_t total_keys)
28{
29 return struct_size(keys_header, keys, total_keys);
30}
31
32unsigned long long dm_crypt_keys_addr;
33EXPORT_SYMBOL_GPL(dm_crypt_keys_addr);
34
35static int __init setup_dmcryptkeys(char *arg)
36{
37 char *end;
38
39 if (!arg)
40 return -EINVAL;
41 dm_crypt_keys_addr = memparse(arg, &end);
42 if (end > arg)
43 return 0;
44
45 dm_crypt_keys_addr = 0;
46 return -EINVAL;
47}
48
49early_param("dmcryptkeys", setup_dmcryptkeys);
50
51/*
52 * Architectures may override this function to read dm crypt keys
53 */
54ssize_t __weak dm_crypt_keys_read(char *buf, size_t count, u64 *ppos)
55{
56 struct kvec kvec = { .iov_base = buf, .iov_len = count };
57 struct iov_iter iter;
58
59 iov_iter_kvec(&iter, READ, &kvec, 1, count);
60 return read_from_oldmem(&iter, count, ppos, cc_platform_has(CC_ATTR_MEM_ENCRYPT));
61}
62
63static int add_key_to_keyring(struct dm_crypt_key *dm_key,
64 key_ref_t keyring_ref)
65{
66 key_ref_t key_ref;
67 int r;
68
69 /* create or update the requested key and add it to the target keyring */
70 key_ref = key_create_or_update(keyring_ref, "user", dm_key->key_desc,
71 dm_key->data, dm_key->key_size,
72 KEY_USR_ALL, KEY_ALLOC_IN_QUOTA);
73
74 if (!IS_ERR(key_ref)) {
75 r = key_ref_to_ptr(key_ref)->serial;
76 key_ref_put(key_ref);
77 kexec_dprintk("Success adding key %s", dm_key->key_desc);
78 } else {
79 r = PTR_ERR(key_ref);
80 kexec_dprintk("Error when adding key");
81 }
82
83 key_ref_put(keyring_ref);
84 return r;
85}
86
87static void get_keys_from_kdump_reserved_memory(void)
88{
89 struct keys_header *keys_header_loaded;
90
91 arch_kexec_unprotect_crashkres();
92
93 keys_header_loaded = kmap_local_page(pfn_to_page(
94 kexec_crash_image->dm_crypt_keys_addr >> PAGE_SHIFT));
95
96 memcpy(keys_header, keys_header_loaded, get_keys_header_size(key_count));
97 kunmap_local(keys_header_loaded);
98 arch_kexec_protect_crashkres();
99}
100
101static int restore_dm_crypt_keys_to_thread_keyring(void)
102{
103 struct dm_crypt_key *key;
104 size_t keys_header_size;
105 key_ref_t keyring_ref;
106 u64 addr;
107
108 /* find the target keyring (which must be writable) */
109 keyring_ref =
110 lookup_user_key(KEY_SPEC_USER_KEYRING, 0x01, KEY_NEED_WRITE);
111 if (IS_ERR(keyring_ref)) {
112 kexec_dprintk("Failed to get the user keyring\n");
113 return PTR_ERR(keyring_ref);
114 }
115
116 addr = dm_crypt_keys_addr;
117 dm_crypt_keys_read((char *)&key_count, sizeof(key_count), &addr);
118 if (key_count < 0 || key_count > KEY_NUM_MAX) {
119 kexec_dprintk("Failed to read the number of dm-crypt keys\n");
120 return -1;
121 }
122
123 kexec_dprintk("There are %u keys\n", key_count);
124 addr = dm_crypt_keys_addr;
125
126 keys_header_size = get_keys_header_size(key_count);
127 keys_header = kzalloc(keys_header_size, GFP_KERNEL);
128 if (!keys_header)
129 return -ENOMEM;
130
131 dm_crypt_keys_read((char *)keys_header, keys_header_size, &addr);
132
133 for (int i = 0; i < keys_header->total_keys; i++) {
134 key = &keys_header->keys[i];
135 kexec_dprintk("Get key (size=%u)\n", key->key_size);
136 add_key_to_keyring(key, keyring_ref);
137 }
138
139 return 0;
140}
141
142static int read_key_from_user_keying(struct dm_crypt_key *dm_key)
143{
144 const struct user_key_payload *ukp;
145 struct key *key;
146 int ret = 0;
147
148 kexec_dprintk("Requesting logon key %s", dm_key->key_desc);
149 key = request_key(&key_type_logon, dm_key->key_desc, NULL);
150
151 if (IS_ERR(key)) {
152 pr_warn("No such logon key %s\n", dm_key->key_desc);
153 return PTR_ERR(key);
154 }
155
156 down_read(&key->sem);
157 ukp = user_key_payload_locked(key);
158 if (!ukp) {
159 ret = -EKEYREVOKED;
160 goto out;
161 }
162
163 if (ukp->datalen > KEY_SIZE_MAX) {
164 pr_err("Key size %u exceeds maximum (%u)\n", ukp->datalen, KEY_SIZE_MAX);
165 ret = -EINVAL;
166 goto out;
167 }
168
169 memcpy(dm_key->data, ukp->data, ukp->datalen);
170 dm_key->key_size = ukp->datalen;
171 kexec_dprintk("Get dm crypt key (size=%u) %s\n", dm_key->key_size,
172 dm_key->key_desc);
173
174out:
175 up_read(&key->sem);
176 key_put(key);
177 return ret;
178}
179
180struct config_key {
181 struct config_item item;
182 const char *description;
183};
184
185static inline struct config_key *to_config_key(struct config_item *item)
186{
187 return container_of(item, struct config_key, item);
188}
189
190static ssize_t config_key_description_show(struct config_item *item, char *page)
191{
192 return sprintf(page, "%s\n", to_config_key(item)->description);
193}
194
195static ssize_t config_key_description_store(struct config_item *item,
196 const char *page, size_t count)
197{
198 struct config_key *config_key = to_config_key(item);
199 size_t len;
200 int ret;
201
202 ret = -EINVAL;
203 len = strcspn(page, "\n");
204
205 if (len > KEY_DESC_MAX_LEN) {
206 pr_err("The key description shouldn't exceed %u characters", KEY_DESC_MAX_LEN);
207 return ret;
208 }
209
210 if (!len)
211 return ret;
212
213 kfree(config_key->description);
214 ret = -ENOMEM;
215 config_key->description = kmemdup_nul(page, len, GFP_KERNEL);
216 if (!config_key->description)
217 return ret;
218
219 return count;
220}
221
222CONFIGFS_ATTR(config_key_, description);
223
224static struct configfs_attribute *config_key_attrs[] = {
225 &config_key_attr_description,
226 NULL,
227};
228
229static void config_key_release(struct config_item *item)
230{
231 kfree(to_config_key(item));
232 key_count--;
233}
234
235static const struct configfs_item_operations config_key_item_ops = {
236 .release = config_key_release,
237};
238
239static const struct config_item_type config_key_type = {
240 .ct_item_ops = &config_key_item_ops,
241 .ct_attrs = config_key_attrs,
242 .ct_owner = THIS_MODULE,
243};
244
245static struct config_item *config_keys_make_item(struct config_group *group,
246 const char *name)
247{
248 struct config_key *config_key;
249
250 if (key_count > KEY_NUM_MAX) {
251 pr_err("Only %u keys at maximum to be created\n", KEY_NUM_MAX);
252 return ERR_PTR(-EINVAL);
253 }
254
255 config_key = kzalloc_obj(struct config_key);
256 if (!config_key)
257 return ERR_PTR(-ENOMEM);
258
259 config_item_init_type_name(&config_key->item, name, &config_key_type);
260
261 key_count++;
262
263 return &config_key->item;
264}
265
266static ssize_t config_keys_count_show(struct config_item *item, char *page)
267{
268 return sprintf(page, "%d\n", key_count);
269}
270
271CONFIGFS_ATTR_RO(config_keys_, count);
272
273static bool is_dm_key_reused;
274
275static ssize_t config_keys_reuse_show(struct config_item *item, char *page)
276{
277 return sprintf(page, "%d\n", is_dm_key_reused);
278}
279
280static ssize_t config_keys_reuse_store(struct config_item *item,
281 const char *page, size_t count)
282{
283 if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
284 kexec_dprintk(
285 "dm-crypt keys haven't be saved to crash-reserved memory\n");
286 return -EINVAL;
287 }
288
289 if (kstrtobool(page, &is_dm_key_reused))
290 return -EINVAL;
291
292 if (is_dm_key_reused)
293 get_keys_from_kdump_reserved_memory();
294
295 return count;
296}
297
298CONFIGFS_ATTR(config_keys_, reuse);
299
300static struct configfs_attribute *config_keys_attrs[] = {
301 &config_keys_attr_count,
302 &config_keys_attr_reuse,
303 NULL,
304};
305
306/*
307 * Note that, since no extra work is required on ->drop_item(),
308 * no ->drop_item() is provided.
309 */
310static const struct configfs_group_operations config_keys_group_ops = {
311 .make_item = config_keys_make_item,
312};
313
314static const struct config_item_type config_keys_type = {
315 .ct_group_ops = &config_keys_group_ops,
316 .ct_attrs = config_keys_attrs,
317 .ct_owner = THIS_MODULE,
318};
319
320static bool restore;
321
322static ssize_t config_keys_restore_show(struct config_item *item, char *page)
323{
324 return sprintf(page, "%d\n", restore);
325}
326
327static ssize_t config_keys_restore_store(struct config_item *item,
328 const char *page, size_t count)
329{
330 if (!restore)
331 restore_dm_crypt_keys_to_thread_keyring();
332
333 if (kstrtobool(page, &restore))
334 return -EINVAL;
335
336 return count;
337}
338
339CONFIGFS_ATTR(config_keys_, restore);
340
341static struct configfs_attribute *kdump_config_keys_attrs[] = {
342 &config_keys_attr_restore,
343 NULL,
344};
345
346static const struct config_item_type kdump_config_keys_type = {
347 .ct_attrs = kdump_config_keys_attrs,
348 .ct_owner = THIS_MODULE,
349};
350
351static struct configfs_subsystem config_keys_subsys = {
352 .su_group = {
353 .cg_item = {
354 .ci_namebuf = "crash_dm_crypt_keys",
355 .ci_type = &config_keys_type,
356 },
357 },
358};
359
360static int build_keys_header(void)
361{
362 struct config_item *item = NULL;
363 struct config_key *key;
364 int i, r;
365
366 if (keys_header != NULL)
367 kvfree(keys_header);
368
369 keys_header = kzalloc(get_keys_header_size(key_count), GFP_KERNEL);
370 if (!keys_header)
371 return -ENOMEM;
372
373 keys_header->total_keys = key_count;
374
375 i = 0;
376 list_for_each_entry(item, &config_keys_subsys.su_group.cg_children,
377 ci_entry) {
378 if (item->ci_type != &config_key_type)
379 continue;
380
381 key = to_config_key(item);
382
383 if (!key->description) {
384 pr_warn("No key description for key %s\n", item->ci_name);
385 return -EINVAL;
386 }
387
388 strscpy(keys_header->keys[i].key_desc, key->description,
389 KEY_DESC_MAX_LEN);
390 r = read_key_from_user_keying(&keys_header->keys[i]);
391 if (r != 0) {
392 kexec_dprintk("Failed to read key %s\n",
393 keys_header->keys[i].key_desc);
394 return r;
395 }
396 i++;
397 kexec_dprintk("Found key: %s\n", item->ci_name);
398 }
399
400 return 0;
401}
402
403int crash_load_dm_crypt_keys(struct kimage *image)
404{
405 struct kexec_buf kbuf = {
406 .image = image,
407 .buf_min = 0,
408 .buf_max = ULONG_MAX,
409 .top_down = false,
410 .random = true,
411 };
412 int r;
413
414
415 if (key_count <= 0) {
416 kexec_dprintk("No dm-crypt keys\n");
417 return -ENOENT;
418 }
419
420 if (!is_dm_key_reused) {
421 image->dm_crypt_keys_addr = 0;
422 r = build_keys_header();
423 if (r)
424 return r;
425 }
426
427 kbuf.buffer = keys_header;
428 kbuf.bufsz = get_keys_header_size(key_count);
429
430 kbuf.memsz = kbuf.bufsz;
431 kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
432 kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
433 r = kexec_add_buffer(&kbuf);
434 if (r) {
435 kvfree((void *)kbuf.buffer);
436 return r;
437 }
438 image->dm_crypt_keys_addr = kbuf.mem;
439 image->dm_crypt_keys_sz = kbuf.bufsz;
440 kexec_dprintk(
441 "Loaded dm crypt keys to kexec_buffer bufsz=0x%lx memsz=0x%lx\n",
442 kbuf.bufsz, kbuf.memsz);
443
444 return r;
445}
446
447static int __init configfs_dmcrypt_keys_init(void)
448{
449 int ret;
450
451 if (is_kdump_kernel()) {
452 config_keys_subsys.su_group.cg_item.ci_type =
453 &kdump_config_keys_type;
454 }
455
456 config_group_init(&config_keys_subsys.su_group);
457 mutex_init(&config_keys_subsys.su_mutex);
458 ret = configfs_register_subsystem(&config_keys_subsys);
459 if (ret) {
460 pr_err("Error %d while registering subsystem %s\n", ret,
461 config_keys_subsys.su_group.cg_item.ci_namebuf);
462 goto out_unregister;
463 }
464
465 return 0;
466
467out_unregister:
468 configfs_unregister_subsystem(&config_keys_subsys);
469
470 return ret;
471}
472
473module_init(configfs_dmcrypt_keys_init);