]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - kernel/module.c
mwifiex: pcie: read FROMDEVICE DMA-able memory with READ_ONCE()
[karo-tx-linux.git] / kernel / module.c
index 0e54d5bf0097f57954d4848db6a830f5a0bc7072..5088784c0cf9e97c166b7dc06afed9d1c7709d2e 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>
@@ -313,8 +313,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);
@@ -330,7 +333,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);
 }
 
 /*
@@ -1138,24 +1141,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].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';
-       if (mod->taints & (1 << TAINT_LIVEPATCH))
-               buf[l++] = 'K';
-       /*
-        * TAINT_FORCED_RMMOD: could be added.
-        * TAINT_CPU_OUT_OF_SPEC, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
-        * apply to modules.
-        */
        return l;
 }
 
@@ -1911,6 +1903,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);
@@ -1920,6 +1915,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);
@@ -1952,6 +1950,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)
@@ -1968,9 +1969,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);
@@ -1981,10 +1991,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);
 }
@@ -3709,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);
@@ -4042,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;
@@ -4086,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)
@@ -4257,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 */