File Index
Files and directories
Sign in
FILE

kallsyms.c

File preview with syntax highlighting.

linux-6.19.14/kernel/module/kallsyms.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Module kallsyms support
  4 *
  5 * Copyright (C) 2010 Rusty Russell
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/module_symbol.h>
 10#include <linux/kallsyms.h>
 11#include <linux/buildid.h>
 12#include <linux/bsearch.h>
 13#include "internal.h"
 14
 15/* Lookup exported symbol in given range of kernel_symbols */
 16static const struct kernel_symbol *lookup_exported_symbol(const char *name,
 17							  const struct kernel_symbol *start,
 18							  const struct kernel_symbol *stop)
 19{
 20	return bsearch(name, start, stop - start,
 21			sizeof(struct kernel_symbol), cmp_name);
 22}
 23
 24static int is_exported(const char *name, unsigned long value,
 25		       const struct module *mod)
 26{
 27	const struct kernel_symbol *ks;
 28
 29	if (!mod)
 30		ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab);
 31	else
 32		ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms);
 33
 34	return ks && kernel_symbol_value(ks) == value;
 35}
 36
 37/* As per nm */
 38static char elf_type(const Elf_Sym *sym, const struct load_info *info)
 39{
 40	const Elf_Shdr *sechdrs = info->sechdrs;
 41
 42	if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
 43		if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)
 44			return 'v';
 45		else
 46			return 'w';
 47	}
 48	if (sym->st_shndx == SHN_UNDEF)
 49		return 'U';
 50	if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu)
 51		return 'a';
 52	if (sym->st_shndx >= SHN_LORESERVE)
 53		return '?';
 54	if (sechdrs[sym->st_shndx].sh_flags & SHF_EXECINSTR)
 55		return 't';
 56	if (sechdrs[sym->st_shndx].sh_flags & SHF_ALLOC &&
 57	    sechdrs[sym->st_shndx].sh_type != SHT_NOBITS) {
 58		if (!(sechdrs[sym->st_shndx].sh_flags & SHF_WRITE))
 59			return 'r';
 60		else if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)
 61			return 'g';
 62		else
 63			return 'd';
 64	}
 65	if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) {
 66		if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)
 67			return 's';
 68		else
 69			return 'b';
 70	}
 71	if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name,
 72		      ".debug")) {
 73		return 'n';
 74	}
 75	return '?';
 76}
 77
 78static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
 79			   unsigned int shnum, unsigned int pcpundx)
 80{
 81	const Elf_Shdr *sec;
 82	enum mod_mem_type type;
 83
 84	if (src->st_shndx == SHN_UNDEF ||
 85	    src->st_shndx >= shnum ||
 86	    !src->st_name)
 87		return false;
 88
 89#ifdef CONFIG_KALLSYMS_ALL
 90	if (src->st_shndx == pcpundx)
 91		return true;
 92#endif
 93
 94	sec = sechdrs + src->st_shndx;
 95	type = sec->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT;
 96	if (!(sec->sh_flags & SHF_ALLOC)
 97#ifndef CONFIG_KALLSYMS_ALL
 98	    || !(sec->sh_flags & SHF_EXECINSTR)
 99#endif
100	    || mod_mem_type_is_init(type))
101		return false;
102
103	return true;
104}
105
106/*
107 * We only allocate and copy the strings needed by the parts of symtab
108 * we keep.  This is simple, but has the effect of making multiple
109 * copies of duplicates.  We could be more sophisticated, see
110 * linux-kernel thread starting with
111 * <73defb5e4bca04a6431392cc341112b1@localhost>.
112 */
113void layout_symtab(struct module *mod, struct load_info *info)
114{
115	Elf_Shdr *symsect = info->sechdrs + info->index.sym;
116	Elf_Shdr *strsect = info->sechdrs + info->index.str;
117	const Elf_Sym *src;
118	unsigned int i, nsrc, ndst, strtab_size = 0;
119	struct module_memory *mod_mem_data = &mod->mem[MOD_DATA];
120	struct module_memory *mod_mem_init_data = &mod->mem[MOD_INIT_DATA];
121
122	/* Put symbol section at end of init part of module. */
123	symsect->sh_flags |= SHF_ALLOC;
124	symsect->sh_entsize = module_get_offset_and_type(mod, MOD_INIT_DATA,
125							 symsect, info->index.sym);
126	pr_debug("\t%s\n", info->secstrings + symsect->sh_name);
127
128	src = (void *)info->hdr + symsect->sh_offset;
129	nsrc = symsect->sh_size / sizeof(*src);
130
131	/* Compute total space required for the core symbols' strtab. */
132	for (ndst = i = 0; i < nsrc; i++) {
133		if (i == 0 || is_livepatch_module(mod) ||
134		    is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
135				   info->index.pcpu)) {
136			strtab_size += strlen(&info->strtab[src[i].st_name]) + 1;
137			ndst++;
138		}
139	}
140
141	/* Append room for core symbols at end of core part. */
142	info->symoffs = ALIGN(mod_mem_data->size, symsect->sh_addralign ?: 1);
143	info->stroffs = mod_mem_data->size = info->symoffs + ndst * sizeof(Elf_Sym);
144	mod_mem_data->size += strtab_size;
145	/* Note add_kallsyms() computes strtab_size as core_typeoffs - stroffs */
146	info->core_typeoffs = mod_mem_data->size;
147	mod_mem_data->size += ndst * sizeof(char);
148
149	/* Put string table section at end of init part of module. */
150	strsect->sh_flags |= SHF_ALLOC;
151	strsect->sh_entsize = module_get_offset_and_type(mod, MOD_INIT_DATA,
152							 strsect, info->index.str);
153	pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
154
155	/* We'll tack temporary mod_kallsyms on the end. */
156	mod_mem_init_data->size = ALIGN(mod_mem_init_data->size,
157					__alignof__(struct mod_kallsyms));
158	info->mod_kallsyms_init_off = mod_mem_init_data->size;
159
160	mod_mem_init_data->size += sizeof(struct mod_kallsyms);
161	info->init_typeoffs = mod_mem_init_data->size;
162	mod_mem_init_data->size += nsrc * sizeof(char);
163}
164
165/*
166 * We use the full symtab and strtab which layout_symtab arranged to
167 * be appended to the init section.  Later we switch to the cut-down
168 * core-only ones.
169 */
170void add_kallsyms(struct module *mod, const struct load_info *info)
171{
172	unsigned int i, ndst;
173	const Elf_Sym *src;
174	Elf_Sym *dst;
175	char *s;
176	Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
177	unsigned long strtab_size;
178	void *data_base = mod->mem[MOD_DATA].base;
179	void *init_data_base = mod->mem[MOD_INIT_DATA].base;
180	struct mod_kallsyms *kallsyms;
181
182	kallsyms = init_data_base + info->mod_kallsyms_init_off;
183
184	kallsyms->symtab = (void *)symsec->sh_addr;
185	kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
186	/* Make sure we get permanent strtab: don't use info->strtab. */
187	kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
188	kallsyms->typetab = init_data_base + info->init_typeoffs;
189
190	/*
191	 * Now populate the cut down core kallsyms for after init
192	 * and set types up while we still have access to sections.
193	 */
194	mod->core_kallsyms.symtab = dst = data_base + info->symoffs;
195	mod->core_kallsyms.strtab = s = data_base + info->stroffs;
196	mod->core_kallsyms.typetab = data_base + info->core_typeoffs;
197	strtab_size = info->core_typeoffs - info->stroffs;
198	src = kallsyms->symtab;
199	for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
200		kallsyms->typetab[i] = elf_type(src + i, info);
201		if (i == 0 || is_livepatch_module(mod) ||
202		    is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
203				   info->index.pcpu)) {
204			ssize_t ret;
205
206			mod->core_kallsyms.typetab[ndst] =
207				kallsyms->typetab[i];
208			dst[ndst] = src[i];
209			dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
210			ret = strscpy(s, &kallsyms->strtab[src[i].st_name],
211				      strtab_size);
212			if (ret < 0)
213				break;
214			s += ret + 1;
215			strtab_size -= ret + 1;
216		}
217	}
218
219	/* Set up to point into init section. */
220	rcu_assign_pointer(mod->kallsyms, kallsyms);
221	mod->core_kallsyms.num_symtab = ndst;
222}
223
224#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
225void init_build_id(struct module *mod, const struct load_info *info)
226{
227	const Elf_Shdr *sechdr;
228	unsigned int i;
229
230	for (i = 0; i < info->hdr->e_shnum; i++) {
231		sechdr = &info->sechdrs[i];
232		if (!sect_empty(sechdr) && sechdr->sh_type == SHT_NOTE &&
233		    !build_id_parse_buf((void *)sechdr->sh_addr, mod->build_id,
234					sechdr->sh_size))
235			break;
236	}
237}
238#else
239void init_build_id(struct module *mod, const struct load_info *info)
240{
241}
242#endif
243
244static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum)
245{
246	return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
247}
248
249/*
250 * Given a module and address, find the corresponding symbol and return its name
251 * while providing its size and offset if needed.
252 */
253static const char *find_kallsyms_symbol(struct module *mod,
254					unsigned long addr,
255					unsigned long *size,
256					unsigned long *offset)
257{
258	unsigned int i, best = 0;
259	unsigned long nextval, bestval;
260	struct mod_kallsyms *kallsyms = rcu_dereference(mod->kallsyms);
261	struct module_memory *mod_mem;
262
263	/* At worse, next value is at end of module */
264	if (within_module_init(addr, mod))
265		mod_mem = &mod->mem[MOD_INIT_TEXT];
266	else
267		mod_mem = &mod->mem[MOD_TEXT];
268
269	nextval = (unsigned long)mod_mem->base + mod_mem->size;
270
271	bestval = kallsyms_symbol_value(&kallsyms->symtab[best]);
272
273	/*
274	 * Scan for closest preceding symbol, and next symbol. (ELF
275	 * starts real symbols at 1).
276	 */
277	for (i = 1; i < kallsyms->num_symtab; i++) {
278		const Elf_Sym *sym = &kallsyms->symtab[i];
279		unsigned long thisval = kallsyms_symbol_value(sym);
280
281		if (sym->st_shndx == SHN_UNDEF)
282			continue;
283
284		/*
285		 * We ignore unnamed symbols: they're uninformative
286		 * and inserted at a whim.
287		 */
288		if (*kallsyms_symbol_name(kallsyms, i) == '\0' ||
289		    is_mapping_symbol(kallsyms_symbol_name(kallsyms, i)))
290			continue;
291
292		if (thisval <= addr && thisval > bestval) {
293			best = i;
294			bestval = thisval;
295		}
296		if (thisval > addr && thisval < nextval)
297			nextval = thisval;
298	}
299
300	if (!best)
301		return NULL;
302
303	if (size)
304		*size = nextval - bestval;
305	if (offset)
306		*offset = addr - bestval;
307
308	return kallsyms_symbol_name(kallsyms, best);
309}
310
311void * __weak dereference_module_function_descriptor(struct module *mod,
312						     void *ptr)
313{
314	return ptr;
315}
316
317/*
318 * For kallsyms to ask for address resolution.  NULL means not found.  Careful
319 * not to lock to avoid deadlock on oopses, RCU is enough.
320 */
321int module_address_lookup(unsigned long addr,
322			  unsigned long *size,
323			  unsigned long *offset,
324			  char **modname,
325			  const unsigned char **modbuildid,
326			  char *namebuf)
327{
328	const char *sym;
329	int ret = 0;
330	struct module *mod;
331
332	guard(rcu)();
333	mod = __module_address(addr);
334	if (mod) {
335		if (modname)
336			*modname = mod->name;
337		if (modbuildid)
338			*modbuildid = module_buildid(mod);
339
340		sym = find_kallsyms_symbol(mod, addr, size, offset);
341
342		if (sym)
343			ret = strscpy(namebuf, sym, KSYM_NAME_LEN);
344	}
345	return ret;
346}
347
348int lookup_module_symbol_name(unsigned long addr, char *symname)
349{
350	struct module *mod;
351
352	guard(rcu)();
353	list_for_each_entry_rcu(mod, &modules, list) {
354		if (mod->state == MODULE_STATE_UNFORMED)
355			continue;
356		if (within_module(addr, mod)) {
357			const char *sym;
358
359			sym = find_kallsyms_symbol(mod, addr, NULL, NULL);
360			if (!sym)
361				goto out;
362
363			strscpy(symname, sym, KSYM_NAME_LEN);
364			return 0;
365		}
366	}
367out:
368	return -ERANGE;
369}
370
371int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
372		       char *name, char *module_name, int *exported)
373{
374	struct module *mod;
375
376	guard(rcu)();
377	list_for_each_entry_rcu(mod, &modules, list) {
378		struct mod_kallsyms *kallsyms;
379
380		if (mod->state == MODULE_STATE_UNFORMED)
381			continue;
382		kallsyms = rcu_dereference(mod->kallsyms);
383		if (symnum < kallsyms->num_symtab) {
384			const Elf_Sym *sym = &kallsyms->symtab[symnum];
385
386			*value = kallsyms_symbol_value(sym);
387			*type = kallsyms->typetab[symnum];
388			strscpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN);
389			strscpy(module_name, mod->name, MODULE_NAME_LEN);
390			*exported = is_exported(name, *value, mod);
391			return 0;
392		}
393		symnum -= kallsyms->num_symtab;
394	}
395	return -ERANGE;
396}
397
398/* Given a module and name of symbol, find and return the symbol's value */
399static unsigned long __find_kallsyms_symbol_value(struct module *mod, const char *name)
400{
401	unsigned int i;
402	struct mod_kallsyms *kallsyms = rcu_dereference(mod->kallsyms);
403
404	for (i = 0; i < kallsyms->num_symtab; i++) {
405		const Elf_Sym *sym = &kallsyms->symtab[i];
406
407		if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 &&
408		    sym->st_shndx != SHN_UNDEF)
409			return kallsyms_symbol_value(sym);
410	}
411	return 0;
412}
413
414static unsigned long __module_kallsyms_lookup_name(const char *name)
415{
416	struct module *mod;
417	char *colon;
418
419	colon = strnchr(name, MODULE_NAME_LEN, ':');
420	if (colon) {
421		mod = find_module_all(name, colon - name, false);
422		if (mod)
423			return __find_kallsyms_symbol_value(mod, colon + 1);
424		return 0;
425	}
426
427	list_for_each_entry_rcu(mod, &modules, list) {
428		unsigned long ret;
429
430		if (mod->state == MODULE_STATE_UNFORMED)
431			continue;
432		ret = __find_kallsyms_symbol_value(mod, name);
433		if (ret)
434			return ret;
435	}
436	return 0;
437}
438
439/* Look for this name: can be of form module:name. */
440unsigned long module_kallsyms_lookup_name(const char *name)
441{
442	/* Don't lock: we're in enough trouble already. */
443	guard(rcu)();
444	return __module_kallsyms_lookup_name(name);
445}
446
447unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name)
448{
449	guard(rcu)();
450	return __find_kallsyms_symbol_value(mod, name);
451}
452
453int module_kallsyms_on_each_symbol(const char *modname,
454				   int (*fn)(void *, const char *, unsigned long),
455				   void *data)
456{
457	struct module *mod;
458	unsigned int i;
459	int ret = 0;
460
461	mutex_lock(&module_mutex);
462	list_for_each_entry(mod, &modules, list) {
463		struct mod_kallsyms *kallsyms;
464
465		if (mod->state == MODULE_STATE_UNFORMED)
466			continue;
467
468		if (modname && strcmp(modname, mod->name))
469			continue;
470
471		kallsyms = rcu_dereference_check(mod->kallsyms,
472						 lockdep_is_held(&module_mutex));
473
474		for (i = 0; i < kallsyms->num_symtab; i++) {
475			const Elf_Sym *sym = &kallsyms->symtab[i];
476
477			if (sym->st_shndx == SHN_UNDEF)
478				continue;
479
480			ret = fn(data, kallsyms_symbol_name(kallsyms, i),
481				 kallsyms_symbol_value(sym));
482			if (ret != 0)
483				goto out;
484		}
485
486		/*
487		 * The given module is found, the subsequent modules do not
488		 * need to be compared.
489		 */
490		if (modname)
491			break;
492	}
493out:
494	mutex_unlock(&module_mutex);
495	return ret;
496}
~/ Read-only file preview.