projects/linux·blob v7.2-rc5 · refs

407 lines · 8.9 KiB

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
10struct 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
24struct codetag_range {
25 struct codetag *start;
26 struct codetag *stop;
27};
28
29struct codetag_module {
30 struct module *mod;
31 struct codetag_range range;
32 unsigned long mod_seq;
33};
34
35static DEFINE_MUTEX(codetag_lock);
36static LIST_HEAD(codetag_types);
37
38void codetag_lock_module_list(struct codetag_type *cttype)
39{
40 down_read(&cttype->mod_lock);
41}
42
43bool codetag_trylock_module_list(struct codetag_type *cttype)
44{
45 return down_read_trylock(&cttype->mod_lock) != 0;
46}
47
48void codetag_unlock_module_list(struct codetag_type *cttype)
49{
50 up_read(&cttype->mod_lock);
51}
52
53struct 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
66static 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
71static inline
72struct 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
80struct 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
122void 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
133static 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
140static 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
160static 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
169static 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
178static 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 */
236bool 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
264void *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
289void 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
305void 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
321int 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
340void 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
380struct codetag_type *
381codetag_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}