xref: /linux/lib/codetag.c (revision 67c2696cf76aa276376fdd845c7d1b3e16b97af2)
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/codetag.h>
3 #include <linux/idr.h>
4 #include <linux/kallsyms.h>
5 #include <linux/module.h>
6 #include <linux/seq_buf.h>
7 #include <linux/slab.h>
8 #include <linux/vmalloc.h>
9 
10 struct codetag_type {
11 	struct list_head link;
12 	unsigned int count;
13 	struct idr mod_idr;
14 	/*
15 	 * protects mod_idr, next_mod_seq,
16 	 * iter->mod_seq and cmod->mod_seq
17 	 */
18 	struct rw_semaphore mod_lock;
19 	struct codetag_type_desc desc;
20 	/* generates unique sequence number for module load */
21 	unsigned long next_mod_seq;
22 };
23 
24 struct codetag_range {
25 	struct codetag *start;
26 	struct codetag *stop;
27 };
28 
29 struct codetag_module {
30 	struct module *mod;
31 	struct codetag_range range;
32 	unsigned long mod_seq;
33 };
34 
35 static DEFINE_MUTEX(codetag_lock);
36 static LIST_HEAD(codetag_types);
37 
38 void codetag_lock_module_list(struct codetag_type *cttype)
39 {
40 	down_read(&cttype->mod_lock);
41 }
42 
43 bool codetag_trylock_module_list(struct codetag_type *cttype)
44 {
45 	return down_read_trylock(&cttype->mod_lock) != 0;
46 }
47 
48 void codetag_unlock_module_list(struct codetag_type *cttype)
49 {
50 	up_read(&cttype->mod_lock);
51 }
52 
53 struct codetag_iterator codetag_get_ct_iter(struct codetag_type *cttype)
54 {
55 	struct codetag_iterator iter = {
56 		.cttype = cttype,
57 		.cmod = NULL,
58 		.mod_id = 0,
59 		.ct = NULL,
60 		.mod_seq = 0,
61 	};
62 
63 	return iter;
64 }
65 
66 static inline struct codetag *get_first_module_ct(struct codetag_module *cmod)
67 {
68 	return cmod->range.start < cmod->range.stop ? cmod->range.start : NULL;
69 }
70 
71 static inline
72 struct codetag *get_next_module_ct(struct codetag_iterator *iter)
73 {
74 	struct codetag *res = (struct codetag *)
75 			((char *)iter->ct + iter->cttype->desc.tag_size);
76 
77 	return res < iter->cmod->range.stop ? res : NULL;
78 }
79 
80 struct codetag *codetag_next_ct(struct codetag_iterator *iter)
81 {
82 	struct codetag_type *cttype = iter->cttype;
83 	struct codetag_module *cmod;
84 	struct codetag *ct;
85 
86 	lockdep_assert_held(&cttype->mod_lock);
87 
88 	if (unlikely(idr_is_empty(&cttype->mod_idr)))
89 		return NULL;
90 
91 	ct = NULL;
92 	while (true) {
93 		cmod = idr_find(&cttype->mod_idr, iter->mod_id);
94 
95 		/* If module was removed move to the next one */
96 		if (!cmod)
97 			cmod = idr_get_next_ul(&cttype->mod_idr,
98 					       &iter->mod_id);
99 
100 		/* Exit if no more modules */
101 		if (!cmod)
102 			break;
103 
104 		if (!iter->cmod || iter->mod_seq != cmod->mod_seq) {
105 			iter->cmod = cmod;
106 			iter->mod_seq = cmod->mod_seq;
107 			ct = get_first_module_ct(cmod);
108 		} else {
109 			ct = get_next_module_ct(iter);
110 		}
111 
112 		if (ct)
113 			break;
114 
115 		iter->mod_id++;
116 	}
117 
118 	iter->ct = ct;
119 	return ct;
120 }
121 
122 void codetag_to_text(struct seq_buf *out, struct codetag *ct)
123 {
124 	if (ct->modname)
125 		seq_buf_printf(out, "%s:%u [%s] func:%s",
126 			       ct->filename, ct->lineno,
127 			       ct->modname, ct->function);
128 	else
129 		seq_buf_printf(out, "%s:%u func:%s",
130 			       ct->filename, ct->lineno, ct->function);
131 }
132 
133 static inline size_t range_size(const struct codetag_type *cttype,
134 				const struct codetag_range *range)
135 {
136 	return ((char *)range->stop - (char *)range->start) /
137 			cttype->desc.tag_size;
138 }
139 
140 static void *get_symbol(struct module *mod, const char *prefix, const char *name)
141 {
142 	DECLARE_SEQ_BUF(sb, KSYM_NAME_LEN);
143 	const char *buf;
144 	void *ret;
145 
146 	seq_buf_printf(&sb, "%s%s", prefix, name);
147 	if (seq_buf_has_overflowed(&sb))
148 		return NULL;
149 
150 	buf = seq_buf_str(&sb);
151 	preempt_disable();
152 	ret = mod ?
153 		(void *)find_kallsyms_symbol_value(mod, buf) :
154 		(void *)kallsyms_lookup_name(buf);
155 	preempt_enable();
156 
157 	return ret;
158 }
159 
160 static struct codetag_range get_section_range(struct module *mod,
161 					      const char *section)
162 {
163 	return (struct codetag_range) {
164 		get_symbol(mod, CODETAG_SECTION_START_PREFIX, section),
165 		get_symbol(mod, CODETAG_SECTION_STOP_PREFIX, section),
166 	};
167 }
168 
169 static const char *get_mod_name(__maybe_unused struct module *mod)
170 {
171 #ifdef CONFIG_MODULES
172 	if (mod)
173 		return mod->name;
174 #endif
175 	return "(built-in)";
176 }
177 
178 static int codetag_module_init(struct codetag_type *cttype, struct module *mod)
179 {
180 	struct codetag_range range;
181 	struct codetag_module *cmod;
182 	int mod_id;
183 	int err;
184 
185 	range = get_section_range(mod, cttype->desc.section);
186 	if (!range.start || !range.stop) {
187 		pr_warn("Failed to load code tags of type %s from the module %s\n",
188 			cttype->desc.section, get_mod_name(mod));
189 		return -EINVAL;
190 	}
191 
192 	/* Ignore empty ranges */
193 	if (range.start == range.stop)
194 		return 0;
195 
196 	BUG_ON(range.start > range.stop);
197 
198 	cmod = kmalloc_obj(*cmod);
199 	if (unlikely(!cmod))
200 		return -ENOMEM;
201 
202 	cmod->mod = mod;
203 	cmod->range = range;
204 
205 	down_write(&cttype->mod_lock);
206 	cmod->mod_seq = ++cttype->next_mod_seq;
207 	mod_id = idr_alloc(&cttype->mod_idr, cmod, 0, 0, GFP_KERNEL);
208 	if (mod_id >= 0) {
209 		if (cttype->desc.module_load) {
210 			err = cttype->desc.module_load(mod, range.start, range.stop);
211 			if (!err)
212 				cttype->count += range_size(cttype, &range);
213 			else
214 				idr_remove(&cttype->mod_idr, mod_id);
215 		} else {
216 			cttype->count += range_size(cttype, &range);
217 			err = 0;
218 		}
219 	} else {
220 		err = mod_id;
221 	}
222 	up_write(&cttype->mod_lock);
223 
224 	if (err < 0) {
225 		kfree(cmod);
226 		return err;
227 	}
228 
229 	return 0;
230 }
231 
232 #ifdef CONFIG_MODULES
233 #define CODETAG_SECTION_PREFIX	".codetag."
234 
235 /* Some codetag types need a separate module section */
236 bool codetag_needs_module_section(struct module *mod, const char *name,
237 				  unsigned long size)
238 {
239 	const char *type_name;
240 	struct codetag_type *cttype;
241 	bool ret = false;
242 
243 	if (strncmp(name, CODETAG_SECTION_PREFIX, strlen(CODETAG_SECTION_PREFIX)))
244 		return false;
245 
246 	type_name = name + strlen(CODETAG_SECTION_PREFIX);
247 	mutex_lock(&codetag_lock);
248 	list_for_each_entry(cttype, &codetag_types, link) {
249 		if (strcmp(type_name, cttype->desc.section) == 0) {
250 			if (!cttype->desc.needs_section_mem)
251 				break;
252 
253 			down_write(&cttype->mod_lock);
254 			ret = cttype->desc.needs_section_mem(mod, size);
255 			up_write(&cttype->mod_lock);
256 			break;
257 		}
258 	}
259 	mutex_unlock(&codetag_lock);
260 
261 	return ret;
262 }
263 
264 void *codetag_alloc_module_section(struct module *mod, const char *name,
265 				   unsigned long size, unsigned int prepend,
266 				   unsigned long align)
267 {
268 	const char *type_name = name + strlen(CODETAG_SECTION_PREFIX);
269 	struct codetag_type *cttype;
270 	void *ret = ERR_PTR(-EINVAL);
271 
272 	mutex_lock(&codetag_lock);
273 	list_for_each_entry(cttype, &codetag_types, link) {
274 		if (strcmp(type_name, cttype->desc.section) == 0) {
275 			if (WARN_ON(!cttype->desc.alloc_section_mem))
276 				break;
277 
278 			down_write(&cttype->mod_lock);
279 			ret = cttype->desc.alloc_section_mem(mod, size, prepend, align);
280 			up_write(&cttype->mod_lock);
281 			break;
282 		}
283 	}
284 	mutex_unlock(&codetag_lock);
285 
286 	return ret;
287 }
288 
289 void codetag_free_module_sections(struct module *mod)
290 {
291 	struct codetag_type *cttype;
292 
293 	mutex_lock(&codetag_lock);
294 	list_for_each_entry(cttype, &codetag_types, link) {
295 		if (!cttype->desc.free_section_mem)
296 			continue;
297 
298 		down_write(&cttype->mod_lock);
299 		cttype->desc.free_section_mem(mod, false);
300 		up_write(&cttype->mod_lock);
301 	}
302 	mutex_unlock(&codetag_lock);
303 }
304 
305 void codetag_module_replaced(struct module *mod, struct module *new_mod)
306 {
307 	struct codetag_type *cttype;
308 
309 	mutex_lock(&codetag_lock);
310 	list_for_each_entry(cttype, &codetag_types, link) {
311 		if (!cttype->desc.module_replaced)
312 			continue;
313 
314 		down_write(&cttype->mod_lock);
315 		cttype->desc.module_replaced(mod, new_mod);
316 		up_write(&cttype->mod_lock);
317 	}
318 	mutex_unlock(&codetag_lock);
319 }
320 
321 int codetag_load_module(struct module *mod)
322 {
323 	struct codetag_type *cttype;
324 	int ret = 0;
325 
326 	if (!mod)
327 		return 0;
328 
329 	mutex_lock(&codetag_lock);
330 	list_for_each_entry(cttype, &codetag_types, link) {
331 		ret = codetag_module_init(cttype, mod);
332 		if (ret)
333 			break;
334 	}
335 	mutex_unlock(&codetag_lock);
336 
337 	return ret;
338 }
339 
340 void codetag_unload_module(struct module *mod)
341 {
342 	struct codetag_type *cttype;
343 
344 	if (!mod)
345 		return;
346 
347 	/* await any module's kfree_rcu() operations to complete */
348 	kvfree_rcu_barrier();
349 
350 	mutex_lock(&codetag_lock);
351 	list_for_each_entry(cttype, &codetag_types, link) {
352 		struct codetag_module *found = NULL;
353 		struct codetag_module *cmod;
354 		unsigned long mod_id, tmp;
355 
356 		down_write(&cttype->mod_lock);
357 		idr_for_each_entry_ul(&cttype->mod_idr, cmod, tmp, mod_id) {
358 			if (cmod->mod && cmod->mod == mod) {
359 				found = cmod;
360 				break;
361 			}
362 		}
363 		if (found) {
364 			if (cttype->desc.module_unload)
365 				cttype->desc.module_unload(cmod->mod,
366 					cmod->range.start, cmod->range.stop);
367 
368 			cttype->count -= range_size(cttype, &cmod->range);
369 			idr_remove(&cttype->mod_idr, mod_id);
370 			kfree(cmod);
371 		}
372 		up_write(&cttype->mod_lock);
373 		if (found && cttype->desc.free_section_mem)
374 			cttype->desc.free_section_mem(mod, true);
375 	}
376 	mutex_unlock(&codetag_lock);
377 }
378 #endif /* CONFIG_MODULES */
379 
380 struct codetag_type *
381 codetag_register_type(const struct codetag_type_desc *desc)
382 {
383 	struct codetag_type *cttype;
384 	int err;
385 
386 	BUG_ON(desc->tag_size <= 0);
387 
388 	cttype = kzalloc_obj(*cttype);
389 	if (unlikely(!cttype))
390 		return ERR_PTR(-ENOMEM);
391 
392 	cttype->desc = *desc;
393 	idr_init(&cttype->mod_idr);
394 	init_rwsem(&cttype->mod_lock);
395 
396 	err = codetag_module_init(cttype, NULL);
397 	if (unlikely(err)) {
398 		kfree(cttype);
399 		return ERR_PTR(err);
400 	}
401 
402 	mutex_lock(&codetag_lock);
403 	list_add_tail(&cttype->link, &codetag_types);
404 	mutex_unlock(&codetag_lock);
405 
406 	return cttype;
407 }
408