Linux Audio

Check our new training course

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