Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f9f852c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull modules updates from Jessica Yu:

 - Some modules-related kallsyms cleanups and a kallsyms fix for ARM.

 - Include keys from the secondary keyring in module signature
   verification.

* tag 'modules-for-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
  ARM: module: Fix function kallsyms on Thumb-2
  module: Overwrite st_size instead of st_info
  module: make it clearer when we're handling kallsyms symbols vs exported symbols
  modsign: use all trusted keys to verify module signature
parents 3f03bf93 93d77e7f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -61,4 +61,15 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val);
	MODULE_ARCH_VERMAGIC_ARMTHUMB \
	MODULE_ARCH_VERMAGIC_P2V

#ifdef CONFIG_THUMB2_KERNEL
#define HAVE_ARCH_KALLSYMS_SYMBOL_VALUE
static inline unsigned long kallsyms_symbol_value(const Elf_Sym *sym)
{
	if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
		return sym->st_value & ~1;

	return sym->st_value;
}
#endif

#endif /* _ASM_ARM_MODULE_H */
+7 −0
Original line number Diff line number Diff line
@@ -486,6 +486,13 @@ struct module {
#define MODULE_ARCH_INIT {}
#endif

#ifndef HAVE_ARCH_KALLSYMS_SYMBOL_VALUE
static inline unsigned long kallsyms_symbol_value(const Elf_Sym *sym)
{
	return sym->st_value;
}
#endif

extern struct mutex module_mutex;

/* FIXME: It'd be nice to isolate modules during init, too, so they
+72 −51
Original line number Diff line number Diff line
@@ -495,7 +495,7 @@ struct find_symbol_arg {
	const struct kernel_symbol *sym;
};

static bool check_symbol(const struct symsearch *syms,
static bool check_exported_symbol(const struct symsearch *syms,
				  struct module *owner,
				  unsigned int symnum, void *data)
{
@@ -555,7 +555,7 @@ static int cmp_name(const void *va, const void *vb)
	return strcmp(a, kernel_symbol_name(b));
}

static bool find_symbol_in_section(const struct symsearch *syms,
static bool find_exported_symbol_in_section(const struct symsearch *syms,
					    struct module *owner,
					    void *data)
{
@@ -565,13 +565,14 @@ static bool find_symbol_in_section(const struct symsearch *syms,
	sym = bsearch(fsa->name, syms->start, syms->stop - syms->start,
			sizeof(struct kernel_symbol), cmp_name);

	if (sym != NULL && check_symbol(syms, owner, sym - syms->start, data))
	if (sym != NULL && check_exported_symbol(syms, owner,
						 sym - syms->start, data))
		return true;

	return false;
}

/* Find a symbol and return it, along with, (optional) crc and
/* Find an exported symbol and return it, along with, (optional) crc and
 * (optional) module which owns it.  Needs preempt disabled or module_mutex. */
const struct kernel_symbol *find_symbol(const char *name,
					struct module **owner,
@@ -585,7 +586,7 @@ const struct kernel_symbol *find_symbol(const char *name,
	fsa.gplok = gplok;
	fsa.warn = warn;

	if (each_symbol_section(find_symbol_in_section, &fsa)) {
	if (each_symbol_section(find_exported_symbol_in_section, &fsa)) {
		if (owner)
			*owner = fsa.owner;
		if (crc)
@@ -2198,7 +2199,7 @@ EXPORT_SYMBOL_GPL(__symbol_get);
 *
 * You must hold the module_mutex.
 */
static int verify_export_symbols(struct module *mod)
static int verify_exported_symbols(struct module *mod)
{
	unsigned int i;
	struct module *owner;
@@ -2519,8 +2520,8 @@ static void free_modinfo(struct module *mod)

#ifdef CONFIG_KALLSYMS

/* lookup symbol in given range of kernel_symbols */
static const struct kernel_symbol *lookup_symbol(const char *name,
/* Lookup exported symbol in given range of kernel_symbols */
static const struct kernel_symbol *lookup_exported_symbol(const char *name,
							  const struct kernel_symbol *start,
							  const struct kernel_symbol *stop)
{
@@ -2533,9 +2534,10 @@ static int is_exported(const char *name, unsigned long value,
{
	const struct kernel_symbol *ks;
	if (!mod)
		ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
		ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab);
	else
		ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
		ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms);

	return ks != NULL && kernel_symbol_value(ks) == value;
}

@@ -2682,7 +2684,7 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)

	/* Set types up while we still have access to sections. */
	for (i = 0; i < mod->kallsyms->num_symtab; i++)
		mod->kallsyms->symtab[i].st_info
		mod->kallsyms->symtab[i].st_size
			= elf_type(&mod->kallsyms->symtab[i], info);

	/* Now populate the cut down core kallsyms for after init. */
@@ -3592,7 +3594,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
	mutex_lock(&module_mutex);

	/* Find duplicate symbols (must be called under lock). */
	err = verify_export_symbols(mod);
	err = verify_exported_symbols(mod);
	if (err < 0)
		goto out;

@@ -3911,18 +3913,22 @@ static inline int is_arm_mapping_symbol(const char *str)
	       && (str[2] == '\0' || str[2] == '.');
}

static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum)
static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum)
{
	return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
}

static const char *get_ksymbol(struct module *mod,
/*
 * Given a module and address, find the corresponding symbol and return its name
 * while providing its size and offset if needed.
 */
static const char *find_kallsyms_symbol(struct module *mod,
					unsigned long addr,
					unsigned long *size,
					unsigned long *offset)
{
	unsigned int i, best = 0;
	unsigned long nextval;
	unsigned long nextval, bestval;
	struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);

	/* At worse, next value is at end of module */
@@ -3931,34 +3937,40 @@ static const char *get_ksymbol(struct module *mod,
	else
		nextval = (unsigned long)mod->core_layout.base+mod->core_layout.text_size;

	bestval = kallsyms_symbol_value(&kallsyms->symtab[best]);

	/* Scan for closest preceding symbol, and next symbol. (ELF
	   starts real symbols at 1). */
	for (i = 1; i < kallsyms->num_symtab; i++) {
		if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
		const Elf_Sym *sym = &kallsyms->symtab[i];
		unsigned long thisval = kallsyms_symbol_value(sym);

		if (sym->st_shndx == SHN_UNDEF)
			continue;

		/* We ignore unnamed symbols: they're uninformative
		 * and inserted at a whim. */
		if (*symname(kallsyms, i) == '\0'
		    || is_arm_mapping_symbol(symname(kallsyms, i)))
		if (*kallsyms_symbol_name(kallsyms, i) == '\0'
		    || is_arm_mapping_symbol(kallsyms_symbol_name(kallsyms, i)))
			continue;

		if (kallsyms->symtab[i].st_value <= addr
		    && kallsyms->symtab[i].st_value > kallsyms->symtab[best].st_value)
		if (thisval <= addr && thisval > bestval) {
			best = i;
		if (kallsyms->symtab[i].st_value > addr
		    && kallsyms->symtab[i].st_value < nextval)
			nextval = kallsyms->symtab[i].st_value;
			bestval = thisval;
		}
		if (thisval > addr && thisval < nextval)
			nextval = thisval;
	}

	if (!best)
		return NULL;

	if (size)
		*size = nextval - kallsyms->symtab[best].st_value;
		*size = nextval - bestval;
	if (offset)
		*offset = addr - kallsyms->symtab[best].st_value;
	return symname(kallsyms, best);
		*offset = addr - bestval;

	return kallsyms_symbol_name(kallsyms, best);
}

void * __weak dereference_module_function_descriptor(struct module *mod,
@@ -3983,7 +3995,8 @@ const char *module_address_lookup(unsigned long addr,
	if (mod) {
		if (modname)
			*modname = mod->name;
		ret = get_ksymbol(mod, addr, size, offset);

		ret = find_kallsyms_symbol(mod, addr, size, offset);
	}
	/* Make a copy in here where it's safe */
	if (ret) {
@@ -4006,9 +4019,10 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)
		if (within_module(addr, mod)) {
			const char *sym;

			sym = get_ksymbol(mod, addr, NULL, NULL);
			sym = find_kallsyms_symbol(mod, addr, NULL, NULL);
			if (!sym)
				goto out;

			strlcpy(symname, sym, KSYM_NAME_LEN);
			preempt_enable();
			return 0;
@@ -4031,7 +4045,7 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
		if (within_module(addr, mod)) {
			const char *sym;

			sym = get_ksymbol(mod, addr, size, offset);
			sym = find_kallsyms_symbol(mod, addr, size, offset);
			if (!sym)
				goto out;
			if (modname)
@@ -4060,9 +4074,11 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
			continue;
		kallsyms = rcu_dereference_sched(mod->kallsyms);
		if (symnum < kallsyms->num_symtab) {
			*value = kallsyms->symtab[symnum].st_value;
			*type = kallsyms->symtab[symnum].st_info;
			strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN);
			const Elf_Sym *sym = &kallsyms->symtab[symnum];

			*value = kallsyms_symbol_value(sym);
			*type = sym->st_size;
			strlcpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN);
			strlcpy(module_name, mod->name, MODULE_NAME_LEN);
			*exported = is_exported(name, *value, mod);
			preempt_enable();
@@ -4074,15 +4090,19 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
	return -ERANGE;
}

static unsigned long mod_find_symname(struct module *mod, const char *name)
/* Given a module and name of symbol, find and return the symbol's value */
static unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name)
{
	unsigned int i;
	struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);

	for (i = 0; i < kallsyms->num_symtab; i++)
		if (strcmp(name, symname(kallsyms, i)) == 0 &&
		    kallsyms->symtab[i].st_shndx != SHN_UNDEF)
			return kallsyms->symtab[i].st_value;
	for (i = 0; i < kallsyms->num_symtab; i++) {
		const Elf_Sym *sym = &kallsyms->symtab[i];

		if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 &&
		    sym->st_shndx != SHN_UNDEF)
			return kallsyms_symbol_value(sym);
	}
	return 0;
}

@@ -4097,12 +4117,12 @@ unsigned long module_kallsyms_lookup_name(const char *name)
	preempt_disable();
	if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) {
		if ((mod = find_module_all(name, colon - name, false)) != NULL)
			ret = mod_find_symname(mod, colon+1);
			ret = find_kallsyms_symbol_value(mod, colon+1);
	} else {
		list_for_each_entry_rcu(mod, &modules, list) {
			if (mod->state == MODULE_STATE_UNFORMED)
				continue;
			if ((ret = mod_find_symname(mod, name)) != 0)
			if ((ret = find_kallsyms_symbol_value(mod, name)) != 0)
				break;
		}
	}
@@ -4127,12 +4147,13 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
		if (mod->state == MODULE_STATE_UNFORMED)
			continue;
		for (i = 0; i < kallsyms->num_symtab; i++) {
			const Elf_Sym *sym = &kallsyms->symtab[i];

			if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
			if (sym->st_shndx == SHN_UNDEF)
				continue;

			ret = fn(data, symname(kallsyms, i),
				 mod, kallsyms->symtab[i].st_value);
			ret = fn(data, kallsyms_symbol_name(kallsyms, i),
				 mod, kallsyms_symbol_value(sym));
			if (ret != 0)
				return ret;
		}
+2 −1
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ int mod_verify_sig(const void *mod, struct load_info *info)
	}

	return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
				      NULL, VERIFYING_MODULE_SIGNATURE,
				      VERIFY_USE_SECONDARY_KEYRING,
				      VERIFYING_MODULE_SIGNATURE,
				      NULL, NULL);
}