mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 21:24:08 +08:00
Modules updates for v4.21
Summary of modules changes for the 4.21 merge window: - Some modules-related kallsyms cleanups and a kallsyms fix for ARM. - Include keys from the secondary keyring in module signature verification. Signed-off-by: Jessica Yu <jeyu@kernel.org> -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJcFzpbAAoJEMBFfjjOO8FyxOAP/jqIyJ08IThhgEWcsXwCgvir a5PtovqAwP3pWXJ0SE64/Hz4edwcPUnUvzt6nia7JELgZWukIQcjA/Yav4w65KA6 kNAW4+BY41vjGpFBtObgMjU9dcEr8QPhO4362s7sPwxYaoRMI+uYHzEkxDvJaL8p 1d5g/xdX+82rTQUwgzxHHqrfoHbL0H83eVLTG6YtmWCDHdXGq4lI7ZvHd87Qii3H PoL1ALiFyf0eO1Gouaivox3tBkpX6hI8Kl9Tm8lL0dIlIn3AcXj869T/h6jbhqMT qpMazFokSWGZ1m2sCfaxoA6L+MUqgn0zHSLm68B69CHj483919QsQ5wpHSmpT2Jp /szUuO1vHDd/e+nMGvxO0teg94OUfJ+J08RNC0B+QJ3dclOARR3z2Qnx1nR+7go/ nBSjlFvedx7wvv9hIHYJdPdtxy7qOwY+jLW2nDXUwYSIkpJKq5Fm1qYlqEJhyuhy bQgTCR4da0iMdCuccHXS3XYhIsqgNDhZpcBu19ToRCH7RroitK/8rBssMCVsd0WB uSLgdkgkZrpOMzb/lQv8IDvqXOUrU2Tm2SUikUiZWzQGEvkeD6rDjxSxhEUbq5+m ZujOgp5EE4Li5PXUeX5rqMOxNmNysvOK8r0pynn6D2c77x/hDNuLHQQ5OFT9kPNs qInek4B09h0gij4OgSRp =vevq -----END PGP SIGNATURE----- Merge tag 'modules-for-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux 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
This commit is contained in:
commit
7f9f852c75
@ -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 */
|
||||
|
@ -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
|
||||
|
123
kernel/module.c
123
kernel/module.c
@ -495,9 +495,9 @@ struct find_symbol_arg {
|
||||
const struct kernel_symbol *sym;
|
||||
};
|
||||
|
||||
static bool check_symbol(const struct symsearch *syms,
|
||||
struct module *owner,
|
||||
unsigned int symnum, void *data)
|
||||
static bool check_exported_symbol(const struct symsearch *syms,
|
||||
struct module *owner,
|
||||
unsigned int symnum, void *data)
|
||||
{
|
||||
struct find_symbol_arg *fsa = data;
|
||||
|
||||
@ -555,9 +555,9 @@ 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,
|
||||
struct module *owner,
|
||||
void *data)
|
||||
static bool find_exported_symbol_in_section(const struct symsearch *syms,
|
||||
struct module *owner,
|
||||
void *data)
|
||||
{
|
||||
struct find_symbol_arg *fsa = data;
|
||||
struct kernel_symbol *sym;
|
||||
@ -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,10 +2520,10 @@ 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,
|
||||
const struct kernel_symbol *start,
|
||||
const struct kernel_symbol *stop)
|
||||
/* 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)
|
||||
{
|
||||
return bsearch(name, start, stop - start,
|
||||
sizeof(struct kernel_symbol), cmp_name);
|
||||
@ -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,
|
||||
unsigned long addr,
|
||||
unsigned long *size,
|
||||
unsigned long *offset)
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user