module: allow ndiswrapper to use GPL-only symbols
[sfrench/cifs-2.6.git] / kernel / module.c
index 1bb4c5e0d56e330b1de92b5e20fddbd446e9d314..be4807fb90e48afd4ec74c460aaf8a214c4b0a4a 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/semaphore.h>
 #include <asm/cacheflush.h>
 #include <linux/license.h>
+#include <asm/sections.h>
 
 #if 0
 #define DEBUGP printk
@@ -65,6 +66,9 @@
 static DEFINE_MUTEX(module_mutex);
 static LIST_HEAD(modules);
 
+/* Waiting for a module to finish initializing? */
+static DECLARE_WAIT_QUEUE_HEAD(module_wq);
+
 static BLOCKING_NOTIFIER_HEAD(module_notify_list);
 
 int register_module_notifier(struct notifier_block * nb)
@@ -84,8 +88,11 @@ EXPORT_SYMBOL(unregister_module_notifier);
 static inline int strong_try_module_get(struct module *mod)
 {
        if (mod && mod->state == MODULE_STATE_COMING)
+               return -EBUSY;
+       if (try_module_get(mod))
                return 0;
-       return try_module_get(mod);
+       else
+               return -ENOENT;
 }
 
 static inline void add_taint_module(struct module *mod, unsigned flag)
@@ -284,7 +291,7 @@ static unsigned long __find_symbol(const char *name,
                }
        }
        DEBUGP("Failed to find symbol %s\n", name);
-       return 0;
+       return -ENOENT;
 }
 
 /* Search for module by name: must hold module_mutex. */
@@ -337,9 +344,6 @@ static inline unsigned int block_size(int val)
        return val;
 }
 
-/* Created by linker magic */
-extern char __per_cpu_start[], __per_cpu_end[];
-
 static void *percpu_modalloc(unsigned long size, unsigned long align,
                             const char *name)
 {
@@ -424,6 +428,14 @@ static unsigned int find_pcpusec(Elf_Ehdr *hdr,
        return find_sec(hdr, sechdrs, secstrings, ".data.percpu");
 }
 
+static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               memcpy(pcpudest + per_cpu_offset(cpu), from, size);
+}
+
 static int percpu_modinit(void)
 {
        pcpu_num_used = 2;
@@ -539,11 +551,21 @@ static int already_uses(struct module *a, struct module *b)
 static int use_module(struct module *a, struct module *b)
 {
        struct module_use *use;
-       int no_warn;
+       int no_warn, err;
 
        if (b == NULL || already_uses(a, b)) return 1;
 
-       if (!strong_try_module_get(b))
+       /* If we're interrupted or time out, we fail. */
+       if (wait_event_interruptible_timeout(
+                   module_wq, (err = strong_try_module_get(b)) != -EBUSY,
+                   30 * HZ) <= 0) {
+               printk("%s: gave up waiting for init of module %s.\n",
+                      a->name, b->name);
+               return 0;
+       }
+
+       /* If strong_try_module_get() returned a different error, we fail. */
+       if (err)
                return 0;
 
        DEBUGP("Allocating new usage for %s.\n", a->name);
@@ -722,7 +744,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
                mutex_lock(&module_mutex);
        }
        /* Store the name of the last unloaded module for diagnostic purposes */
-       sprintf(last_unloaded_module, mod->name);
+       strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
        free_module(mod);
 
  out:
@@ -759,7 +781,7 @@ void __symbol_put(const char *symbol)
        const unsigned long *crc;
 
        preempt_disable();
-       if (!__find_symbol(symbol, &owner, &crc, 1))
+       if (IS_ERR_VALUE(__find_symbol(symbol, &owner, &crc, 1)))
                BUG();
        module_put(owner);
        preempt_enable();
@@ -816,7 +838,7 @@ static inline void module_unload_free(struct module *mod)
 
 static inline int use_module(struct module *a, struct module *b)
 {
-       return strong_try_module_get(b);
+       return strong_try_module_get(b) == 0;
 }
 
 static inline void module_unload_init(struct module *mod)
@@ -905,7 +927,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
        const unsigned long *crc;
        struct module *owner;
 
-       if (!__find_symbol("struct_module", &owner, &crc, 1))
+       if (IS_ERR_VALUE(__find_symbol("struct_module",
+                                               &owner, &crc, 1)))
                BUG();
        return check_version(sechdrs, versindex, "struct_module", mod,
                             crc);
@@ -954,22 +977,21 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
 
        ret = __find_symbol(name, &owner, &crc,
                        !(mod->taints & TAINT_PROPRIETARY_MODULE));
-       if (ret) {
+       if (!IS_ERR_VALUE(ret)) {
                /* use_module can fail due to OOM,
                   or module initialization or unloading */
                if (!check_version(sechdrs, versindex, name, mod, crc) ||
                    !use_module(mod, owner))
-                       ret = 0;
+                       ret = -EINVAL;
        }
        return ret;
 }
 
-
 /*
  * /sys/module/foo/sections stuff
  * J. Corbet <corbet@lwn.net>
  */
-#ifdef CONFIG_KALLSYMS
+#if defined(CONFIG_KALLSYMS) && defined(CONFIG_SYSFS)
 static ssize_t module_sect_show(struct module_attribute *mattr,
                                struct module *mod, char *buf)
 {
@@ -1165,7 +1187,7 @@ static inline void add_notes_attrs(struct module *mod, unsigned int nsect,
 static inline void remove_notes_attrs(struct module *mod)
 {
 }
-#endif /* CONFIG_KALLSYMS */
+#endif
 
 #ifdef CONFIG_SYSFS
 int module_add_modinfo_attrs(struct module *mod)
@@ -1208,12 +1230,11 @@ void module_remove_modinfo_attrs(struct module *mod)
        }
        kfree(mod->modinfo_attrs);
 }
-#endif
 
-#ifdef CONFIG_SYSFS
 int mod_sysfs_init(struct module *mod)
 {
        int err;
+       struct kobject *kobj;
 
        if (!module_sysfs_initialized) {
                printk(KERN_ERR "%s: module sysfs not initialized\n",
@@ -1221,6 +1242,15 @@ int mod_sysfs_init(struct module *mod)
                err = -EINVAL;
                goto out;
        }
+
+       kobj = kset_find_obj(module_kset, mod->name);
+       if (kobj) {
+               printk(KERN_ERR "%s: module is already loaded\n", mod->name);
+               kobject_put(kobj);
+               err = -EINVAL;
+               goto out;
+       }
+
        mod->mkobj.mod = mod;
 
        memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj));
@@ -1277,6 +1307,17 @@ static void mod_kobject_remove(struct module *mod)
        kobject_put(&mod->mkobj.kobj);
 }
 
+/*
+ * link the module with the whole machine is stopped with interrupts off
+ * - this defends against kallsyms not taking locks
+ */
+static int __link_module(void *_mod)
+{
+       struct module *mod = _mod;
+       list_add(&mod->list, &modules);
+       return 0;
+}
+
 /*
  * unlink the module with the whole machine is stopped with interrupts off
  * - this defends against kallsyms not taking locks
@@ -1326,7 +1367,9 @@ void *__symbol_get(const char *symbol)
 
        preempt_disable();
        value = __find_symbol(symbol, &owner, &crc, 1);
-       if (value && !strong_try_module_get(owner))
+       if (IS_ERR_VALUE(value))
+               value = 0;
+       else if (strong_try_module_get(owner))
                value = 0;
        preempt_enable();
 
@@ -1346,14 +1389,16 @@ static int verify_export_symbols(struct module *mod)
        const unsigned long *crc;
 
        for (i = 0; i < mod->num_syms; i++)
-               if (__find_symbol(mod->syms[i].name, &owner, &crc, 1)) {
+               if (!IS_ERR_VALUE(__find_symbol(mod->syms[i].name,
+                                                       &owner, &crc, 1))) {
                        name = mod->syms[i].name;
                        ret = -ENOEXEC;
                        goto dup;
                }
 
        for (i = 0; i < mod->num_gpl_syms; i++)
-               if (__find_symbol(mod->gpl_syms[i].name, &owner, &crc, 1)) {
+               if (!IS_ERR_VALUE(__find_symbol(mod->gpl_syms[i].name,
+                                                       &owner, &crc, 1))) {
                        name = mod->gpl_syms[i].name;
                        ret = -ENOEXEC;
                        goto dup;
@@ -1403,7 +1448,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
                                           strtab + sym[i].st_name, mod);
 
                        /* Ok if resolved.  */
-                       if (sym[i].st_value != 0)
+                       if (!IS_ERR_VALUE(sym[i].st_value))
                                break;
                        /* Ok if weak.  */
                        if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
@@ -1888,8 +1933,15 @@ static struct module *load_module(void __user *umod,
        /* Set up license info based on the info section */
        set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
 
+       /*
+        * ndiswrapper is under GPL by itself, but loads proprietary modules.
+        * Don't use add_taint_module(), as it would prevent ndiswrapper from
+        * using GPL-only symbols it needs.
+        */
        if (strcmp(mod->name, "ndiswrapper") == 0)
                add_taint(TAINT_PROPRIETARY_MODULE);
+
+       /* driverloader was caught wrongly pretending to be under GPL */
        if (strcmp(mod->name, "driverloader") == 0)
                add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
 
@@ -1990,7 +2042,7 @@ static struct module *load_module(void __user *umod,
 #ifdef CONFIG_MARKERS
        if (!mod->taints)
                marker_update_probe_range(mod->markers,
-                       mod->markers + mod->num_markers, NULL, NULL);
+                       mod->markers + mod->num_markers);
 #endif
        err = module_finalize(hdr, sechdrs, mod);
        if (err < 0)
@@ -2019,6 +2071,11 @@ static struct module *load_module(void __user *umod,
                printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
                       mod->name);
 
+       /* Now sew it into the lists so we can get lockdep and oops
+         * info during argument parsing.  Noone should access us, since
+         * strong_try_module_get() will fail. */
+       stop_machine_run(__link_module, mod, NR_CPUS);
+
        /* Size of section 0 is 0, so this works well if no params */
        err = parse_args(mod->name, mod->args,
                         (struct kernel_param *)
@@ -2027,7 +2084,7 @@ static struct module *load_module(void __user *umod,
                         / sizeof(struct kernel_param),
                         NULL);
        if (err < 0)
-               goto arch_cleanup;
+               goto unlink;
 
        err = mod_sysfs_setup(mod,
                              (struct kernel_param *)
@@ -2035,7 +2092,7 @@ static struct module *load_module(void __user *umod,
                              sechdrs[setupindex].sh_size
                              / sizeof(struct kernel_param));
        if (err < 0)
-               goto arch_cleanup;
+               goto unlink;
        add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
        add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
 
@@ -2050,7 +2107,8 @@ static struct module *load_module(void __user *umod,
        /* Done! */
        return mod;
 
- arch_cleanup:
+ unlink:
+       stop_machine_run(__unlink_module, mod, NR_CPUS);
        module_arch_cleanup(mod);
  cleanup:
        kobject_del(&mod->mkobj.kobj);
@@ -2075,17 +2133,6 @@ static struct module *load_module(void __user *umod,
        goto free_hdr;
 }
 
-/*
- * link the module with the whole machine is stopped with interrupts off
- * - this defends against kallsyms not taking locks
- */
-static int __link_module(void *_mod)
-{
-       struct module *mod = _mod;
-       list_add(&mod->list, &modules);
-       return 0;
-}
-
 /* This is where the real work happens */
 asmlinkage long
 sys_init_module(void __user *umod,
@@ -2110,10 +2157,6 @@ sys_init_module(void __user *umod,
                return PTR_ERR(mod);
        }
 
-       /* Now sew it into the lists.  They won't access us, since
-           strong_try_module_get() will fail. */
-       stop_machine_run(__link_module, mod, NR_CPUS);
-
        /* Drop lock so they can recurse */
        mutex_unlock(&module_mutex);
 
@@ -2132,6 +2175,7 @@ sys_init_module(void __user *umod,
                mutex_lock(&module_mutex);
                free_module(mod);
                mutex_unlock(&module_mutex);
+               wake_up(&module_wq);
                return ret;
        }
 
@@ -2146,6 +2190,7 @@ sys_init_module(void __user *umod,
        mod->init_size = 0;
        mod->init_text_size = 0;
        mutex_unlock(&module_mutex);
+       wake_up(&module_wq);
 
        return 0;
 }
@@ -2210,14 +2255,13 @@ static const char *get_ksymbol(struct module *mod,
        return mod->strtab + mod->symtab[best].st_name;
 }
 
-/* For kallsyms to ask for address resolution.  NULL means not found.
-   We don't lock, as this is used for oops resolution and races are a
-   lesser concern. */
-/* FIXME: Risky: returns a pointer into a module w/o lock */
+/* For kallsyms to ask for address resolution.  NULL means not found.  Careful
+ * not to lock to avoid deadlock on oopses, simply disable preemption. */
 const char *module_address_lookup(unsigned long addr,
-                                 unsigned long *size,
-                                 unsigned long *offset,
-                                 char **modname)
+                           unsigned long *size,
+                           unsigned long *offset,
+                           char **modname,
+                           char *namebuf)
 {
        struct module *mod;
        const char *ret = NULL;
@@ -2232,6 +2276,11 @@ const char *module_address_lookup(unsigned long addr,
                        break;
                }
        }
+       /* Make a copy in here where it's safe */
+       if (ret) {
+               strncpy(namebuf, ret, KSYM_NAME_LEN - 1);
+               ret = namebuf;
+       }
        preempt_enable();
        return ret;
 }
@@ -2519,7 +2568,7 @@ EXPORT_SYMBOL(struct_module);
 #endif
 
 #ifdef CONFIG_MARKERS
-void module_update_markers(struct module *probe_module, int *refcount)
+void module_update_markers(void)
 {
        struct module *mod;
 
@@ -2527,8 +2576,7 @@ void module_update_markers(struct module *probe_module, int *refcount)
        list_for_each_entry(mod, &modules, list)
                if (!mod->taints)
                        marker_update_probe_range(mod->markers,
-                               mod->markers + mod->num_markers,
-                               probe_module, refcount);
+                               mod->markers + mod->num_markers);
        mutex_unlock(&module_mutex);
 }
 #endif