summaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c255
1 files changed, 41 insertions, 214 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 77764f22f021..ddfe45ac2fd1 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -39,6 +39,7 @@
#include <linux/device.h>
#include <linux/string.h>
#include <linux/sched.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
@@ -60,18 +61,18 @@
static DEFINE_SPINLOCK(modlist_lock);
/* List of modules, protected by module_mutex AND modlist_lock */
-static DECLARE_MUTEX(module_mutex);
+static DEFINE_MUTEX(module_mutex);
static LIST_HEAD(modules);
-static DECLARE_MUTEX(notify_mutex);
+static DEFINE_MUTEX(notify_mutex);
static struct notifier_block * module_notify_list;
int register_module_notifier(struct notifier_block * nb)
{
int err;
- down(&notify_mutex);
+ mutex_lock(&notify_mutex);
err = notifier_chain_register(&module_notify_list, nb);
- up(&notify_mutex);
+ mutex_unlock(&notify_mutex);
return err;
}
EXPORT_SYMBOL(register_module_notifier);
@@ -79,9 +80,9 @@ EXPORT_SYMBOL(register_module_notifier);
int unregister_module_notifier(struct notifier_block * nb)
{
int err;
- down(&notify_mutex);
+ mutex_lock(&notify_mutex);
err = notifier_chain_unregister(&module_notify_list, nb);
- up(&notify_mutex);
+ mutex_unlock(&notify_mutex);
return err;
}
EXPORT_SYMBOL(unregister_module_notifier);
@@ -232,24 +233,6 @@ static unsigned long __find_symbol(const char *name,
return 0;
}
-/* Find a symbol in this elf symbol table */
-static unsigned long find_local_symbol(Elf_Shdr *sechdrs,
- unsigned int symindex,
- const char *strtab,
- const char *name)
-{
- unsigned int i;
- Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
-
- /* Search (defined) internal symbols first. */
- for (i = 1; i < sechdrs[symindex].sh_size/sizeof(*sym); i++) {
- if (sym[i].st_shndx != SHN_UNDEF
- && strcmp(name, strtab + sym[i].st_name) == 0)
- return sym[i].st_value;
- }
- return 0;
-}
-
/* Search for module by name: must hold module_mutex. */
static struct module *find_module(const char *name)
{
@@ -601,7 +584,7 @@ static void free_module(struct module *mod);
static void wait_for_zero_refcount(struct module *mod)
{
/* Since we might sleep for some time, drop the semaphore first */
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
for (;;) {
DEBUGP("Looking at refcount...\n");
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -610,7 +593,7 @@ static void wait_for_zero_refcount(struct module *mod)
schedule();
}
current->state = TASK_RUNNING;
- down(&module_mutex);
+ mutex_lock(&module_mutex);
}
asmlinkage long
@@ -627,7 +610,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
return -EFAULT;
name[MODULE_NAME_LEN-1] = '\0';
- if (down_interruptible(&module_mutex) != 0)
+ if (mutex_lock_interruptible(&module_mutex) != 0)
return -EINTR;
mod = find_module(name);
@@ -676,14 +659,14 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
/* Final destruction now noone is using it. */
if (mod->exit != NULL) {
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
mod->exit();
- down(&module_mutex);
+ mutex_lock(&module_mutex);
}
free_module(mod);
out:
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
return ret;
}
@@ -784,139 +767,6 @@ static struct module_attribute *modinfo_attrs[] = {
NULL,
};
-#ifdef CONFIG_OBSOLETE_MODPARM
-/* Bounds checking done below */
-static int obsparm_copy_string(const char *val, struct kernel_param *kp)
-{
- strcpy(kp->arg, val);
- return 0;
-}
-
-static int set_obsolete(const char *val, struct kernel_param *kp)
-{
- unsigned int min, max;
- unsigned int size, maxsize;
- int dummy;
- char *endp;
- const char *p;
- struct obsolete_modparm *obsparm = kp->arg;
-
- if (!val) {
- printk(KERN_ERR "Parameter %s needs an argument\n", kp->name);
- return -EINVAL;
- }
-
- /* type is: [min[-max]]{b,h,i,l,s} */
- p = obsparm->type;
- min = simple_strtol(p, &endp, 10);
- if (endp == obsparm->type)
- min = max = 1;
- else if (*endp == '-') {
- p = endp+1;
- max = simple_strtol(p, &endp, 10);
- } else
- max = min;
- switch (*endp) {
- case 'b':
- return param_array(kp->name, val, min, max, obsparm->addr,
- 1, param_set_byte, &dummy);
- case 'h':
- return param_array(kp->name, val, min, max, obsparm->addr,
- sizeof(short), param_set_short, &dummy);
- case 'i':
- return param_array(kp->name, val, min, max, obsparm->addr,
- sizeof(int), param_set_int, &dummy);
- case 'l':
- return param_array(kp->name, val, min, max, obsparm->addr,
- sizeof(long), param_set_long, &dummy);
- case 's':
- return param_array(kp->name, val, min, max, obsparm->addr,
- sizeof(char *), param_set_charp, &dummy);
-
- case 'c':
- /* Undocumented: 1-5c50 means 1-5 strings of up to 49 chars,
- and the decl is "char xxx[5][50];" */
- p = endp+1;
- maxsize = simple_strtol(p, &endp, 10);
- /* We check lengths here (yes, this is a hack). */
- p = val;
- while (p[size = strcspn(p, ",")]) {
- if (size >= maxsize)
- goto oversize;
- p += size+1;
- }
- if (size >= maxsize)
- goto oversize;
- return param_array(kp->name, val, min, max, obsparm->addr,
- maxsize, obsparm_copy_string, &dummy);
- }
- printk(KERN_ERR "Unknown obsolete parameter type %s\n", obsparm->type);
- return -EINVAL;
- oversize:
- printk(KERN_ERR
- "Parameter %s doesn't fit in %u chars.\n", kp->name, maxsize);
- return -EINVAL;
-}
-
-static int obsolete_params(const char *name,
- char *args,
- struct obsolete_modparm obsparm[],
- unsigned int num,
- Elf_Shdr *sechdrs,
- unsigned int symindex,
- const char *strtab)
-{
- struct kernel_param *kp;
- unsigned int i;
- int ret;
-
- kp = kmalloc(sizeof(kp[0]) * num, GFP_KERNEL);
- if (!kp)
- return -ENOMEM;
-
- for (i = 0; i < num; i++) {
- char sym_name[128 + sizeof(MODULE_SYMBOL_PREFIX)];
-
- snprintf(sym_name, sizeof(sym_name), "%s%s",
- MODULE_SYMBOL_PREFIX, obsparm[i].name);
-
- kp[i].name = obsparm[i].name;
- kp[i].perm = 000;
- kp[i].set = set_obsolete;
- kp[i].get = NULL;
- obsparm[i].addr
- = (void *)find_local_symbol(sechdrs, symindex, strtab,
- sym_name);
- if (!obsparm[i].addr) {
- printk("%s: falsely claims to have parameter %s\n",
- name, obsparm[i].name);
- ret = -EINVAL;
- goto out;
- }
- kp[i].arg = &obsparm[i];
- }
-
- ret = parse_args(name, args, kp, num, NULL);
- out:
- kfree(kp);
- return ret;
-}
-#else
-static int obsolete_params(const char *name,
- char *args,
- struct obsolete_modparm obsparm[],
- unsigned int num,
- Elf_Shdr *sechdrs,
- unsigned int symindex,
- const char *strtab)
-{
- if (num != 0)
- printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
- name);
- return 0;
-}
-#endif /* CONFIG_OBSOLETE_MODPARM */
-
static const char vermagic[] = VERMAGIC_STRING;
#ifdef CONFIG_MODVERSIONS
@@ -1571,7 +1421,6 @@ static struct module *load_module(void __user *umod,
exportindex, modindex, obsparmindex, infoindex, gplindex,
crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex,
gplfuturecrcindex;
- long arglen;
struct module *mod;
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1690,23 +1539,11 @@ static struct module *load_module(void __user *umod,
}
/* Now copy in args */
- arglen = strlen_user(uargs);
- if (!arglen) {
- err = -EFAULT;
- goto free_hdr;
- }
- args = kmalloc(arglen, GFP_KERNEL);
- if (!args) {
- err = -ENOMEM;
+ args = strndup_user(uargs, ~0UL >> 1);
+ if (IS_ERR(args)) {
+ err = PTR_ERR(args);
goto free_hdr;
}
- if (copy_from_user(args, uargs, arglen) != 0) {
- err = -EFAULT;
- goto free_mod;
- }
-
- /* Userspace could have altered the string after the strlen_user() */
- args[arglen - 1] = '\0';
if (find_module(mod->name)) {
err = -EEXIST;
@@ -1886,27 +1723,17 @@ static struct module *load_module(void __user *umod,
set_fs(old_fs);
mod->args = args;
- if (obsparmindex) {
- err = obsolete_params(mod->name, mod->args,
- (struct obsolete_modparm *)
- sechdrs[obsparmindex].sh_addr,
- sechdrs[obsparmindex].sh_size
- / sizeof(struct obsolete_modparm),
- sechdrs, symindex,
- (char *)sechdrs[strindex].sh_addr);
- if (setupindex)
- printk(KERN_WARNING "%s: Ignoring new-style "
- "parameters in presence of obsolete ones\n",
- mod->name);
- } else {
- /* Size of section 0 is 0, so this works well if no params */
- err = parse_args(mod->name, mod->args,
- (struct kernel_param *)
- sechdrs[setupindex].sh_addr,
- sechdrs[setupindex].sh_size
- / sizeof(struct kernel_param),
- NULL);
- }
+ if (obsparmindex)
+ printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
+ mod->name);
+
+ /* Size of section 0 is 0, so this works well if no params */
+ err = parse_args(mod->name, mod->args,
+ (struct kernel_param *)
+ sechdrs[setupindex].sh_addr,
+ sechdrs[setupindex].sh_size
+ / sizeof(struct kernel_param),
+ NULL);
if (err < 0)
goto arch_cleanup;
@@ -1972,13 +1799,13 @@ sys_init_module(void __user *umod,
return -EPERM;
/* Only one module load at a time, please */
- if (down_interruptible(&module_mutex) != 0)
+ if (mutex_lock_interruptible(&module_mutex) != 0)
return -EINTR;
/* Do all the hard work */
mod = load_module(umod, len, uargs);
if (IS_ERR(mod)) {
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
return PTR_ERR(mod);
}
@@ -1987,11 +1814,11 @@ sys_init_module(void __user *umod,
stop_machine_run(__link_module, mod, NR_CPUS);
/* Drop lock so they can recurse */
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
- down(&notify_mutex);
+ mutex_lock(&notify_mutex);
notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod);
- up(&notify_mutex);
+ mutex_unlock(&notify_mutex);
/* Start the module */
if (mod->init != NULL)
@@ -2006,15 +1833,15 @@ sys_init_module(void __user *umod,
mod->name);
else {
module_put(mod);
- down(&module_mutex);
+ mutex_lock(&module_mutex);
free_module(mod);
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
}
return ret;
}
/* Now it's a first class citizen! */
- down(&module_mutex);
+ mutex_lock(&module_mutex);
mod->state = MODULE_STATE_LIVE;
/* Drop initial reference. */
module_put(mod);
@@ -2022,7 +1849,7 @@ sys_init_module(void __user *umod,
mod->module_init = NULL;
mod->init_size = 0;
mod->init_text_size = 0;
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
return 0;
}
@@ -2112,7 +1939,7 @@ struct module *module_get_kallsym(unsigned int symnum,
{
struct module *mod;
- down(&module_mutex);
+ mutex_lock(&module_mutex);
list_for_each_entry(mod, &modules, list) {
if (symnum < mod->num_symtab) {
*value = mod->symtab[symnum].st_value;
@@ -2120,12 +1947,12 @@ struct module *module_get_kallsym(unsigned int symnum,
strncpy(namebuf,
mod->strtab + mod->symtab[symnum].st_name,
127);
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
return mod;
}
symnum -= mod->num_symtab;
}
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
return NULL;
}
@@ -2168,7 +1995,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
struct list_head *i;
loff_t n = 0;
- down(&module_mutex);
+ mutex_lock(&module_mutex);
list_for_each(i, &modules) {
if (n++ == *pos)
break;
@@ -2189,7 +2016,7 @@ static void *m_next(struct seq_file *m, void *p, loff_t *pos)
static void m_stop(struct seq_file *m, void *p)
{
- up(&module_mutex);
+ mutex_unlock(&module_mutex);
}
static int m_show(struct seq_file *m, void *p)
OpenPOWER on IntegriCloud