]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - kernel/module.c
Merge tag 'drm-next-msm-5.8-2020-06-08' of git://anongit.freedesktop.org/drm/drm
[mirror_ubuntu-jammy-kernel.git] / kernel / module.c
index a0f201d2e18480d2af25ccf67a3e1a7374b8cefe..e8a198588f26eec9d13c7ecfd20993098075c760 100644 (file)
@@ -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>
@@ -1943,7 +1946,6 @@ static void mod_sysfs_teardown(struct module *mod)
        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.
@@ -1957,6 +1959,14 @@ static void mod_sysfs_teardown(struct module *mod)
  *
  * 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))
 {
@@ -1966,6 +1976,15 @@ static void frob_text(const struct module_layout *layout,
                   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))
@@ -1997,20 +2016,7 @@ static void frob_writable_data(const struct module_layout *layout,
                   (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;
@@ -2036,19 +2042,29 @@ static void module_enable_nx(const struct module *mod)
        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 */
 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
 /*
@@ -2334,11 +2350,13 @@ static int apply_relocations(struct module *mod, const struct load_info *info)
                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)
@@ -3326,12 +3344,6 @@ static int check_module_license_and_versions(struct module *mod)
 
 static void flush_module_icache(const struct module *mod)
 {
-       mm_segment_t old_fs;
-
-       /* flush the icache in correct context */
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-
        /*
         * Flush the instruction cache, since we've played with text.
         * Do it before processing of module parameters, so the module
@@ -3343,8 +3355,6 @@ static void flush_module_icache(const struct module *mod)
                                   + mod->init_layout.size);
        flush_icache_range((unsigned long)mod->core_layout.base,
                           (unsigned long)mod->core_layout.base + mod->core_layout.size);
-
-       set_fs(old_fs);
 }
 
 int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
@@ -3392,6 +3402,11 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
        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;