git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
tun: Fix minor race in TUNSETLINK ioctl handling.
[safe/jmp/linux-2.6]
/
kernel
/
module.c
diff --git
a/kernel/module.c
b/kernel/module.c
index
e814cd7
..
5d437bf
100644
(file)
--- a/
kernel/module.c
+++ b/
kernel/module.c
@@
-46,6
+46,7
@@
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
#include <linux/license.h>
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
#include <linux/license.h>
+#include <asm/sections.h>
#if 0
#define DEBUGP printk
#if 0
#define DEBUGP printk
@@
-290,7
+291,7
@@
static unsigned long __find_symbol(const char *name,
}
}
DEBUGP("Failed to find symbol %s\n", name);
}
}
DEBUGP("Failed to find symbol %s\n", name);
- return
0
;
+ return
-ENOENT
;
}
/* Search for module by name: must hold module_mutex. */
}
/* Search for module by name: must hold module_mutex. */
@@
-343,9
+344,6
@@
static inline unsigned int block_size(int val)
return 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)
{
static void *percpu_modalloc(unsigned long size, unsigned long align,
const char *name)
{
@@
-430,6
+428,14
@@
static unsigned int find_pcpusec(Elf_Ehdr *hdr,
return find_sec(hdr, sechdrs, secstrings, ".data.percpu");
}
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;
static int percpu_modinit(void)
{
pcpu_num_used = 2;
@@
-775,7
+781,7
@@
void __symbol_put(const char *symbol)
const unsigned long *crc;
preempt_disable();
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();
BUG();
module_put(owner);
preempt_enable();
@@
-921,7
+927,8
@@
static inline int check_modstruct_version(Elf_Shdr *sechdrs,
const unsigned long *crc;
struct module *owner;
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);
BUG();
return check_version(sechdrs, versindex, "struct_module", mod,
crc);
@@
-970,22
+977,21
@@
static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
ret = __find_symbol(name, &owner, &crc,
!(mod->taints & TAINT_PROPRIETARY_MODULE));
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))
/* 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;
}
}
return ret;
}
-
/*
* /sys/module/foo/sections stuff
* J. Corbet <corbet@lwn.net>
*/
/*
* /sys/module/foo/sections stuff
* J. Corbet <corbet@lwn.net>
*/
-#if
def CONFIG_KALLSYMS
+#if
defined(CONFIG_KALLSYMS) && defined(CONFIG_SYSFS)
static ssize_t module_sect_show(struct module_attribute *mattr,
struct module *mod, char *buf)
{
static ssize_t module_sect_show(struct module_attribute *mattr,
struct module *mod, char *buf)
{
@@
-1181,7
+1187,7
@@
static inline void add_notes_attrs(struct module *mod, unsigned int nsect,
static inline void remove_notes_attrs(struct module *mod)
{
}
static inline void remove_notes_attrs(struct module *mod)
{
}
-#endif
/* CONFIG_KALLSYMS */
+#endif
#ifdef CONFIG_SYSFS
int module_add_modinfo_attrs(struct module *mod)
#ifdef CONFIG_SYSFS
int module_add_modinfo_attrs(struct module *mod)
@@
-1224,12
+1230,11
@@
void module_remove_modinfo_attrs(struct module *mod)
}
kfree(mod->modinfo_attrs);
}
}
kfree(mod->modinfo_attrs);
}
-#endif
-#ifdef CONFIG_SYSFS
int mod_sysfs_init(struct module *mod)
{
int err;
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",
if (!module_sysfs_initialized) {
printk(KERN_ERR "%s: module sysfs not initialized\n",
@@
-1237,6
+1242,15
@@
int mod_sysfs_init(struct module *mod)
err = -EINVAL;
goto out;
}
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));
mod->mkobj.mod = mod;
memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj));
@@
-1353,7
+1367,9
@@
void *__symbol_get(const char *symbol)
preempt_disable();
value = __find_symbol(symbol, &owner, &crc, 1);
preempt_disable();
value = __find_symbol(symbol, &owner, &crc, 1);
- if (value && strong_try_module_get(owner) != 0)
+ if (IS_ERR_VALUE(value))
+ value = 0;
+ else if (strong_try_module_get(owner))
value = 0;
preempt_enable();
value = 0;
preempt_enable();
@@
-1373,14
+1389,16
@@
static int verify_export_symbols(struct module *mod)
const unsigned long *crc;
for (i = 0; i < mod->num_syms; i++)
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++)
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;
name = mod->gpl_syms[i].name;
ret = -ENOEXEC;
goto dup;
@@
-1430,7
+1448,7
@@
static int simplify_symbols(Elf_Shdr *sechdrs,
strtab + sym[i].st_name, mod);
/* Ok if resolved. */
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)
break;
/* Ok if weak. */
if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
@@
-1915,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"));
/* 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);
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);
if (strcmp(mod->name, "driverloader") == 0)
add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
@@
-2017,7
+2042,7
@@
static struct module *load_module(void __user *umod,
#ifdef CONFIG_MARKERS
if (!mod->taints)
marker_update_probe_range(mod->markers,
#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)
#endif
err = module_finalize(hdr, sechdrs, mod);
if (err < 0)
@@
-2153,10
+2178,20
@@
sys_init_module(void __user *umod,
wake_up(&module_wq);
return ret;
}
wake_up(&module_wq);
return ret;
}
+ if (ret > 0) {
+ printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, "
+ "it should follow 0/-E convention\n"
+ KERN_WARNING "%s: loading module anyway...\n",
+ __func__, mod->name, ret,
+ __func__);
+ dump_stack();
+ }
- /* Now it's a first class citizen! */
- mutex_lock(&module_mutex);
+ /* Now it's a first class citizen! Wake up anyone waiting for it. */
mod->state = MODULE_STATE_LIVE;
mod->state = MODULE_STATE_LIVE;
+ wake_up(&module_wq);
+
+ mutex_lock(&module_mutex);
/* Drop initial reference. */
module_put(mod);
unwind_remove_table(mod->unwind_info, 1);
/* Drop initial reference. */
module_put(mod);
unwind_remove_table(mod->unwind_info, 1);
@@
-2165,7
+2200,6
@@
sys_init_module(void __user *umod,
mod->init_size = 0;
mod->init_text_size = 0;
mutex_unlock(&module_mutex);
mod->init_size = 0;
mod->init_text_size = 0;
mutex_unlock(&module_mutex);
- wake_up(&module_wq);
return 0;
}
return 0;
}
@@
-2232,7
+2266,7
@@
static const char *get_ksymbol(struct module *mod,
/* For kallsyms to ask for address resolution. NULL means not found. Careful
* not to lock to avoid deadlock on oopses, simply disable preemption. */
/* For kallsyms to ask for address resolution. NULL means not found. Careful
* not to lock to avoid deadlock on oopses, simply disable preemption. */
-char *module_address_lookup(unsigned long addr,
+c
onst c
har *module_address_lookup(unsigned long addr,
unsigned long *size,
unsigned long *offset,
char **modname,
unsigned long *size,
unsigned long *offset,
char **modname,
@@
-2257,7
+2291,7
@@
char *module_address_lookup(unsigned long addr,
ret = namebuf;
}
preempt_enable();
ret = namebuf;
}
preempt_enable();
- return
(char *)
ret;
+ return ret;
}
int lookup_module_symbol_name(unsigned long addr, char *symname)
}
int lookup_module_symbol_name(unsigned long addr, char *symname)
@@
-2543,7
+2577,7
@@
EXPORT_SYMBOL(struct_module);
#endif
#ifdef CONFIG_MARKERS
#endif
#ifdef CONFIG_MARKERS
-void module_update_markers(
struct module *probe_module, int *refcount
)
+void module_update_markers(
void
)
{
struct module *mod;
{
struct module *mod;
@@
-2551,8
+2585,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,
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
mutex_unlock(&module_mutex);
}
#endif