mirror of
https://github.com/dynup/kpatch
synced 2025-03-31 23:57:33 +00:00
fix activeness safety check when unpatching
When unpatching, the activeness safety logic should check for the new function on the stack, not the old one. Fixes #64.
This commit is contained in:
parent
48cc3a409e
commit
f3f39c0587
@ -118,12 +118,24 @@ void kpatch_backtrace_address_verify(void *data, unsigned long address,
|
||||
return;
|
||||
|
||||
for (i = 0; i < kpmod->num_funcs; i++) {
|
||||
struct kpatch_func *func = &kpmod->funcs[i];
|
||||
unsigned long func_addr, func_size;
|
||||
struct kpatch_func *func, *active_func;
|
||||
|
||||
if (address >= func->old_addr &&
|
||||
address < func->old_addr + func->old_size) {
|
||||
func = &kpmod->funcs[i];
|
||||
active_func = kpatch_get_func(func->old_addr);
|
||||
if (!active_func) {
|
||||
/* patching an unpatched func */
|
||||
func_addr = func->old_addr;
|
||||
func_size = func->old_size;
|
||||
} else {
|
||||
/* repatching or unpatching */
|
||||
func_addr = active_func->new_addr;
|
||||
func_size = active_func->new_size;
|
||||
}
|
||||
|
||||
if (address >= func_addr && address < func_addr + func_size) {
|
||||
pr_err("activeness safety check failed for function "
|
||||
"at address 0x%lx\n", func->old_addr);
|
||||
"at address 0x%lx\n", func_addr);
|
||||
args->ret = -EBUSY;
|
||||
return;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
struct kpatch_func {
|
||||
unsigned long new_addr;
|
||||
unsigned long new_size;
|
||||
unsigned long old_addr;
|
||||
unsigned long old_size;
|
||||
struct hlist_node node;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Josh Poimboeuf <jpoimboe@redhat.com>
|
||||
* Copyright (C) 2013-2014 Josh Poimboeuf <jpoimboe@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -48,6 +48,7 @@ static int __init patch_init(void)
|
||||
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;
|
||||
kpmod.funcs[i].new_size = patches[i].new_size;
|
||||
}
|
||||
|
||||
ret = kpatch_register(&kpmod);
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
struct kpatch_patch {
|
||||
unsigned long new_addr;
|
||||
unsigned long new_size;
|
||||
unsigned long old_addr;
|
||||
unsigned long old_size;
|
||||
};
|
||||
|
@ -315,10 +315,18 @@ int main(int argc, char **argv)
|
||||
for_each_sym(&symlist, cur) {
|
||||
if (cur->action != PATCH)
|
||||
continue;
|
||||
|
||||
patches_data[i].old_addr = cur->vm_addr;
|
||||
patches_data[i].old_size = cur->vm_len;
|
||||
patches_data[i].new_size = cur->sym.st_size;
|
||||
|
||||
/*
|
||||
* Use a relocation to set patches_data[i].new_addr at module
|
||||
* loading time.
|
||||
*/
|
||||
relas_data[i].r_offset = i * sizeof(struct kpatch_patch);
|
||||
relas_data[i].r_info = GELF_R_INFO(cur->index, R_X86_64_64);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user