ACPI: ibm_acpi: Update documentation for brightness and volume.
[sfrench/cifs-2.6.git] / kernel / module.c
index 05625d5dc7583ac5567d3deec22ebd95c57b72bc..67009bd56c522b634d35a9b8c2852228b4b29730 100644 (file)
@@ -87,6 +87,12 @@ static inline int strong_try_module_get(struct module *mod)
        return try_module_get(mod);
 }
 
+static inline void add_taint_module(struct module *mod, unsigned flag)
+{
+       add_taint(flag);
+       mod->taints |= flag;
+}
+
 /* A thread that wants to hold a reference to a module only while it
  * is running can call ths to safely exit.
  * nfsd and lockd use this.
@@ -847,11 +853,10 @@ static int check_version(Elf_Shdr *sechdrs,
                return 0;
        }
        /* Not in module's version table.  OK, but that taints the kernel. */
-       if (!(tainted & TAINT_FORCED_MODULE)) {
+       if (!(tainted & TAINT_FORCED_MODULE))
                printk("%s: no version for \"%s\" found: kernel tainted.\n",
                       mod->name, symname);
-               add_taint(TAINT_FORCED_MODULE);
-       }
+       add_taint_module(mod, TAINT_FORCED_MODULE);
        return 1;
 }
 
@@ -909,7 +914,8 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
        unsigned long ret;
        const unsigned long *crc;
 
-       ret = __find_symbol(name, &owner, &crc, mod->license_gplok);
+       ret = __find_symbol(name, &owner, &crc,
+                       !(mod->taints & TAINT_PROPRIETARY_MODULE));
        if (ret) {
                /* use_module can fail due to OOM, or module unloading */
                if (!check_version(sechdrs, versindex, name, mod, crc) ||
@@ -1334,11 +1340,11 @@ static void set_license(struct module *mod, const char *license)
        if (!license)
                license = "unspecified";
 
-       mod->license_gplok = license_is_gpl_compatible(license);
-       if (!mod->license_gplok && !(tainted & TAINT_PROPRIETARY_MODULE)) {
-               printk(KERN_WARNING "%s: module license '%s' taints kernel.\n",
-                      mod->name, license);
-               add_taint(TAINT_PROPRIETARY_MODULE);
+       if (!license_is_gpl_compatible(license)) {
+               if (!(tainted & TAINT_PROPRIETARY_MODULE))
+                       printk(KERN_WARNING "%s: module license '%s' taints"
+                               "kernel.\n", mod->name, license);
+               add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
        }
 }
 
@@ -1617,7 +1623,7 @@ static struct module *load_module(void __user *umod,
        modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
        /* This is allowed: modprobe --force will invalidate it. */
        if (!modmagic) {
-               add_taint(TAINT_FORCED_MODULE);
+               add_taint_module(mod, TAINT_FORCED_MODULE);
                printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
                       mod->name);
        } else if (!same_magic(modmagic, vermagic)) {
@@ -1712,9 +1718,9 @@ static struct module *load_module(void __user *umod,
        set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
 
        if (strcmp(mod->name, "ndiswrapper") == 0)
-               add_taint(TAINT_PROPRIETARY_MODULE);
+               add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
        if (strcmp(mod->name, "driverloader") == 0)
-               add_taint(TAINT_PROPRIETARY_MODULE);
+               add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
 
        /* Set up MODINFO_ATTR fields */
        setup_modinfo(mod, sechdrs, infoindex);
@@ -1759,7 +1765,7 @@ static struct module *load_module(void __user *umod,
            (mod->num_unused_gpl_syms && !unusedgplcrcindex)) {
                printk(KERN_WARNING "%s: No versions for exported symbols."
                       " Tainting kernel.\n", mod->name);
-               add_taint(TAINT_FORCED_MODULE);
+               add_taint_module(mod, TAINT_FORCED_MODULE);
        }
 #endif
 
@@ -2032,7 +2038,8 @@ const char *module_address_lookup(unsigned long addr,
        list_for_each_entry(mod, &modules, list) {
                if (within(addr, mod->module_init, mod->init_size)
                    || within(addr, mod->module_core, mod->core_size)) {
-                       *modname = mod->name;
+                       if (modname)
+                               *modname = mod->name;
                        return get_ksymbol(mod, addr, size, offset);
                }
        }
@@ -2123,9 +2130,33 @@ static void m_stop(struct seq_file *m, void *p)
        mutex_unlock(&module_mutex);
 }
 
+static char *taint_flags(unsigned int taints, char *buf)
+{
+       int bx = 0;
+
+       if (taints) {
+               buf[bx++] = '(';
+               if (taints & TAINT_PROPRIETARY_MODULE)
+                       buf[bx++] = 'P';
+               if (taints & TAINT_FORCED_MODULE)
+                       buf[bx++] = 'F';
+               /*
+                * TAINT_FORCED_RMMOD: could be added.
+                * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
+                * apply to modules.
+                */
+               buf[bx++] = ')';
+       }
+       buf[bx] = '\0';
+
+       return buf;
+}
+
 static int m_show(struct seq_file *m, void *p)
 {
        struct module *mod = list_entry(p, struct module, list);
+       char buf[8];
+
        seq_printf(m, "%s %lu",
                   mod->name, mod->init_size + mod->core_size);
        print_unload_info(m, mod);
@@ -2138,6 +2169,10 @@ static int m_show(struct seq_file *m, void *p)
        /* Used by oprofile and other similar tools. */
        seq_printf(m, " 0x%p", mod->module_core);
 
+       /* Taints info */
+       if (mod->taints)
+               seq_printf(m, " %s", taint_flags(mod->taints, buf));
+
        seq_printf(m, "\n");
        return 0;
 }
@@ -2230,10 +2265,11 @@ struct module *module_text_address(unsigned long addr)
 void print_modules(void)
 {
        struct module *mod;
+       char buf[8];
 
        printk("Modules linked in:");
        list_for_each_entry(mod, &modules, list)
-               printk(" %s", mod->name);
+               printk(" %s%s", mod->name, taint_flags(mod->taints, buf));
        printk("\n");
 }