xref: /linux/kernel/crash_dump_dm_crypt.c (revision 7d4e49a77d9930c69751b9192448fda6ff9100f1)
1180cf31aSCoiby Xu // SPDX-License-Identifier: GPL-2.0-only
2479e5854SCoiby Xu #include <linux/key.h>
3479e5854SCoiby Xu #include <linux/keyctl.h>
4180cf31aSCoiby Xu #include <keys/user-type.h>
5180cf31aSCoiby Xu #include <linux/crash_dump.h>
6*62f17d9dSCoiby Xu #include <linux/cc_platform.h>
7180cf31aSCoiby Xu #include <linux/configfs.h>
8180cf31aSCoiby Xu #include <linux/module.h>
9180cf31aSCoiby Xu 
10180cf31aSCoiby Xu #define KEY_NUM_MAX 128	/* maximum dm crypt keys */
11479e5854SCoiby Xu #define KEY_SIZE_MAX 256	/* maximum dm crypt key size */
12180cf31aSCoiby Xu #define KEY_DESC_MAX_LEN 128	/* maximum dm crypt key description size */
13180cf31aSCoiby Xu 
14180cf31aSCoiby Xu static unsigned int key_count;
15180cf31aSCoiby Xu 
16479e5854SCoiby Xu struct dm_crypt_key {
17479e5854SCoiby Xu 	unsigned int key_size;
18479e5854SCoiby Xu 	char key_desc[KEY_DESC_MAX_LEN];
19479e5854SCoiby Xu 	u8 data[KEY_SIZE_MAX];
20479e5854SCoiby Xu };
21479e5854SCoiby Xu 
22479e5854SCoiby Xu static struct keys_header {
23479e5854SCoiby Xu 	unsigned int total_keys;
24479e5854SCoiby Xu 	struct dm_crypt_key keys[] __counted_by(total_keys);
25479e5854SCoiby Xu } *keys_header;
26479e5854SCoiby Xu 
get_keys_header_size(size_t total_keys)27479e5854SCoiby Xu static size_t get_keys_header_size(size_t total_keys)
28479e5854SCoiby Xu {
29479e5854SCoiby Xu 	return struct_size(keys_header, keys, total_keys);
30479e5854SCoiby Xu }
31479e5854SCoiby Xu 
32*62f17d9dSCoiby Xu unsigned long long dm_crypt_keys_addr;
33*62f17d9dSCoiby Xu EXPORT_SYMBOL_GPL(dm_crypt_keys_addr);
34*62f17d9dSCoiby Xu 
setup_dmcryptkeys(char * arg)35*62f17d9dSCoiby Xu static int __init setup_dmcryptkeys(char *arg)
36*62f17d9dSCoiby Xu {
37*62f17d9dSCoiby Xu 	char *end;
38*62f17d9dSCoiby Xu 
39*62f17d9dSCoiby Xu 	if (!arg)
40*62f17d9dSCoiby Xu 		return -EINVAL;
41*62f17d9dSCoiby Xu 	dm_crypt_keys_addr = memparse(arg, &end);
42*62f17d9dSCoiby Xu 	if (end > arg)
43*62f17d9dSCoiby Xu 		return 0;
44*62f17d9dSCoiby Xu 
45*62f17d9dSCoiby Xu 	dm_crypt_keys_addr = 0;
46*62f17d9dSCoiby Xu 	return -EINVAL;
47*62f17d9dSCoiby Xu }
48*62f17d9dSCoiby Xu 
49*62f17d9dSCoiby Xu early_param("dmcryptkeys", setup_dmcryptkeys);
50*62f17d9dSCoiby Xu 
51*62f17d9dSCoiby Xu /*
52*62f17d9dSCoiby Xu  * Architectures may override this function to read dm crypt keys
53*62f17d9dSCoiby Xu  */
dm_crypt_keys_read(char * buf,size_t count,u64 * ppos)54*62f17d9dSCoiby Xu ssize_t __weak dm_crypt_keys_read(char *buf, size_t count, u64 *ppos)
55*62f17d9dSCoiby Xu {
56*62f17d9dSCoiby Xu 	struct kvec kvec = { .iov_base = buf, .iov_len = count };
57*62f17d9dSCoiby Xu 	struct iov_iter iter;
58*62f17d9dSCoiby Xu 
59*62f17d9dSCoiby Xu 	iov_iter_kvec(&iter, READ, &kvec, 1, count);
60*62f17d9dSCoiby Xu 	return read_from_oldmem(&iter, count, ppos, cc_platform_has(CC_ATTR_MEM_ENCRYPT));
61*62f17d9dSCoiby Xu }
62*62f17d9dSCoiby Xu 
add_key_to_keyring(struct dm_crypt_key * dm_key,key_ref_t keyring_ref)63*62f17d9dSCoiby Xu static int add_key_to_keyring(struct dm_crypt_key *dm_key,
64*62f17d9dSCoiby Xu 			      key_ref_t keyring_ref)
65*62f17d9dSCoiby Xu {
66*62f17d9dSCoiby Xu 	key_ref_t key_ref;
67*62f17d9dSCoiby Xu 	int r;
68*62f17d9dSCoiby Xu 
69*62f17d9dSCoiby Xu 	/* create or update the requested key and add it to the target keyring */
70*62f17d9dSCoiby Xu 	key_ref = key_create_or_update(keyring_ref, "user", dm_key->key_desc,
71*62f17d9dSCoiby Xu 				       dm_key->data, dm_key->key_size,
72*62f17d9dSCoiby Xu 				       KEY_USR_ALL, KEY_ALLOC_IN_QUOTA);
73*62f17d9dSCoiby Xu 
74*62f17d9dSCoiby Xu 	if (!IS_ERR(key_ref)) {
75*62f17d9dSCoiby Xu 		r = key_ref_to_ptr(key_ref)->serial;
76*62f17d9dSCoiby Xu 		key_ref_put(key_ref);
77*62f17d9dSCoiby Xu 		kexec_dprintk("Success adding key %s", dm_key->key_desc);
78*62f17d9dSCoiby Xu 	} else {
79*62f17d9dSCoiby Xu 		r = PTR_ERR(key_ref);
80*62f17d9dSCoiby Xu 		kexec_dprintk("Error when adding key");
81*62f17d9dSCoiby Xu 	}
82*62f17d9dSCoiby Xu 
83*62f17d9dSCoiby Xu 	key_ref_put(keyring_ref);
84*62f17d9dSCoiby Xu 	return r;
85*62f17d9dSCoiby Xu }
86*62f17d9dSCoiby Xu 
get_keys_from_kdump_reserved_memory(void)879ebfa8dcSCoiby Xu static void get_keys_from_kdump_reserved_memory(void)
889ebfa8dcSCoiby Xu {
899ebfa8dcSCoiby Xu 	struct keys_header *keys_header_loaded;
909ebfa8dcSCoiby Xu 
919ebfa8dcSCoiby Xu 	arch_kexec_unprotect_crashkres();
929ebfa8dcSCoiby Xu 
939ebfa8dcSCoiby Xu 	keys_header_loaded = kmap_local_page(pfn_to_page(
949ebfa8dcSCoiby Xu 		kexec_crash_image->dm_crypt_keys_addr >> PAGE_SHIFT));
959ebfa8dcSCoiby Xu 
969ebfa8dcSCoiby Xu 	memcpy(keys_header, keys_header_loaded, get_keys_header_size(key_count));
979ebfa8dcSCoiby Xu 	kunmap_local(keys_header_loaded);
989ebfa8dcSCoiby Xu 	arch_kexec_protect_crashkres();
999ebfa8dcSCoiby Xu }
1009ebfa8dcSCoiby Xu 
restore_dm_crypt_keys_to_thread_keyring(void)101*62f17d9dSCoiby Xu static int restore_dm_crypt_keys_to_thread_keyring(void)
102*62f17d9dSCoiby Xu {
103*62f17d9dSCoiby Xu 	struct dm_crypt_key *key;
104*62f17d9dSCoiby Xu 	size_t keys_header_size;
105*62f17d9dSCoiby Xu 	key_ref_t keyring_ref;
106*62f17d9dSCoiby Xu 	u64 addr;
107*62f17d9dSCoiby Xu 
108*62f17d9dSCoiby Xu 	/* find the target keyring (which must be writable) */
109*62f17d9dSCoiby Xu 	keyring_ref =
110*62f17d9dSCoiby Xu 		lookup_user_key(KEY_SPEC_USER_KEYRING, 0x01, KEY_NEED_WRITE);
111*62f17d9dSCoiby Xu 	if (IS_ERR(keyring_ref)) {
112*62f17d9dSCoiby Xu 		kexec_dprintk("Failed to get the user keyring\n");
113*62f17d9dSCoiby Xu 		return PTR_ERR(keyring_ref);
114*62f17d9dSCoiby Xu 	}
115*62f17d9dSCoiby Xu 
116*62f17d9dSCoiby Xu 	addr = dm_crypt_keys_addr;
117*62f17d9dSCoiby Xu 	dm_crypt_keys_read((char *)&key_count, sizeof(key_count), &addr);
118*62f17d9dSCoiby Xu 	if (key_count < 0 || key_count > KEY_NUM_MAX) {
119*62f17d9dSCoiby Xu 		kexec_dprintk("Failed to read the number of dm-crypt keys\n");
120*62f17d9dSCoiby Xu 		return -1;
121*62f17d9dSCoiby Xu 	}
122*62f17d9dSCoiby Xu 
123*62f17d9dSCoiby Xu 	kexec_dprintk("There are %u keys\n", key_count);
124*62f17d9dSCoiby Xu 	addr = dm_crypt_keys_addr;
125*62f17d9dSCoiby Xu 
126*62f17d9dSCoiby Xu 	keys_header_size = get_keys_header_size(key_count);
127*62f17d9dSCoiby Xu 	keys_header = kzalloc(keys_header_size, GFP_KERNEL);
128*62f17d9dSCoiby Xu 	if (!keys_header)
129*62f17d9dSCoiby Xu 		return -ENOMEM;
130*62f17d9dSCoiby Xu 
131*62f17d9dSCoiby Xu 	dm_crypt_keys_read((char *)keys_header, keys_header_size, &addr);
132*62f17d9dSCoiby Xu 
133*62f17d9dSCoiby Xu 	for (int i = 0; i < keys_header->total_keys; i++) {
134*62f17d9dSCoiby Xu 		key = &keys_header->keys[i];
135*62f17d9dSCoiby Xu 		kexec_dprintk("Get key (size=%u)\n", key->key_size);
136*62f17d9dSCoiby Xu 		add_key_to_keyring(key, keyring_ref);
137*62f17d9dSCoiby Xu 	}
138*62f17d9dSCoiby Xu 
139*62f17d9dSCoiby Xu 	return 0;
140*62f17d9dSCoiby Xu }
141*62f17d9dSCoiby Xu 
read_key_from_user_keying(struct dm_crypt_key * dm_key)142479e5854SCoiby Xu static int read_key_from_user_keying(struct dm_crypt_key *dm_key)
143479e5854SCoiby Xu {
144479e5854SCoiby Xu 	const struct user_key_payload *ukp;
145479e5854SCoiby Xu 	struct key *key;
146479e5854SCoiby Xu 
147479e5854SCoiby Xu 	kexec_dprintk("Requesting logon key %s", dm_key->key_desc);
148479e5854SCoiby Xu 	key = request_key(&key_type_logon, dm_key->key_desc, NULL);
149479e5854SCoiby Xu 
150479e5854SCoiby Xu 	if (IS_ERR(key)) {
151479e5854SCoiby Xu 		pr_warn("No such logon key %s\n", dm_key->key_desc);
152479e5854SCoiby Xu 		return PTR_ERR(key);
153479e5854SCoiby Xu 	}
154479e5854SCoiby Xu 
155479e5854SCoiby Xu 	ukp = user_key_payload_locked(key);
156479e5854SCoiby Xu 	if (!ukp)
157479e5854SCoiby Xu 		return -EKEYREVOKED;
158479e5854SCoiby Xu 
159479e5854SCoiby Xu 	if (ukp->datalen > KEY_SIZE_MAX) {
160479e5854SCoiby Xu 		pr_err("Key size %u exceeds maximum (%u)\n", ukp->datalen, KEY_SIZE_MAX);
161479e5854SCoiby Xu 		return -EINVAL;
162479e5854SCoiby Xu 	}
163479e5854SCoiby Xu 
164479e5854SCoiby Xu 	memcpy(dm_key->data, ukp->data, ukp->datalen);
165479e5854SCoiby Xu 	dm_key->key_size = ukp->datalen;
166479e5854SCoiby Xu 	kexec_dprintk("Get dm crypt key (size=%u) %s: %8ph\n", dm_key->key_size,
167479e5854SCoiby Xu 		      dm_key->key_desc, dm_key->data);
168479e5854SCoiby Xu 	return 0;
169479e5854SCoiby Xu }
170479e5854SCoiby Xu 
171180cf31aSCoiby Xu struct config_key {
172180cf31aSCoiby Xu 	struct config_item item;
173180cf31aSCoiby Xu 	const char *description;
174180cf31aSCoiby Xu };
175180cf31aSCoiby Xu 
to_config_key(struct config_item * item)176180cf31aSCoiby Xu static inline struct config_key *to_config_key(struct config_item *item)
177180cf31aSCoiby Xu {
178180cf31aSCoiby Xu 	return container_of(item, struct config_key, item);
179180cf31aSCoiby Xu }
180180cf31aSCoiby Xu 
config_key_description_show(struct config_item * item,char * page)181180cf31aSCoiby Xu static ssize_t config_key_description_show(struct config_item *item, char *page)
182180cf31aSCoiby Xu {
183180cf31aSCoiby Xu 	return sprintf(page, "%s\n", to_config_key(item)->description);
184180cf31aSCoiby Xu }
185180cf31aSCoiby Xu 
config_key_description_store(struct config_item * item,const char * page,size_t count)186180cf31aSCoiby Xu static ssize_t config_key_description_store(struct config_item *item,
187180cf31aSCoiby Xu 					    const char *page, size_t count)
188180cf31aSCoiby Xu {
189180cf31aSCoiby Xu 	struct config_key *config_key = to_config_key(item);
190180cf31aSCoiby Xu 	size_t len;
191180cf31aSCoiby Xu 	int ret;
192180cf31aSCoiby Xu 
193180cf31aSCoiby Xu 	ret = -EINVAL;
194180cf31aSCoiby Xu 	len = strcspn(page, "\n");
195180cf31aSCoiby Xu 
196180cf31aSCoiby Xu 	if (len > KEY_DESC_MAX_LEN) {
197180cf31aSCoiby Xu 		pr_err("The key description shouldn't exceed %u characters", KEY_DESC_MAX_LEN);
198180cf31aSCoiby Xu 		return ret;
199180cf31aSCoiby Xu 	}
200180cf31aSCoiby Xu 
201180cf31aSCoiby Xu 	if (!len)
202180cf31aSCoiby Xu 		return ret;
203180cf31aSCoiby Xu 
204180cf31aSCoiby Xu 	kfree(config_key->description);
205180cf31aSCoiby Xu 	ret = -ENOMEM;
206180cf31aSCoiby Xu 	config_key->description = kmemdup_nul(page, len, GFP_KERNEL);
207180cf31aSCoiby Xu 	if (!config_key->description)
208180cf31aSCoiby Xu 		return ret;
209180cf31aSCoiby Xu 
210180cf31aSCoiby Xu 	return count;
211180cf31aSCoiby Xu }
212180cf31aSCoiby Xu 
213180cf31aSCoiby Xu CONFIGFS_ATTR(config_key_, description);
214180cf31aSCoiby Xu 
215180cf31aSCoiby Xu static struct configfs_attribute *config_key_attrs[] = {
216180cf31aSCoiby Xu 	&config_key_attr_description,
217180cf31aSCoiby Xu 	NULL,
218180cf31aSCoiby Xu };
219180cf31aSCoiby Xu 
config_key_release(struct config_item * item)220180cf31aSCoiby Xu static void config_key_release(struct config_item *item)
221180cf31aSCoiby Xu {
222180cf31aSCoiby Xu 	kfree(to_config_key(item));
223180cf31aSCoiby Xu 	key_count--;
224180cf31aSCoiby Xu }
225180cf31aSCoiby Xu 
226180cf31aSCoiby Xu static struct configfs_item_operations config_key_item_ops = {
227180cf31aSCoiby Xu 	.release = config_key_release,
228180cf31aSCoiby Xu };
229180cf31aSCoiby Xu 
230180cf31aSCoiby Xu static const struct config_item_type config_key_type = {
231180cf31aSCoiby Xu 	.ct_item_ops = &config_key_item_ops,
232180cf31aSCoiby Xu 	.ct_attrs = config_key_attrs,
233180cf31aSCoiby Xu 	.ct_owner = THIS_MODULE,
234180cf31aSCoiby Xu };
235180cf31aSCoiby Xu 
config_keys_make_item(struct config_group * group,const char * name)236180cf31aSCoiby Xu static struct config_item *config_keys_make_item(struct config_group *group,
237180cf31aSCoiby Xu 						 const char *name)
238180cf31aSCoiby Xu {
239180cf31aSCoiby Xu 	struct config_key *config_key;
240180cf31aSCoiby Xu 
241180cf31aSCoiby Xu 	if (key_count > KEY_NUM_MAX) {
242180cf31aSCoiby Xu 		pr_err("Only %u keys at maximum to be created\n", KEY_NUM_MAX);
243180cf31aSCoiby Xu 		return ERR_PTR(-EINVAL);
244180cf31aSCoiby Xu 	}
245180cf31aSCoiby Xu 
246180cf31aSCoiby Xu 	config_key = kzalloc(sizeof(struct config_key), GFP_KERNEL);
247180cf31aSCoiby Xu 	if (!config_key)
248180cf31aSCoiby Xu 		return ERR_PTR(-ENOMEM);
249180cf31aSCoiby Xu 
250180cf31aSCoiby Xu 	config_item_init_type_name(&config_key->item, name, &config_key_type);
251180cf31aSCoiby Xu 
252180cf31aSCoiby Xu 	key_count++;
253180cf31aSCoiby Xu 
254180cf31aSCoiby Xu 	return &config_key->item;
255180cf31aSCoiby Xu }
256180cf31aSCoiby Xu 
config_keys_count_show(struct config_item * item,char * page)257180cf31aSCoiby Xu static ssize_t config_keys_count_show(struct config_item *item, char *page)
258180cf31aSCoiby Xu {
259180cf31aSCoiby Xu 	return sprintf(page, "%d\n", key_count);
260180cf31aSCoiby Xu }
261180cf31aSCoiby Xu 
262180cf31aSCoiby Xu CONFIGFS_ATTR_RO(config_keys_, count);
263180cf31aSCoiby Xu 
2649ebfa8dcSCoiby Xu static bool is_dm_key_reused;
2659ebfa8dcSCoiby Xu 
config_keys_reuse_show(struct config_item * item,char * page)2669ebfa8dcSCoiby Xu static ssize_t config_keys_reuse_show(struct config_item *item, char *page)
2679ebfa8dcSCoiby Xu {
2689ebfa8dcSCoiby Xu 	return sprintf(page, "%d\n", is_dm_key_reused);
2699ebfa8dcSCoiby Xu }
2709ebfa8dcSCoiby Xu 
config_keys_reuse_store(struct config_item * item,const char * page,size_t count)2719ebfa8dcSCoiby Xu static ssize_t config_keys_reuse_store(struct config_item *item,
2729ebfa8dcSCoiby Xu 					   const char *page, size_t count)
2739ebfa8dcSCoiby Xu {
2749ebfa8dcSCoiby Xu 	if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
2759ebfa8dcSCoiby Xu 		kexec_dprintk(
2769ebfa8dcSCoiby Xu 			"dm-crypt keys haven't be saved to crash-reserved memory\n");
2779ebfa8dcSCoiby Xu 		return -EINVAL;
2789ebfa8dcSCoiby Xu 	}
2799ebfa8dcSCoiby Xu 
2809ebfa8dcSCoiby Xu 	if (kstrtobool(page, &is_dm_key_reused))
2819ebfa8dcSCoiby Xu 		return -EINVAL;
2829ebfa8dcSCoiby Xu 
2839ebfa8dcSCoiby Xu 	if (is_dm_key_reused)
2849ebfa8dcSCoiby Xu 		get_keys_from_kdump_reserved_memory();
2859ebfa8dcSCoiby Xu 
2869ebfa8dcSCoiby Xu 	return count;
2879ebfa8dcSCoiby Xu }
2889ebfa8dcSCoiby Xu 
2899ebfa8dcSCoiby Xu CONFIGFS_ATTR(config_keys_, reuse);
2909ebfa8dcSCoiby Xu 
291180cf31aSCoiby Xu static struct configfs_attribute *config_keys_attrs[] = {
292180cf31aSCoiby Xu 	&config_keys_attr_count,
2939ebfa8dcSCoiby Xu 	&config_keys_attr_reuse,
294180cf31aSCoiby Xu 	NULL,
295180cf31aSCoiby Xu };
296180cf31aSCoiby Xu 
297180cf31aSCoiby Xu /*
298180cf31aSCoiby Xu  * Note that, since no extra work is required on ->drop_item(),
299180cf31aSCoiby Xu  * no ->drop_item() is provided.
300180cf31aSCoiby Xu  */
301180cf31aSCoiby Xu static struct configfs_group_operations config_keys_group_ops = {
302180cf31aSCoiby Xu 	.make_item = config_keys_make_item,
303180cf31aSCoiby Xu };
304180cf31aSCoiby Xu 
305180cf31aSCoiby Xu static const struct config_item_type config_keys_type = {
306180cf31aSCoiby Xu 	.ct_group_ops = &config_keys_group_ops,
307180cf31aSCoiby Xu 	.ct_attrs = config_keys_attrs,
308180cf31aSCoiby Xu 	.ct_owner = THIS_MODULE,
309180cf31aSCoiby Xu };
310180cf31aSCoiby Xu 
311*62f17d9dSCoiby Xu static bool restore;
312*62f17d9dSCoiby Xu 
config_keys_restore_show(struct config_item * item,char * page)313*62f17d9dSCoiby Xu static ssize_t config_keys_restore_show(struct config_item *item, char *page)
314*62f17d9dSCoiby Xu {
315*62f17d9dSCoiby Xu 	return sprintf(page, "%d\n", restore);
316*62f17d9dSCoiby Xu }
317*62f17d9dSCoiby Xu 
config_keys_restore_store(struct config_item * item,const char * page,size_t count)318*62f17d9dSCoiby Xu static ssize_t config_keys_restore_store(struct config_item *item,
319*62f17d9dSCoiby Xu 					  const char *page, size_t count)
320*62f17d9dSCoiby Xu {
321*62f17d9dSCoiby Xu 	if (!restore)
322*62f17d9dSCoiby Xu 		restore_dm_crypt_keys_to_thread_keyring();
323*62f17d9dSCoiby Xu 
324*62f17d9dSCoiby Xu 	if (kstrtobool(page, &restore))
325*62f17d9dSCoiby Xu 		return -EINVAL;
326*62f17d9dSCoiby Xu 
327*62f17d9dSCoiby Xu 	return count;
328*62f17d9dSCoiby Xu }
329*62f17d9dSCoiby Xu 
330*62f17d9dSCoiby Xu CONFIGFS_ATTR(config_keys_, restore);
331*62f17d9dSCoiby Xu 
332*62f17d9dSCoiby Xu static struct configfs_attribute *kdump_config_keys_attrs[] = {
333*62f17d9dSCoiby Xu 	&config_keys_attr_restore,
334*62f17d9dSCoiby Xu 	NULL,
335*62f17d9dSCoiby Xu };
336*62f17d9dSCoiby Xu 
337*62f17d9dSCoiby Xu static const struct config_item_type kdump_config_keys_type = {
338*62f17d9dSCoiby Xu 	.ct_attrs = kdump_config_keys_attrs,
339*62f17d9dSCoiby Xu 	.ct_owner = THIS_MODULE,
340*62f17d9dSCoiby Xu };
341*62f17d9dSCoiby Xu 
342180cf31aSCoiby Xu static struct configfs_subsystem config_keys_subsys = {
343180cf31aSCoiby Xu 	.su_group = {
344180cf31aSCoiby Xu 		.cg_item = {
345180cf31aSCoiby Xu 			.ci_namebuf = "crash_dm_crypt_keys",
346180cf31aSCoiby Xu 			.ci_type = &config_keys_type,
347180cf31aSCoiby Xu 		},
348180cf31aSCoiby Xu 	},
349180cf31aSCoiby Xu };
350180cf31aSCoiby Xu 
build_keys_header(void)351479e5854SCoiby Xu static int build_keys_header(void)
352479e5854SCoiby Xu {
353479e5854SCoiby Xu 	struct config_item *item = NULL;
354479e5854SCoiby Xu 	struct config_key *key;
355479e5854SCoiby Xu 	int i, r;
356479e5854SCoiby Xu 
357479e5854SCoiby Xu 	if (keys_header != NULL)
358479e5854SCoiby Xu 		kvfree(keys_header);
359479e5854SCoiby Xu 
360479e5854SCoiby Xu 	keys_header = kzalloc(get_keys_header_size(key_count), GFP_KERNEL);
361479e5854SCoiby Xu 	if (!keys_header)
362479e5854SCoiby Xu 		return -ENOMEM;
363479e5854SCoiby Xu 
364479e5854SCoiby Xu 	keys_header->total_keys = key_count;
365479e5854SCoiby Xu 
366479e5854SCoiby Xu 	i = 0;
367479e5854SCoiby Xu 	list_for_each_entry(item, &config_keys_subsys.su_group.cg_children,
368479e5854SCoiby Xu 			    ci_entry) {
369479e5854SCoiby Xu 		if (item->ci_type != &config_key_type)
370479e5854SCoiby Xu 			continue;
371479e5854SCoiby Xu 
372479e5854SCoiby Xu 		key = to_config_key(item);
373479e5854SCoiby Xu 
374479e5854SCoiby Xu 		if (!key->description) {
375479e5854SCoiby Xu 			pr_warn("No key description for key %s\n", item->ci_name);
376479e5854SCoiby Xu 			return -EINVAL;
377479e5854SCoiby Xu 		}
378479e5854SCoiby Xu 
379479e5854SCoiby Xu 		strscpy(keys_header->keys[i].key_desc, key->description,
380479e5854SCoiby Xu 			KEY_DESC_MAX_LEN);
381479e5854SCoiby Xu 		r = read_key_from_user_keying(&keys_header->keys[i]);
382479e5854SCoiby Xu 		if (r != 0) {
383479e5854SCoiby Xu 			kexec_dprintk("Failed to read key %s\n",
384479e5854SCoiby Xu 				      keys_header->keys[i].key_desc);
385479e5854SCoiby Xu 			return r;
386479e5854SCoiby Xu 		}
387479e5854SCoiby Xu 		i++;
388479e5854SCoiby Xu 		kexec_dprintk("Found key: %s\n", item->ci_name);
389479e5854SCoiby Xu 	}
390479e5854SCoiby Xu 
391479e5854SCoiby Xu 	return 0;
392479e5854SCoiby Xu }
393479e5854SCoiby Xu 
crash_load_dm_crypt_keys(struct kimage * image)394479e5854SCoiby Xu int crash_load_dm_crypt_keys(struct kimage *image)
395479e5854SCoiby Xu {
396479e5854SCoiby Xu 	struct kexec_buf kbuf = {
397479e5854SCoiby Xu 		.image = image,
398479e5854SCoiby Xu 		.buf_min = 0,
399479e5854SCoiby Xu 		.buf_max = ULONG_MAX,
400479e5854SCoiby Xu 		.top_down = false,
401479e5854SCoiby Xu 		.random = true,
402479e5854SCoiby Xu 	};
403479e5854SCoiby Xu 	int r;
404479e5854SCoiby Xu 
405479e5854SCoiby Xu 
406479e5854SCoiby Xu 	if (key_count <= 0) {
407479e5854SCoiby Xu 		kexec_dprintk("No dm-crypt keys\n");
408479e5854SCoiby Xu 		return -ENOENT;
409479e5854SCoiby Xu 	}
410479e5854SCoiby Xu 
4119ebfa8dcSCoiby Xu 	if (!is_dm_key_reused) {
412479e5854SCoiby Xu 		image->dm_crypt_keys_addr = 0;
413479e5854SCoiby Xu 		r = build_keys_header();
414479e5854SCoiby Xu 		if (r)
415479e5854SCoiby Xu 			return r;
4169ebfa8dcSCoiby Xu 	}
417479e5854SCoiby Xu 
418479e5854SCoiby Xu 	kbuf.buffer = keys_header;
419479e5854SCoiby Xu 	kbuf.bufsz = get_keys_header_size(key_count);
420479e5854SCoiby Xu 
421479e5854SCoiby Xu 	kbuf.memsz = kbuf.bufsz;
422479e5854SCoiby Xu 	kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
423479e5854SCoiby Xu 	kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
424479e5854SCoiby Xu 	r = kexec_add_buffer(&kbuf);
425479e5854SCoiby Xu 	if (r) {
426479e5854SCoiby Xu 		kvfree((void *)kbuf.buffer);
427479e5854SCoiby Xu 		return r;
428479e5854SCoiby Xu 	}
429479e5854SCoiby Xu 	image->dm_crypt_keys_addr = kbuf.mem;
430479e5854SCoiby Xu 	image->dm_crypt_keys_sz = kbuf.bufsz;
431479e5854SCoiby Xu 	kexec_dprintk(
432479e5854SCoiby Xu 		"Loaded dm crypt keys to kexec_buffer bufsz=0x%lx memsz=0x%lx\n",
433479e5854SCoiby Xu 		kbuf.bufsz, kbuf.memsz);
434479e5854SCoiby Xu 
435479e5854SCoiby Xu 	return r;
436479e5854SCoiby Xu }
437479e5854SCoiby Xu 
configfs_dmcrypt_keys_init(void)438180cf31aSCoiby Xu static int __init configfs_dmcrypt_keys_init(void)
439180cf31aSCoiby Xu {
440180cf31aSCoiby Xu 	int ret;
441180cf31aSCoiby Xu 
442*62f17d9dSCoiby Xu 	if (is_kdump_kernel()) {
443*62f17d9dSCoiby Xu 		config_keys_subsys.su_group.cg_item.ci_type =
444*62f17d9dSCoiby Xu 			&kdump_config_keys_type;
445*62f17d9dSCoiby Xu 	}
446*62f17d9dSCoiby Xu 
447180cf31aSCoiby Xu 	config_group_init(&config_keys_subsys.su_group);
448180cf31aSCoiby Xu 	mutex_init(&config_keys_subsys.su_mutex);
449180cf31aSCoiby Xu 	ret = configfs_register_subsystem(&config_keys_subsys);
450180cf31aSCoiby Xu 	if (ret) {
451180cf31aSCoiby Xu 		pr_err("Error %d while registering subsystem %s\n", ret,
452180cf31aSCoiby Xu 		       config_keys_subsys.su_group.cg_item.ci_namebuf);
453180cf31aSCoiby Xu 		goto out_unregister;
454180cf31aSCoiby Xu 	}
455180cf31aSCoiby Xu 
456180cf31aSCoiby Xu 	return 0;
457180cf31aSCoiby Xu 
458180cf31aSCoiby Xu out_unregister:
459180cf31aSCoiby Xu 	configfs_unregister_subsystem(&config_keys_subsys);
460180cf31aSCoiby Xu 
461180cf31aSCoiby Xu 	return ret;
462180cf31aSCoiby Xu }
463180cf31aSCoiby Xu 
464180cf31aSCoiby Xu module_init(configfs_dmcrypt_keys_init);
465