diff --git a/kmod/core/core.c b/kmod/core/core.c index 5c6d965..5c59ce1 100644 --- a/kmod/core/core.c +++ b/kmod/core/core.c @@ -53,8 +53,8 @@ DEFINE_SEMAPHORE(kpatch_mutex); static int kpatch_num_registered; struct kpatch_backtrace_args { - struct kpatch_func *funcs; - int num_funcs, ret; + struct kpatch_module *kpmod; + int ret; }; enum { @@ -88,14 +88,14 @@ void kpatch_backtrace_address_verify(void *data, unsigned long address, int reliable) { struct kpatch_backtrace_args *args = data; - struct kpatch_func *funcs = args->funcs; - int i, num_funcs = args->num_funcs; + struct kpatch_module *kpmod = args->kpmod; + int i; if (args->ret) return; - for (i = 0; i < num_funcs; i++) { - struct kpatch_func *func = &funcs[i]; + for (i = 0; i < kpmod->num_funcs; i++) { + struct kpatch_func *func = &kpmod->funcs[i]; if (address >= func->old_addr && address < func->old_addr + func->old_size) { @@ -124,15 +124,13 @@ struct stacktrace_ops kpatch_backtrace_ops = { * * This function is called from stop_machine() context. */ -static int kpatch_verify_activeness_safety(struct kpatch_func *funcs, - int num_funcs) +static int kpatch_verify_activeness_safety(struct kpatch_module *kpmod) { struct task_struct *g, *t; int ret = 0; struct kpatch_backtrace_args args = { - .funcs = funcs, - .num_funcs = num_funcs, + .kpmod = kpmod, .ret = 0 }; @@ -149,20 +147,15 @@ out: return ret; } -struct kpatch_stop_machine_args { - struct kpatch_func *funcs; - int num_funcs; -}; - /* Called from stop_machine */ static int kpatch_apply_patch(void *data) { - struct kpatch_stop_machine_args *args = data; - struct kpatch_func *funcs = args->funcs; - int num_funcs = args->num_funcs; + struct kpatch_module *kpmod = data; + struct kpatch_func *funcs = kpmod->funcs; + int num_funcs = kpmod->num_funcs; int i, ret; - ret = kpatch_verify_activeness_safety(funcs, num_funcs); + ret = kpatch_verify_activeness_safety(kpmod); if (ret) goto out; @@ -194,12 +187,12 @@ out: /* Called from stop_machine */ static int kpatch_remove_patch(void *data) { - struct kpatch_stop_machine_args *args = data; - struct kpatch_func *funcs = args->funcs; - int num_funcs = args->num_funcs; + struct kpatch_module *kpmod = data; + struct kpatch_func *funcs = kpmod->funcs; + int num_funcs = kpmod->num_funcs; int ret, i; - ret = kpatch_verify_activeness_safety(funcs, num_funcs); + ret = kpatch_verify_activeness_safety(kpmod); if (ret) goto out; @@ -343,21 +336,20 @@ static int kpatch_remove_funcs_from_filter(struct kpatch_func *funcs, return ret; } -int kpatch_register(struct module *mod, struct kpatch_func *funcs, - int num_funcs) +int kpatch_register(struct kpatch_module *kpmod) { int ret, i; - struct kpatch_stop_machine_args args = { - .funcs = funcs, - .num_funcs = num_funcs, - }; + struct kpatch_func *funcs = kpmod->funcs; + int num_funcs = kpmod->num_funcs; + + if (!kpmod->mod || !funcs || !num_funcs) + return -EINVAL; down(&kpatch_mutex); for (i = 0; i < num_funcs; i++) { struct kpatch_func *func = &funcs[i]; - func->mod = mod; func->updating = true; /* @@ -399,7 +391,7 @@ int kpatch_register(struct module *mod, struct kpatch_func *funcs, * Idle the CPUs, verify activeness safety, and atomically make the new * functions visible to the trampoline. */ - ret = stop_machine(kpatch_apply_patch, &args, NULL); + ret = stop_machine(kpatch_apply_patch, kpmod, NULL); if (ret) { /* * This synchronize_rcu is to ensure any other kpatch_get_func @@ -414,7 +406,7 @@ int kpatch_register(struct module *mod, struct kpatch_func *funcs, pr_notice_once("tainting kernel with TAINT_USER\n"); add_taint(TAINT_USER, LOCKDEP_STILL_OK); - pr_notice("loaded patch module \"%s\"\n", mod->name); + pr_notice("loaded patch module \"%s\"\n", kpmod->mod->name); out: atomic_set(&kpatch_operation, KPATCH_OP_NONE); @@ -436,14 +428,11 @@ err_rollback: } EXPORT_SYMBOL(kpatch_register); -int kpatch_unregister(struct module *mod, struct kpatch_func *funcs, - int num_funcs) +int kpatch_unregister(struct kpatch_module *kpmod) { + struct kpatch_func *funcs = kpmod->funcs; + int num_funcs = kpmod->num_funcs; int i, ret; - struct kpatch_stop_machine_args args = { - .funcs = funcs, - .num_funcs = num_funcs, - }; down(&kpatch_mutex); @@ -458,7 +447,7 @@ int kpatch_unregister(struct module *mod, struct kpatch_func *funcs, for (i = 0; i < num_funcs; i++) funcs[i].updating = true; - ret = stop_machine(kpatch_remove_patch, &args, NULL); + ret = stop_machine(kpatch_remove_patch, kpmod, NULL); if (ret) goto out; @@ -482,7 +471,7 @@ int kpatch_unregister(struct module *mod, struct kpatch_func *funcs, if (ret) goto out; - pr_notice("unloaded patch module \"%s\"\n", mod->name); + pr_notice("unloaded patch module \"%s\"\n", kpmod->mod->name); out: atomic_set(&kpatch_operation, KPATCH_OP_NONE); diff --git a/kmod/core/kpatch.h b/kmod/core/kpatch.h index d9893bd..8c91a80 100644 --- a/kmod/core/kpatch.h +++ b/kmod/core/kpatch.h @@ -31,14 +31,17 @@ struct kpatch_func { unsigned long new_addr; unsigned long old_addr; unsigned long old_size; - struct module *mod; struct hlist_node node; bool updating; }; -extern int kpatch_register(struct module *mod, struct kpatch_func *funcs, - int num_funcs); -extern int kpatch_unregister(struct module *mod, struct kpatch_func *funcs, - int num_funcs); +struct kpatch_module { + struct module *mod; + struct kpatch_func *funcs; + int num_funcs; +}; + +extern int kpatch_register(struct kpatch_module *kpmod); +extern int kpatch_unregister(struct kpatch_module *kpmod); #endif /* _KPATCH_H_ */ diff --git a/kmod/patch/kpatch-patch-hook.c b/kmod/patch/kpatch-patch-hook.c index b659e2a..7f650fa 100644 --- a/kmod/patch/kpatch-patch-hook.c +++ b/kmod/patch/kpatch-patch-hook.c @@ -27,8 +27,7 @@ extern char __kpatch_patches, __kpatch_patches_end; -static struct kpatch_func *funcs; -static int num_funcs; +static struct kpatch_module kpmod; static int __init patch_init(void) { @@ -36,26 +35,29 @@ static int __init patch_init(void) int i, ret; patches = (struct kpatch_patch *)&__kpatch_patches; - num_funcs = (&__kpatch_patches_end - &__kpatch_patches) / - sizeof(*patches); - funcs = kmalloc(num_funcs * sizeof(*funcs), GFP_KERNEL); - if (!funcs) + + kpmod.mod = THIS_MODULE; + kpmod.num_funcs = (&__kpatch_patches_end - &__kpatch_patches) / + sizeof(*patches); + kpmod.funcs = kmalloc(kpmod.num_funcs * sizeof(struct kpatch_func), + GFP_KERNEL); + if (!kpmod.funcs) return -ENOMEM; - for (i = 0; i < num_funcs; i++) { - funcs[i].old_addr = patches[i].old_addr; - funcs[i].old_size = patches[i].old_size; - funcs[i].new_addr = patches[i].new_addr; + for (i = 0; i < kpmod.num_funcs; i++) { + kpmod.funcs[i].old_addr = patches[i].old_addr; + kpmod.funcs[i].old_size = patches[i].old_size; + kpmod.funcs[i].new_addr = patches[i].new_addr; } - ret = kpatch_register(THIS_MODULE, funcs, num_funcs); + ret = kpatch_register(&kpmod); if (ret) goto err_free; return 0; err_free: - kfree(funcs); + kfree(kpmod.funcs); return ret; } @@ -63,7 +65,7 @@ static void __exit patch_exit(void) { int ret; - ret = kpatch_unregister(THIS_MODULE, funcs, num_funcs); + ret = kpatch_unregister(&kpmod); if (ret) { /* * TODO: If this happens, we're screwed. We need a way to @@ -77,7 +79,7 @@ static void __exit patch_exit(void) panic("kpatch_unregister failed: %d", ret); } - kfree(funcs); + kfree(kpmod.funcs); } module_init(patch_init);