• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2016 IBM Corporation
4  *
5  * Authors:
6  * Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
7  */
8 
9 #include <linux/slab.h>
10 #include <linux/kexec.h>
11 #include <linux/of.h>
12 #include <linux/memblock.h>
13 #include <linux/libfdt.h>
14 
get_addr_size_cells(int * addr_cells,int * size_cells)15 static int get_addr_size_cells(int *addr_cells, int *size_cells)
16 {
17 	struct device_node *root;
18 
19 	root = of_find_node_by_path("/");
20 	if (!root)
21 		return -EINVAL;
22 
23 	*addr_cells = of_n_addr_cells(root);
24 	*size_cells = of_n_size_cells(root);
25 
26 	of_node_put(root);
27 
28 	return 0;
29 }
30 
do_get_kexec_buffer(const void * prop,int len,unsigned long * addr,size_t * size)31 static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
32 			       size_t *size)
33 {
34 	int ret, addr_cells, size_cells;
35 
36 	ret = get_addr_size_cells(&addr_cells, &size_cells);
37 	if (ret)
38 		return ret;
39 
40 	if (len < 4 * (addr_cells + size_cells))
41 		return -ENOENT;
42 
43 	*addr = of_read_number(prop, addr_cells);
44 	*size = of_read_number(prop + 4 * addr_cells, size_cells);
45 
46 	return 0;
47 }
48 
49 /**
50  * ima_get_kexec_buffer - get IMA buffer from the previous kernel
51  * @addr:	On successful return, set to point to the buffer contents.
52  * @size:	On successful return, set to the buffer size.
53  *
54  * Return: 0 on success, negative errno on error.
55  */
ima_get_kexec_buffer(void ** addr,size_t * size)56 int ima_get_kexec_buffer(void **addr, size_t *size)
57 {
58 	int ret, len;
59 	unsigned long tmp_addr;
60 	size_t tmp_size;
61 	const void *prop;
62 
63 	prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
64 	if (!prop)
65 		return -ENOENT;
66 
67 	ret = do_get_kexec_buffer(prop, len, &tmp_addr, &tmp_size);
68 	if (ret)
69 		return ret;
70 
71 	*addr = __va(tmp_addr);
72 	*size = tmp_size;
73 
74 	return 0;
75 }
76 
77 /**
78  * ima_free_kexec_buffer - free memory used by the IMA buffer
79  */
ima_free_kexec_buffer(void)80 int ima_free_kexec_buffer(void)
81 {
82 	int ret;
83 	unsigned long addr;
84 	size_t size;
85 	struct property *prop;
86 
87 	prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
88 	if (!prop)
89 		return -ENOENT;
90 
91 	ret = do_get_kexec_buffer(prop->value, prop->length, &addr, &size);
92 	if (ret)
93 		return ret;
94 
95 	ret = of_remove_property(of_chosen, prop);
96 	if (ret)
97 		return ret;
98 
99 	return memblock_free(addr, size);
100 
101 }
102 
103 /**
104  * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
105  *
106  * The IMA measurement buffer is of no use to a subsequent kernel, so we always
107  * remove it from the device tree.
108  */
remove_ima_buffer(void * fdt,int chosen_node)109 void remove_ima_buffer(void *fdt, int chosen_node)
110 {
111 	int ret, len;
112 	unsigned long addr;
113 	size_t size;
114 	const void *prop;
115 
116 	prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
117 	if (!prop)
118 		return;
119 
120 	ret = do_get_kexec_buffer(prop, len, &addr, &size);
121 	fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
122 	if (ret)
123 		return;
124 
125 	ret = delete_fdt_mem_rsv(fdt, addr, size);
126 	if (!ret)
127 		pr_debug("Removed old IMA buffer reservation.\n");
128 }
129 
130 #ifdef CONFIG_IMA_KEXEC
131 /**
132  * arch_ima_add_kexec_buffer - do arch-specific steps to add the IMA buffer
133  *
134  * Architectures should use this function to pass on the IMA buffer
135  * information to the next kernel.
136  *
137  * Return: 0 on success, negative errno on error.
138  */
arch_ima_add_kexec_buffer(struct kimage * image,unsigned long load_addr,size_t size)139 int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
140 			      size_t size)
141 {
142 	image->arch.ima_buffer_addr = load_addr;
143 	image->arch.ima_buffer_size = size;
144 
145 	return 0;
146 }
147 
write_number(void * p,u64 value,int cells)148 static int write_number(void *p, u64 value, int cells)
149 {
150 	if (cells == 1) {
151 		u32 tmp;
152 
153 		if (value > U32_MAX)
154 			return -EINVAL;
155 
156 		tmp = cpu_to_be32(value);
157 		memcpy(p, &tmp, sizeof(tmp));
158 	} else if (cells == 2) {
159 		u64 tmp;
160 
161 		tmp = cpu_to_be64(value);
162 		memcpy(p, &tmp, sizeof(tmp));
163 	} else
164 		return -EINVAL;
165 
166 	return 0;
167 }
168 
169 /**
170  * setup_ima_buffer - add IMA buffer information to the fdt
171  * @image:		kexec image being loaded.
172  * @fdt:		Flattened device tree for the next kernel.
173  * @chosen_node:	Offset to the chosen node.
174  *
175  * Return: 0 on success, or negative errno on error.
176  */
setup_ima_buffer(const struct kimage * image,void * fdt,int chosen_node)177 int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node)
178 {
179 	int ret, addr_cells, size_cells, entry_size;
180 	u8 value[16];
181 
182 	remove_ima_buffer(fdt, chosen_node);
183 	if (!image->arch.ima_buffer_size)
184 		return 0;
185 
186 	ret = get_addr_size_cells(&addr_cells, &size_cells);
187 	if (ret)
188 		return ret;
189 
190 	entry_size = 4 * (addr_cells + size_cells);
191 
192 	if (entry_size > sizeof(value))
193 		return -EINVAL;
194 
195 	ret = write_number(value, image->arch.ima_buffer_addr, addr_cells);
196 	if (ret)
197 		return ret;
198 
199 	ret = write_number(value + 4 * addr_cells, image->arch.ima_buffer_size,
200 			   size_cells);
201 	if (ret)
202 		return ret;
203 
204 	ret = fdt_setprop(fdt, chosen_node, "linux,ima-kexec-buffer", value,
205 			  entry_size);
206 	if (ret < 0)
207 		return -EINVAL;
208 
209 	ret = fdt_add_mem_rsv(fdt, image->arch.ima_buffer_addr,
210 			      image->arch.ima_buffer_size);
211 	if (ret)
212 		return -EINVAL;
213 
214 	pr_debug("IMA buffer at 0x%llx, size = 0x%zx\n",
215 		 image->arch.ima_buffer_addr, image->arch.ima_buffer_size);
216 
217 	return 0;
218 }
219 #endif /* CONFIG_IMA_KEXEC */
220