]> Git Repo - linux.git/commitdiff
Merge tag 'modules-for-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu...
authorLinus Torvalds <[email protected]>
Fri, 30 Apr 2021 19:29:36 +0000 (12:29 -0700)
committerLinus Torvalds <[email protected]>
Fri, 30 Apr 2021 19:29:36 +0000 (12:29 -0700)
Pull module updates from Jessica Yu:
 "Fix an age old bug involving jump_calls and static_labels when
  CONFIG_MODULE_UNLOAD=n.

  When CONFIG_MODULE_UNLOAD=n, it means you can't unload modules, so
  normally the __exit sections of a module are not loaded at all.
  However, dynamic code patching (jump_label, static_call, alternatives)
  can have sites in __exit sections even if __exit is never executed.

  Reported by Peter Zijlstra:
     'Alternatives, jump_labels and static_call all can have relocations
      into __exit code. Not loading it at all would be BAD.'

  Therefore, load the __exit sections even when CONFIG_MODULE_UNLOAD=n,
  and discard them after init"

* tag 'modules-for-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
  module: treat exit sections the same as init sections when !CONFIG_MODULE_UNLOAD

1  2 
kernel/module.c

diff --combined kernel/module.c
index 20fb004e7d8da0f851c540919fcc52fc1364e881,173a09175511984e05539b676f165bb2f08e34e5..b5dd92e35b02a78b44532cbdcf69292350dca456
@@@ -2146,8 -2146,6 +2146,8 @@@ void __weak module_arch_freeing_init(st
  {
  }
  
 +static void cfi_cleanup(struct module *mod);
 +
  /* Free a module, remove from lists, etc. */
  static void free_module(struct module *mod)
  {
        synchronize_rcu();
        mutex_unlock(&module_mutex);
  
 +      /* Clean up CFI for the module. */
 +      cfi_cleanup(mod);
 +
        /* This may be empty, but that's OK */
        module_arch_freeing_init(mod);
        module_memfree(mod->init_layout.base);
@@@ -2807,7 -2802,11 +2807,11 @@@ void * __weak module_alloc(unsigned lon
  
  bool __weak module_init_section(const char *name)
  {
+ #ifndef CONFIG_MODULE_UNLOAD
+       return strstarts(name, ".init") || module_exit_section(name);
+ #else
        return strstarts(name, ".init");
+ #endif
  }
  
  bool __weak module_exit_section(const char *name)
@@@ -3121,11 -3120,6 +3125,6 @@@ static int rewrite_section_headers(stru
                 */
                shdr->sh_addr = (size_t)info->hdr + shdr->sh_offset;
  
- #ifndef CONFIG_MODULE_UNLOAD
-               /* Don't load .exit sections */
-               if (module_exit_section(info->secstrings+shdr->sh_name))
-                       shdr->sh_flags &= ~(unsigned long)SHF_ALLOC;
- #endif
        }
  
        /* Track but don't keep modinfo and version sections. */
@@@ -3871,8 -3865,6 +3870,8 @@@ static int unknown_module_param_cb(cha
        return 0;
  }
  
 +static void cfi_init(struct module *mod);
 +
  /*
   * Allocate and load the module: note that size of section 0 is always
   * zero, and we rely on this for optional sections.
@@@ -4004,9 -3996,6 +4003,9 @@@ static int load_module(struct load_inf
  
        flush_module_icache(mod);
  
 +      /* Setup CFI for the module. */
 +      cfi_init(mod);
 +
        /* Now copy in args */
        mod->args = strndup_user(uargs, ~0UL >> 1);
        if (IS_ERR(mod->args)) {
        synchronize_rcu();
        kfree(mod->args);
   free_arch_cleanup:
 +      cfi_cleanup(mod);
        module_arch_cleanup(mod);
   free_modinfo:
        free_modinfo(mod);
@@@ -4426,38 -4414,6 +4425,38 @@@ int module_kallsyms_on_each_symbol(int 
  #endif /* CONFIG_LIVEPATCH */
  #endif /* CONFIG_KALLSYMS */
  
 +static void cfi_init(struct module *mod)
 +{
 +#ifdef CONFIG_CFI_CLANG
 +      initcall_t *init;
 +      exitcall_t *exit;
 +
 +      rcu_read_lock_sched();
 +      mod->cfi_check = (cfi_check_fn)
 +              find_kallsyms_symbol_value(mod, "__cfi_check");
 +      init = (initcall_t *)
 +              find_kallsyms_symbol_value(mod, "__cfi_jt_init_module");
 +      exit = (exitcall_t *)
 +              find_kallsyms_symbol_value(mod, "__cfi_jt_cleanup_module");
 +      rcu_read_unlock_sched();
 +
 +      /* Fix init/exit functions to point to the CFI jump table */
 +      if (init)
 +              mod->init = *init;
 +      if (exit)
 +              mod->exit = *exit;
 +
 +      cfi_module_add(mod, module_addr_min);
 +#endif
 +}
 +
 +static void cfi_cleanup(struct module *mod)
 +{
 +#ifdef CONFIG_CFI_CLANG
 +      cfi_module_remove(mod, module_addr_min);
 +#endif
 +}
 +
  /* Maximum number of characters written by module_flags() */
  #define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
  
This page took 0.070661 seconds and 4 git commands to generate.