Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 348930
b: refs/heads/master
c: 1fb9341
h: refs/heads/master
v: v3
  • Loading branch information
Rusty Russell committed Jan 12, 2013
1 parent 34c33a1 commit 1c1113e
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 42 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0d21b0e3477395e7ff2acc269f15df6e6a8d356d
refs/heads/master: 1fb9341ac34825aa40354e74d9a2c69df7d2c304
90 changes: 49 additions & 41 deletions trunk/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -3017,7 +3017,7 @@ static bool finished_loading(const char *name)
bool ret;

mutex_lock(&module_mutex);
mod = find_module(name);
mod = find_module_all(name, true);
ret = !mod || mod->state == MODULE_STATE_LIVE
|| mod->state == MODULE_STATE_GOING;
mutex_unlock(&module_mutex);
Expand Down Expand Up @@ -3141,6 +3141,32 @@ static int load_module(struct load_info *info, const char __user *uargs,
goto free_copy;
}

/*
* We try to place it in the list now to make sure it's unique
* before we dedicate too many resources. In particular,
* temporary percpu memory exhaustion.
*/
mod->state = MODULE_STATE_UNFORMED;
again:
mutex_lock(&module_mutex);
if ((old = find_module_all(mod->name, true)) != NULL) {
if (old->state == MODULE_STATE_COMING
|| old->state == MODULE_STATE_UNFORMED) {
/* Wait in case it fails to load. */
mutex_unlock(&module_mutex);
err = wait_event_interruptible(module_wq,
finished_loading(mod->name));
if (err)
goto free_module;
goto again;
}
err = -EEXIST;
mutex_unlock(&module_mutex);
goto free_module;
}
list_add_rcu(&mod->list, &modules);
mutex_unlock(&module_mutex);

#ifdef CONFIG_MODULE_SIG
mod->sig_ok = info->sig_ok;
if (!mod->sig_ok)
Expand All @@ -3150,7 +3176,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
/* Now module is in final location, initialize linked lists, etc. */
err = module_unload_init(mod);
if (err)
goto free_module;
goto unlink_mod;

/* Now we've got everything in the final locations, we can
* find optional sections. */
Expand Down Expand Up @@ -3185,54 +3211,33 @@ static int load_module(struct load_info *info, const char __user *uargs,
goto free_arch_cleanup;
}

/* Mark state as coming so strong_try_module_get() ignores us. */
mod->state = MODULE_STATE_COMING;

/* Now sew it into the lists so we can get lockdep and oops
* info during argument parsing. No one should access us, since
* strong_try_module_get() will fail.
* lockdep/oops can run asynchronous, so use the RCU list insertion
* function to insert in a way safe to concurrent readers.
* The mutex protects against concurrent writers.
*/
again:
mutex_lock(&module_mutex);
if ((old = find_module(mod->name)) != NULL) {
if (old->state == MODULE_STATE_COMING) {
/* Wait in case it fails to load. */
mutex_unlock(&module_mutex);
err = wait_event_interruptible(module_wq,
finished_loading(mod->name));
if (err)
goto free_arch_cleanup;
goto again;
}
err = -EEXIST;
goto unlock;
}

/* This has to be done once we're sure module name is unique. */
dynamic_debug_setup(info->debug, info->num_debug);

/* Find duplicate symbols */
mutex_lock(&module_mutex);
/* Find duplicate symbols (must be called under lock). */
err = verify_export_symbols(mod);
if (err < 0)
goto ddebug;
goto ddebug_cleanup;

/* This relies on module_mutex for list integrity. */
module_bug_finalize(info->hdr, info->sechdrs, mod);
list_add_rcu(&mod->list, &modules);

/* Mark state as coming so strong_try_module_get() ignores us,
* but kallsyms etc. can see us. */
mod->state = MODULE_STATE_COMING;

mutex_unlock(&module_mutex);

/* Module is ready to execute: parsing args may do that. */
err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
-32768, 32767, &ddebug_dyndbg_module_param_cb);
if (err < 0)
goto unlink;
goto bug_cleanup;

/* Link in to syfs. */
err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
if (err < 0)
goto unlink;
goto bug_cleanup;

/* Get rid of temporary copy. */
free_copy(info);
Expand All @@ -3242,16 +3247,13 @@ static int load_module(struct load_info *info, const char __user *uargs,

return do_init_module(mod);

unlink:
bug_cleanup:
/* module_bug_cleanup needs module_mutex protection */
mutex_lock(&module_mutex);
/* Unlink carefully: kallsyms could be walking list. */
list_del_rcu(&mod->list);
module_bug_cleanup(mod);
wake_up_all(&module_wq);
ddebug:
dynamic_debug_remove(info->debug);
unlock:
mutex_unlock(&module_mutex);
ddebug_cleanup:
dynamic_debug_remove(info->debug);
synchronize_sched();
kfree(mod->args);
free_arch_cleanup:
Expand All @@ -3260,6 +3262,12 @@ static int load_module(struct load_info *info, const char __user *uargs,
free_modinfo(mod);
free_unload:
module_unload_free(mod);
unlink_mod:
mutex_lock(&module_mutex);
/* Unlink carefully: kallsyms could be walking list. */
list_del_rcu(&mod->list);
wake_up_all(&module_wq);
mutex_unlock(&module_mutex);
free_module:
module_deallocate(mod, info);
free_copy:
Expand Down
1 change: 1 addition & 0 deletions trunk/lib/bug.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static inline unsigned long bug_addr(const struct bug_entry *bug)
}

#ifdef CONFIG_MODULES
/* Updates are protected by module mutex */
static LIST_HEAD(module_bug_list);

static const struct bug_entry *module_find_bug(unsigned long bugaddr)
Expand Down

0 comments on commit 1c1113e

Please sign in to comment.