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