mirror of https://github.com/dynup/kpatch
kmod: add new kpatch_module struct
Put funcs, num_funcs, and mod in their own struct called kpatch_module. This allows us to keep patch module specific variables in one place (and we'll have more of these variables soon).
This commit is contained in:
parent
ff28767295
commit
2984b53d21
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue