]> Git Repo - linux.git/commitdiff
Merge tag 'modules-for-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu...
authorLinus Torvalds <[email protected]>
Thu, 27 Dec 2018 20:08:33 +0000 (12:08 -0800)
committerLinus Torvalds <[email protected]>
Thu, 27 Dec 2018 20:08:33 +0000 (12:08 -0800)
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

1  2 
kernel/module.c

diff --combined kernel/module.c
index 99b46c32d579efca2c42879d143a2e8a9ae6e849,164bf201eae4ce9f9375b833b3d8399febe725d7..339b3cd39dd4b81eb66963034b0a74de3ba2a700
@@@ -495,9 -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 +555,9 @@@ static int cmp_name(const void *va, con
        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;
        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,
        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)
@@@ -2159,7 -2160,7 +2160,7 @@@ static void free_module(struct module *
        /* Remove this module from bug list, this uses list_del_rcu */
        module_bug_cleanup(mod);
        /* Wait for RCU-sched synchronizing before releasing mod->list and buglist. */
 -      synchronize_sched();
 +      synchronize_rcu();
        mutex_unlock(&module_mutex);
  
        /* This may be empty, but that's OK */
@@@ -2198,7 -2199,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 +2520,10 @@@ static void free_modinfo(struct module 
  
  #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 +2534,10 @@@ static int is_exported(const char *name
  {
        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 +2684,7 @@@ static void add_kallsyms(struct module 
  
        /* 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. */
@@@ -3507,15 -3509,15 +3509,15 @@@ static noinline int do_init_module(stru
        /*
         * We want to free module_init, but be aware that kallsyms may be
         * walking this with preempt disabled.  In all the failure paths, we
 -       * call synchronize_sched(), but we don't want to slow down the success
 +       * call synchronize_rcu(), but we don't want to slow down the success
         * path, so use actual RCU here.
         * Note that module_alloc() on most architectures creates W+X page
         * mappings which won't be cleaned up until do_free_init() runs.  Any
         * code such as mark_rodata_ro() which depends on those mappings to
         * be cleaned up needs to sync with the queued work - ie
 -       * rcu_barrier_sched()
 +       * rcu_barrier()
         */
 -      call_rcu_sched(&freeinit->rcu, do_free_init);
 +      call_rcu(&freeinit->rcu, do_free_init);
        mutex_unlock(&module_mutex);
        wake_up_all(&module_wq);
  
@@@ -3526,7 -3528,7 +3528,7 @@@ fail_free_freeinit
  fail:
        /* Try to protect us from buggy refcounters. */
        mod->state = MODULE_STATE_GOING;
 -      synchronize_sched();
 +      synchronize_rcu();
        module_put(mod);
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_GOING, mod);
@@@ -3592,7 -3594,7 +3594,7 @@@ static int complete_formation(struct mo
        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;
  
@@@ -3819,7 -3821,7 +3821,7 @@@ static int load_module(struct load_inf
   ddebug_cleanup:
        ftrace_release_mod(mod);
        dynamic_debug_remove(mod, info->debug);
 -      synchronize_sched();
 +      synchronize_rcu();
        kfree(mod->args);
   free_arch_cleanup:
        module_arch_cleanup(mod);
        mod_tree_remove(mod);
        wake_up_all(&module_wq);
        /* Wait for RCU-sched synchronizing before releasing mod->list. */
 -      synchronize_sched();
 +      synchronize_rcu();
        mutex_unlock(&module_mutex);
   free_module:
        /* Free lock-classes; relies on the preceding sync_rcu() */
@@@ -3911,18 -3913,22 +3913,22 @@@ static inline int is_arm_mapping_symbol
               && (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 */
        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 +3995,8 @@@ const char *module_address_lookup(unsig
        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 +4019,10 @@@ int lookup_module_symbol_name(unsigned 
                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 +4045,7 @@@ int lookup_module_symbol_attrs(unsigne
                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 +4074,11 @@@ int module_get_kallsym(unsigned int sym
                        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();
        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 +4117,12 @@@ unsigned long module_kallsyms_lookup_na
        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 +4147,13 @@@ int module_kallsyms_on_each_symbol(int 
                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;
                }
This page took 0.095639 seconds and 4 git commands to generate.