kmod/core: fix replace race condition

In the replace case, stop calling module_put on a patch module before
we're potentially done with it.

This will also be needed for future module patching if we want to
properly replace a patch module which only patches a future loaded
module (that's a mouthful).

Fixes #165.
This commit is contained in:
Josh Poimboeuf 2014-06-13 12:41:35 -05:00
parent 2ec9a0481d
commit 052806fe43
1 changed files with 16 additions and 7 deletions

View File

@ -707,20 +707,29 @@ int kpatch_register(struct kpatch_module *kpmod, bool replace)
* the ftrace filter, and disable the owning patch module so that it
* can be removed.
*/
if (!ret && replace)
if (!ret && replace) {
struct kpatch_module *kpmod2, *safe;
hash_for_each_rcu(kpatch_func_hash, i, func, node) {
if (func->op != KPATCH_OP_UNPATCH)
continue;
hash_del_rcu(&func->node);
WARN_ON(kpatch_ftrace_remove_func(func->old_addr));
if (func->kpmod->enabled) {
func->kpmod->enabled = false;
pr_notice("unloaded patch module '%s'\n",
func->kpmod->mod->name);
module_put(func->kpmod->mod);
}
}
list_for_each_entry_safe(kpmod2, safe, &kpmod_list, list) {
if (kpmod == kpmod2)
continue;
kpmod2->enabled = false;
pr_notice("unloaded patch module '%s'\n",
kpmod2->mod->name);
module_put(kpmod2->mod);
list_del(&kpmod2->list);
}
}
/* memory barrier between func hash and state write */
smp_wmb();