]> Git Repo - linux.git/commitdiff
Merge tag 'modules-for-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu...
authorLinus Torvalds <[email protected]>
Fri, 5 Jun 2020 19:31:16 +0000 (12:31 -0700)
committerLinus Torvalds <[email protected]>
Fri, 5 Jun 2020 19:31:16 +0000 (12:31 -0700)
Pull module updates from Jessica Yu:

 - Harden CONFIG_STRICT_MODULE_RWX by rejecting any module that has
   SHF_WRITE|SHF_EXECINSTR sections

 - Remove and clean up nested #ifdefs, as it makes code hard to read

* tag 'modules-for-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
  module: Harden STRICT_MODULE_RWX
  module: break nested ARCH_HAS_STRICT_MODULE_RWX and STRICT_MODULE_RWX #ifdefs

1  2 
kernel/module.c

diff --combined kernel/module.c
index bca993c5f1bc7c6572700238464e86d58c5ffd63,70fc20583e6620eb0a42eb8e7de0e1d2567a471f..ef400c389f4963596ed5f0fcf5ce3c0490aa4886
@@@ -4,9 -4,6 +4,9 @@@
     Copyright (C) 2001 Rusty Russell, 2002, 2010 Rusty Russell IBM.
  
  */
 +
 +#define INCLUDE_VERMAGIC
 +
  #include <linux/export.h>
  #include <linux/extable.h>
  #include <linux/moduleloader.h>
@@@ -1946,7 -1943,6 +1946,6 @@@ static void mod_sysfs_teardown(struct m
        mod_sysfs_fini(mod);
  }
  
- #ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX
  /*
   * LKM RO/NX protection: protect module's text/ro-data
   * from modification and any data from execution.
   *
   * These values are always page-aligned (as is base)
   */
+ /*
+  * Since some arches are moving towards PAGE_KERNEL module allocations instead
+  * of PAGE_KERNEL_EXEC, keep frob_text() and module_enable_x() outside of the
+  * CONFIG_STRICT_MODULE_RWX block below because they are needed regardless of
+  * whether we are strict.
+  */
+ #ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX
  static void frob_text(const struct module_layout *layout,
                      int (*set_memory)(unsigned long start, int num_pages))
  {
                   layout->text_size >> PAGE_SHIFT);
  }
  
+ static void module_enable_x(const struct module *mod)
+ {
+       frob_text(&mod->core_layout, set_memory_x);
+       frob_text(&mod->init_layout, set_memory_x);
+ }
+ #else /* !CONFIG_ARCH_HAS_STRICT_MODULE_RWX */
+ static void module_enable_x(const struct module *mod) { }
+ #endif /* CONFIG_ARCH_HAS_STRICT_MODULE_RWX */
  #ifdef CONFIG_STRICT_MODULE_RWX
  static void frob_rodata(const struct module_layout *layout,
                        int (*set_memory)(unsigned long start, int num_pages))
@@@ -2000,7 -2013,20 +2016,7 @@@ static void frob_writable_data(const st
                   (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
  }
  
 -/* livepatching wants to disable read-only so it can frob module. */
 -void module_disable_ro(const struct module *mod)
 -{
 -      if (!rodata_enabled)
 -              return;
 -
 -      frob_text(&mod->core_layout, set_memory_rw);
 -      frob_rodata(&mod->core_layout, set_memory_rw);
 -      frob_ro_after_init(&mod->core_layout, set_memory_rw);
 -      frob_text(&mod->init_layout, set_memory_rw);
 -      frob_rodata(&mod->init_layout, set_memory_rw);
 -}
 -
 -void module_enable_ro(const struct module *mod, bool after_init)
 +static void module_enable_ro(const struct module *mod, bool after_init)
  {
        if (!rodata_enabled)
                return;
@@@ -2026,20 -2052,29 +2042,29 @@@ static void module_enable_nx(const stru
        frob_writable_data(&mod->init_layout, set_memory_nx);
  }
  
+ static int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+                                      char *secstrings, struct module *mod)
+ {
+       const unsigned long shf_wx = SHF_WRITE|SHF_EXECINSTR;
+       int i;
+       for (i = 0; i < hdr->e_shnum; i++) {
+               if ((sechdrs[i].sh_flags & shf_wx) == shf_wx)
+                       return -ENOEXEC;
+       }
+       return 0;
+ }
  #else /* !CONFIG_STRICT_MODULE_RWX */
 -/* module_{enable,disable}_ro() stubs are in module.h */
  static void module_enable_nx(const struct module *mod) { }
- #endif /*  CONFIG_STRICT_MODULE_RWX */
- static void module_enable_x(const struct module *mod)
 +static void module_enable_ro(const struct module *mod, bool after_init) {}
+ static int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+                                      char *secstrings, struct module *mod)
  {
-       frob_text(&mod->core_layout, set_memory_x);
-       frob_text(&mod->init_layout, set_memory_x);
+       return 0;
  }
- #else /* !CONFIG_ARCH_HAS_STRICT_MODULE_RWX */
- static void module_enable_nx(const struct module *mod) { }
- static void module_enable_x(const struct module *mod) { }
- #endif /* CONFIG_ARCH_HAS_STRICT_MODULE_RWX */
+ #endif /*  CONFIG_STRICT_MODULE_RWX */
  
  #ifdef CONFIG_LIVEPATCH
  /*
@@@ -2325,13 -2360,11 +2350,13 @@@ static int apply_relocations(struct mod
                if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC))
                        continue;
  
 -              /* Livepatch relocation sections are applied by livepatch */
                if (info->sechdrs[i].sh_flags & SHF_RELA_LIVEPATCH)
 -                      continue;
 -
 -              if (info->sechdrs[i].sh_type == SHT_REL)
 +                      err = klp_apply_section_relocs(mod, info->sechdrs,
 +                                                     info->secstrings,
 +                                                     info->strtab,
 +                                                     info->index.sym, i,
 +                                                     NULL);
 +              else if (info->sechdrs[i].sh_type == SHT_REL)
                        err = apply_relocate(info->sechdrs, info->strtab,
                                             info->index.sym, i, mod);
                else if (info->sechdrs[i].sh_type == SHT_RELA)
@@@ -2393,7 -2426,7 +2418,7 @@@ static void layout_sections(struct modu
                        if ((s->sh_flags & masks[m][0]) != masks[m][0]
                            || (s->sh_flags & masks[m][1])
                            || s->sh_entsize != ~0UL
 -                          || strstarts(sname, ".init"))
 +                          || module_init_section(sname))
                                continue;
                        s->sh_entsize = get_offset(mod, &mod->core_layout.size, s, i);
                        pr_debug("\t%s\n", sname);
                        if ((s->sh_flags & masks[m][0]) != masks[m][0]
                            || (s->sh_flags & masks[m][1])
                            || s->sh_entsize != ~0UL
 -                          || !strstarts(sname, ".init"))
 +                          || !module_init_section(sname))
                                continue;
                        s->sh_entsize = (get_offset(mod, &mod->init_layout.size, s, i)
                                         | INIT_OFFSET_MASK);
@@@ -2761,11 -2794,6 +2786,11 @@@ void * __weak module_alloc(unsigned lon
        return vmalloc_exec(size);
  }
  
 +bool __weak module_init_section(const char *name)
 +{
 +      return strstarts(name, ".init");
 +}
 +
  bool __weak module_exit_section(const char *name)
  {
        return strstarts(name, ".exit");
@@@ -2944,7 -2972,8 +2969,7 @@@ static int copy_module_from_user(const 
                return err;
  
        /* Suck in entire file: we'll want most of it. */
 -      info->hdr = __vmalloc(info->len,
 -                      GFP_KERNEL | __GFP_NOWARN, PAGE_KERNEL);
 +      info->hdr = __vmalloc(info->len, GFP_KERNEL | __GFP_NOWARN);
        if (!info->hdr)
                return -ENOMEM;
  
@@@ -3147,9 -3176,6 +3172,9 @@@ static int find_module_sections(struct 
        }
  #endif
  
 +      mod->noinstr_text_start = section_objs(info, ".noinstr.text", 1,
 +                                              &mod->noinstr_text_size);
 +
  #ifdef CONFIG_TRACEPOINTS
        mod->tracepoints_ptrs = section_objs(info, "__tracepoints_ptrs",
                                             sizeof(*mod->tracepoints_ptrs),
        mod->ei_funcs = section_objs(info, "_error_injection_whitelist",
                                            sizeof(*mod->ei_funcs),
                                            &mod->num_ei_funcs);
 +#endif
 +#ifdef CONFIG_KPROBES
 +      mod->kprobes_text_start = section_objs(info, ".kprobes.text", 1,
 +                                              &mod->kprobes_text_size);
 +      mod->kprobe_blacklist = section_objs(info, "_kprobe_blacklist",
 +                                              sizeof(unsigned long),
 +                                              &mod->num_kprobe_blacklist);
  #endif
        mod->extable = section_objs(info, "__ex_table",
                                    sizeof(*mod->extable), &mod->num_exentries);
@@@ -3385,6 -3404,11 +3410,11 @@@ static struct module *layout_and_alloca
        if (err < 0)
                return ERR_PTR(err);
  
+       err = module_enforce_rwx_sections(info->hdr, info->sechdrs,
+                                         info->secstrings, info->mod);
+       if (err < 0)
+               return ERR_PTR(err);
        /* We will do a special allocation for per-cpu sections later. */
        info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
  
This page took 0.069417 seconds and 4 git commands to generate.