mirror of https://github.com/dynup/kpatch
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:
parent
2ec9a0481d
commit
052806fe43
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue