diff options
author | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2014-05-28 14:29:50 +0400 |
---|---|---|
committer | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2014-07-31 08:01:30 -0700 |
commit | 3bc5c13d9a5b3d5d697fe6ca01c74e3ba4ca6891 (patch) | |
tree | 70cf8078ac7d1597f38579420b09d231ed17c1f6 | |
parent | 92943d578946dba39396d1488322af7cc8da422e (diff) | |
download | swap-modules-3bc5c13d9a5b3d5d697fe6ca01c74e3ba4ca6891.tar.gz swap-modules-3bc5c13d9a5b3d5d697fe6ca01c74e3ba4ca6891.tar.bz2 swap-modules-3bc5c13d9a5b3d5d697fe6ca01c74e3ba4ca6891.zip |
[IMPROVE] x86: create jumper
Change-Id: Ic356826985c26b7397ab19b5996ba4a78fc54208
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
-rw-r--r-- | kprobe/arch/asm-x86/swap_kprobes.c | 83 | ||||
-rw-r--r-- | kprobe/arch/asm-x86/swap_kprobes.h | 4 |
2 files changed, 87 insertions, 0 deletions
diff --git a/kprobe/arch/asm-x86/swap_kprobes.c b/kprobe/arch/asm-x86/swap_kprobes.c index cd96cf2b..f9cf8f61 100644 --- a/kprobe/arch/asm-x86/swap_kprobes.c +++ b/kprobe/arch/asm-x86/swap_kprobes.c @@ -1000,6 +1000,89 @@ static void kjump_exit(void) +/* + ****************************************************************************** + * jumper * + ****************************************************************************** + */ +struct cb_data { + unsigned long ret_addr; + unsigned long bx; + + jumper_cb_t cb; + char data[0]; +}; + +static unsigned long __used get_bx(struct cb_data *data) +{ + return data->bx; +} + +static unsigned long __used jump_handler(struct cb_data *data) +{ + unsigned long ret_addr = data->ret_addr; + + /* call callback */ + data->cb(data->data); + + /* FIXME: potential memory leak, when process kill */ + kfree(data); + + return ret_addr; +} + +void jump_trampoline(void); +__asm( + "jump_trampoline: \n" + "pushf \n" + SWAP_SAVE_REGS_STRING + "movl %ebx, %eax \n" /* data --> ax */ + "call get_bx \n" + "movl %eax, (%esp) \n" /* restore bx */ + "movl %ebx, %eax \n" /* data --> ax */ + "call jump_handler \n" + /* move flags to cs */ + "movl 56(%esp), %edx \n" + "movl %edx, 52(%esp) \n" + /* replace saved flags with true return address. */ + "movl %eax, 56(%esp) \n" + SWAP_RESTORE_REGS_STRING + "popf\n" + "ret\n" +); + +unsigned long get_jump_addr(void) +{ + return (unsigned long)&jump_trampoline; +} +EXPORT_SYMBOL_GPL(get_jump_addr); + +int set_jump_cb(unsigned long ret_addr, struct pt_regs *regs, + jumper_cb_t cb, void *data, size_t size) +{ + struct cb_data *cb_data; + + cb_data = kmalloc(sizeof(*cb_data) + size, GFP_ATOMIC); + if (cb_data == NULL) + return -ENOMEM; + + /* save data */ + cb_data->ret_addr = ret_addr; + cb_data->cb = cb; + cb_data->bx = regs->bx; + memcpy(cb_data->data, data, size); + + /* save cb_data to bx */ + regs->bx = (long)cb_data; + + return 0; +} +EXPORT_SYMBOL_GPL(set_jump_cb); + + + + + /** * @brief Initializes x86 module deps. * diff --git a/kprobe/arch/asm-x86/swap_kprobes.h b/kprobe/arch/asm-x86/swap_kprobes.h index e8e7e77a..ce6e7a10 100644 --- a/kprobe/arch/asm-x86/swap_kprobes.h +++ b/kprobe/arch/asm-x86/swap_kprobes.h @@ -266,6 +266,10 @@ typedef unsigned long (*jumper_cb_t)(void *); int set_kjump_cb(struct pt_regs *regs, jumper_cb_t cb, void *data, size_t size); +unsigned long get_jump_addr(void); +int set_jump_cb(unsigned long ret_addr, struct pt_regs *regs, + jumper_cb_t cb, void *data, size_t size); + int swap_arch_init_kprobes(void); void swap_arch_exit_kprobes(void); |