summaryrefslogtreecommitdiff
path: root/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 36023bce008f..a80e9596cd03 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -554,8 +554,8 @@ sys_init_module(const char *name_user, struct module *mod_user)
put_mod_name(name);
/* Initialize the module. */
- mod->flags |= MOD_INITIALIZING;
atomic_set(&mod->uc.usecount,1);
+ mod->flags |= MOD_INITIALIZING;
if (mod->init && (error = mod->init()) != 0) {
atomic_set(&mod->uc.usecount,0);
mod->flags &= ~MOD_INITIALIZING;
@@ -613,11 +613,6 @@ sys_delete_module(const char *name_user)
if (name_user) {
if ((error = get_mod_name(name_user, &name)) < 0)
goto out;
- if (error == 0) {
- error = -EINVAL;
- put_mod_name(name);
- goto out;
- }
error = -ENOENT;
if ((mod = find_module(name)) == NULL) {
put_mod_name(name);
@@ -847,7 +842,6 @@ qm_symbols(struct module *mod, char *buf, size_t bufsize, size_t *ret)
bufsize -= len;
space += len;
}
-
if (put_user(i, ret))
return -EFAULT;
else
@@ -876,8 +870,11 @@ qm_info(struct module *mod, char *buf, size_t bufsize, size_t *ret)
info.addr = (unsigned long)mod;
info.size = mod->size;
info.flags = mod->flags;
+
+ /* usecount is one too high here - report appropriately to
+ compensate for locking */
info.usecount = (mod_member_present(mod, can_unload)
- && mod->can_unload ? -1 : atomic_read(&mod->uc.usecount));
+ && mod->can_unload ? -1 : atomic_read(&mod->uc.usecount)-1);
if (copy_to_user(buf, &info, sizeof(struct module_info)))
return -EFAULT;
@@ -909,15 +906,17 @@ sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
goto out;
}
err = -ENOENT;
- if (namelen == 0)
- mod = &kernel_module;
- else if ((mod = find_module(name)) == NULL) {
+ if ((mod = find_module(name)) == NULL) {
put_mod_name(name);
goto out;
}
put_mod_name(name);
}
+ /* __MOD_ touches the flags. We must avoid that */
+
+ atomic_inc(&mod->uc.usecount);
+
switch (which)
{
case 0:
@@ -942,6 +941,8 @@ sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
err = -EINVAL;
break;
}
+ atomic_dec(&mod->uc.usecount);
+
out:
unlock_kernel();
return err;