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