Merge branch 'stable-4.11' of git://git.infradead.org/users/pcmoore/audit
[linux-2.6-microblaze.git] / kernel / module.c
index 5432dbe..e2eec4b 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/string.h>
 #include <linux/mutex.h>
 #include <linux/rculist.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/mmu_context.h>
 #include <linux/license.h>
@@ -314,8 +314,11 @@ struct load_info {
        } index;
 };
 
-/* We require a truly strong try_module_get(): 0 means failure due to
-   ongoing or failed initialization etc. */
+/*
+ * We require a truly strong try_module_get(): 0 means success.
+ * Otherwise an error is returned due to ongoing or failed
+ * initialization etc.
+ */
 static inline int strong_try_module_get(struct module *mod)
 {
        BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED);
@@ -331,7 +334,7 @@ static inline void add_taint_module(struct module *mod, unsigned flag,
                                    enum lockdep_ok lockdep_ok)
 {
        add_taint(flag, lockdep_ok);
-       mod->taints |= (1U << flag);
+       set_bit(flag, &mod->taints);
 }
 
 /*
@@ -387,16 +390,16 @@ extern const struct kernel_symbol __start___ksymtab_gpl[];
 extern const struct kernel_symbol __stop___ksymtab_gpl[];
 extern const struct kernel_symbol __start___ksymtab_gpl_future[];
 extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
-extern const unsigned long __start___kcrctab[];
-extern const unsigned long __start___kcrctab_gpl[];
-extern const unsigned long __start___kcrctab_gpl_future[];
+extern const s32 __start___kcrctab[];
+extern const s32 __start___kcrctab_gpl[];
+extern const s32 __start___kcrctab_gpl_future[];
 #ifdef CONFIG_UNUSED_SYMBOLS
 extern const struct kernel_symbol __start___ksymtab_unused[];
 extern const struct kernel_symbol __stop___ksymtab_unused[];
 extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
 extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
-extern const unsigned long __start___kcrctab_unused[];
-extern const unsigned long __start___kcrctab_unused_gpl[];
+extern const s32 __start___kcrctab_unused[];
+extern const s32 __start___kcrctab_unused_gpl[];
 #endif
 
 #ifndef CONFIG_MODVERSIONS
@@ -495,7 +498,7 @@ struct find_symbol_arg {
 
        /* Output */
        struct module *owner;
-       const unsigned long *crc;
+       const s32 *crc;
        const struct kernel_symbol *sym;
 };
 
@@ -561,7 +564,7 @@ static bool find_symbol_in_section(const struct symsearch *syms,
  * (optional) module which owns it.  Needs preempt disabled or module_mutex. */
 const struct kernel_symbol *find_symbol(const char *name,
                                        struct module **owner,
-                                       const unsigned long **crc,
+                                       const s32 **crc,
                                        bool gplok,
                                        bool warn)
 {
@@ -1139,22 +1142,13 @@ static inline int module_unload_init(struct module *mod)
 static size_t module_flags_taint(struct module *mod, char *buf)
 {
        size_t l = 0;
+       int i;
+
+       for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
+               if (taint_flags[i].module && test_bit(i, &mod->taints))
+                       buf[l++] = taint_flags[i].c_true;
+       }
 
-       if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
-               buf[l++] = 'P';
-       if (mod->taints & (1 << TAINT_OOT_MODULE))
-               buf[l++] = 'O';
-       if (mod->taints & (1 << TAINT_FORCED_MODULE))
-               buf[l++] = 'F';
-       if (mod->taints & (1 << TAINT_CRAP))
-               buf[l++] = 'C';
-       if (mod->taints & (1 << TAINT_UNSIGNED_MODULE))
-               buf[l++] = 'E';
-       /*
-        * TAINT_FORCED_RMMOD: could be added.
-        * TAINT_CPU_OUT_OF_SPEC, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
-        * apply to modules.
-        */
        return l;
 }
 
@@ -1256,23 +1250,17 @@ static int try_to_force_load(struct module *mod, const char *reason)
 }
 
 #ifdef CONFIG_MODVERSIONS
-/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */
-static unsigned long maybe_relocated(unsigned long crc,
-                                    const struct module *crc_owner)
+
+static u32 resolve_rel_crc(const s32 *crc)
 {
-#ifdef ARCH_RELOCATES_KCRCTAB
-       if (crc_owner == NULL)
-               return crc - (unsigned long)reloc_start;
-#endif
-       return crc;
+       return *(u32 *)((void *)crc + *crc);
 }
 
 static int check_version(Elf_Shdr *sechdrs,
                         unsigned int versindex,
                         const char *symname,
                         struct module *mod,
-                        const unsigned long *crc,
-                        const struct module *crc_owner)
+                        const s32 *crc)
 {
        unsigned int i, num_versions;
        struct modversion_info *versions;
@@ -1290,18 +1278,25 @@ static int check_version(Elf_Shdr *sechdrs,
                / sizeof(struct modversion_info);
 
        for (i = 0; i < num_versions; i++) {
+               u32 crcval;
+
                if (strcmp(versions[i].name, symname) != 0)
                        continue;
 
-               if (versions[i].crc == maybe_relocated(*crc, crc_owner))
+               if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
+                       crcval = resolve_rel_crc(crc);
+               else
+                       crcval = *crc;
+               if (versions[i].crc == crcval)
                        return 1;
-               pr_debug("Found checksum %lX vs module %lX\n",
-                      maybe_relocated(*crc, crc_owner), versions[i].crc);
+               pr_debug("Found checksum %X vs module %lX\n",
+                        crcval, versions[i].crc);
                goto bad_version;
        }
 
-       pr_warn("%s: no symbol version for %s\n", mod->name, symname);
-       return 0;
+       /* Broken toolchain. Warn once, then let it go.. */
+       pr_warn_once("%s: no symbol version for %s\n", mod->name, symname);
+       return 1;
 
 bad_version:
        pr_warn("%s: disagrees about version of symbol %s\n",
@@ -1313,7 +1308,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
                                          unsigned int versindex,
                                          struct module *mod)
 {
-       const unsigned long *crc;
+       const s32 *crc;
 
        /*
         * Since this should be found in kernel (which can't be removed), no
@@ -1327,8 +1322,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
        }
        preempt_enable();
        return check_version(sechdrs, versindex,
-                            VMLINUX_SYMBOL_STR(module_layout), mod, crc,
-                            NULL);
+                            VMLINUX_SYMBOL_STR(module_layout), mod, crc);
 }
 
 /* First part is kernel version, which we ignore if module has crcs. */
@@ -1346,8 +1340,7 @@ static inline int check_version(Elf_Shdr *sechdrs,
                                unsigned int versindex,
                                const char *symname,
                                struct module *mod,
-                               const unsigned long *crc,
-                               const struct module *crc_owner)
+                               const s32 *crc)
 {
        return 1;
 }
@@ -1374,7 +1367,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
 {
        struct module *owner;
        const struct kernel_symbol *sym;
-       const unsigned long *crc;
+       const s32 *crc;
        int err;
 
        /*
@@ -1389,8 +1382,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
        if (!sym)
                goto unlock;
 
-       if (!check_version(info->sechdrs, info->index.vers, name, mod, crc,
-                          owner)) {
+       if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) {
                sym = ERR_PTR(-EINVAL);
                goto getname;
        }
@@ -1909,6 +1901,9 @@ static void frob_writable_data(const struct module_layout *layout,
 /* 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);
@@ -1918,6 +1913,9 @@ void module_disable_ro(const struct module *mod)
 
 void module_enable_ro(const struct module *mod, bool after_init)
 {
+       if (!rodata_enabled)
+               return;
+
        frob_text(&mod->core_layout, set_memory_ro);
        frob_rodata(&mod->core_layout, set_memory_ro);
        frob_text(&mod->init_layout, set_memory_ro);
@@ -1950,6 +1948,9 @@ void set_all_modules_text_rw(void)
 {
        struct module *mod;
 
+       if (!rodata_enabled)
+               return;
+
        mutex_lock(&module_mutex);
        list_for_each_entry_rcu(mod, &modules, list) {
                if (mod->state == MODULE_STATE_UNFORMED)
@@ -1966,9 +1967,18 @@ void set_all_modules_text_ro(void)
 {
        struct module *mod;
 
+       if (!rodata_enabled)
+               return;
+
        mutex_lock(&module_mutex);
        list_for_each_entry_rcu(mod, &modules, list) {
-               if (mod->state == MODULE_STATE_UNFORMED)
+               /*
+                * Ignore going modules since it's possible that ro
+                * protection has already been disabled, otherwise we'll
+                * run into protection faults at module deallocation.
+                */
+               if (mod->state == MODULE_STATE_UNFORMED ||
+                       mod->state == MODULE_STATE_GOING)
                        continue;
 
                frob_text(&mod->core_layout, set_memory_ro);
@@ -1979,10 +1989,12 @@ void set_all_modules_text_ro(void)
 
 static void disable_ro_nx(const struct module_layout *layout)
 {
-       frob_text(layout, set_memory_rw);
-       frob_rodata(layout, set_memory_rw);
+       if (rodata_enabled) {
+               frob_text(layout, set_memory_rw);
+               frob_rodata(layout, set_memory_rw);
+               frob_ro_after_init(layout, set_memory_rw);
+       }
        frob_rodata(layout, set_memory_x);
-       frob_ro_after_init(layout, set_memory_rw);
        frob_ro_after_init(layout, set_memory_x);
        frob_writable_data(layout, set_memory_x);
 }
@@ -2793,14 +2805,17 @@ static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned l
 }
 
 #ifdef CONFIG_LIVEPATCH
-static int find_livepatch_modinfo(struct module *mod, struct load_info *info)
+static int check_modinfo_livepatch(struct module *mod, struct load_info *info)
 {
-       mod->klp = get_modinfo(info, "livepatch") ? true : false;
+       if (get_modinfo(info, "livepatch")) {
+               mod->klp = true;
+               add_taint_module(mod, TAINT_LIVEPATCH, LOCKDEP_STILL_OK);
+       }
 
        return 0;
 }
 #else /* !CONFIG_LIVEPATCH */
-static int find_livepatch_modinfo(struct module *mod, struct load_info *info)
+static int check_modinfo_livepatch(struct module *mod, struct load_info *info)
 {
        if (get_modinfo(info, "livepatch")) {
                pr_err("%s: module is marked as livepatch module, but livepatch support is disabled",
@@ -2970,7 +2985,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
                        "is unknown, you have been warned.\n", mod->name);
        }
 
-       err = find_livepatch_modinfo(mod, info);
+       err = check_modinfo_livepatch(mod, info);
        if (err)
                return err;
 
@@ -3706,6 +3721,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
  sysfs_cleanup:
        mod_sysfs_teardown(mod);
  coming_cleanup:
+       mod->state = MODULE_STATE_GOING;
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_GOING, mod);
        klp_module_going(mod);
@@ -4039,6 +4055,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
 }
 #endif /* CONFIG_KALLSYMS */
 
+/* Maximum number of characters written by module_flags() */
+#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
+
+/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
 static char *module_flags(struct module *mod, char *buf)
 {
        int bx = 0;
@@ -4083,7 +4103,7 @@ static void m_stop(struct seq_file *m, void *p)
 static int m_show(struct seq_file *m, void *p)
 {
        struct module *mod = list_entry(p, struct module, list);
-       char buf[8];
+       char buf[MODULE_FLAGS_BUF_SIZE];
 
        /* We always ignore unformed modules. */
        if (mod->state == MODULE_STATE_UNFORMED)
@@ -4254,7 +4274,7 @@ EXPORT_SYMBOL_GPL(__module_text_address);
 void print_modules(void)
 {
        struct module *mod;
-       char buf[8];
+       char buf[MODULE_FLAGS_BUF_SIZE];
 
        printk(KERN_DEFAULT "Modules linked in:");
        /* Most callers should already have preempt disabled, but make sure */