Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/lib/codetag.c
26131 views
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, bool lock)
39
{
40
if (lock)
41
down_read(&cttype->mod_lock);
42
else
43
up_read(&cttype->mod_lock);
44
}
45
46
bool codetag_trylock_module_list(struct codetag_type *cttype)
47
{
48
return down_read_trylock(&cttype->mod_lock) != 0;
49
}
50
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
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
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
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
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
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
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
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
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
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 */
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
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
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
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
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
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 *
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
407