Created
December 2, 2020 14:15
-
-
Save DavadDi/a82f46a1bb9e9f5a6c22d44c8142e89b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// hijack.c | |
#include <linux/kernel.h> /* We're doing kernel work */ | |
#include <linux/module.h> /* Specifically, a module */ | |
#include <linux/proc_fs.h> /* Necessary because we use the proc fs */ | |
#include <asm/uaccess.h> /* for copy_from_user */ | |
#include <linux/fs.h> | |
#include <linux/seq_file.h> | |
#include <linux/slab.h> | |
#include <linux/kallsyms.h> | |
#include <linux/cpu.h> | |
char *stub; | |
char *addr = NULL; | |
// 可以用JMP模式,也可以用CALL模式 | |
//#define JMP 1 | |
// 和 ipvs 模块里同名的 estimation_timer 函数 | |
static void estimation_timer(unsigned long arg) | |
{ | |
printk("estimation_timer patched\n"); | |
return; | |
} | |
// hijack_stub的作用就类似于ftrace kpatch里的ftrace_regs_caller | |
static void hijack_stub(unsigned long arg) | |
{ | |
// 用nop占位,加上C编译器自动生成的函数header代码,这么大的函数来容纳stub应该够了。 | |
asm ("nop; nop; nop; nop; nop; nop; nop; nop;"); | |
return; | |
} | |
#define FTRACE_SIZE 5 | |
#define POKE_OFFSET 0 | |
#define POKE_LENGTH 5 | |
#define SKIP_LENGTH 8 | |
static unsigned long *(*_mod_find_symname)(struct module *mod, const char *name); | |
static void *(*_text_poke_smp)(void *addr, const void *opcode, size_t len); | |
static struct mutex *_text_mutex; | |
unsigned char saved_inst[POKE_LENGTH]; | |
struct module *mod; | |
static int __init hotfix_init(void) | |
{ | |
unsigned char jmp_call[POKE_LENGTH]; | |
unsigned char e8_skip_stack[SKIP_LENGTH]; | |
s32 offset, i = 5; | |
mod = find_module("ip_vs"); | |
printk("hotfix_init init\n"); | |
if (!mod) { | |
printk("hotfix mod not found\n"); | |
return -1; | |
} | |
_mod_find_symname = (void *)kallsyms_lookup_name("mod_find_symname"); | |
if (!_mod_find_symname) { | |
printk("hotfix _mod_find_symname error"); | |
return -1; | |
} | |
addr = (void *)_mod_find_symname(mod, "estimation_timer"); | |
if (!addr) { | |
printk("hotfix addr estimation_timer NULL\n"); | |
return -1; | |
} | |
printk("hotfix estimation_timer addr %p\n", addr); | |
_text_poke_smp = (void *)kallsyms_lookup_name("text_poke_smp"); | |
_text_mutex = (void *)kallsyms_lookup_name("text_mutex"); | |
if (!_text_poke_smp || !_text_mutex) { | |
printk("!_text_poke_smp || !_text_mutex"); | |
return -1; | |
} | |
stub = (void *)hijack_stub; | |
offset = (s32)((long)estimation_timer - (long)stub - FTRACE_SIZE); | |
// 下面的代码就是stub函数的最终填充,它类似于ftrace_regs_caller的作用! | |
e8_skip_stack[0] = 0xe8; | |
(*(s32 *)(&e8_skip_stack[1])) = offset; | |
#ifndef JMP // 如果是call模式,则需要手工平衡堆栈,跳过原始函数的栈帧 | |
e8_skip_stack[i++] = 0x41; // pop %r11 | |
e8_skip_stack[i++] = 0x5b; // r11寄存器为临时使用寄存器,遵循调用者自行保护原则 | |
#endif | |
e8_skip_stack[i++] = 0xc3; | |
_text_poke_smp(&stub[0], e8_skip_stack, SKIP_LENGTH); | |
offset = (s32)((long)stub - (long)addr - FTRACE_SIZE); | |
memcpy(&saved_inst[0], addr, POKE_LENGTH); | |
#ifndef JMP | |
jmp_call[0] = 0xe8; | |
#else | |
jmp_call[0] = 0xe9; | |
#endif | |
(*(s32 *)(&jmp_call[1])) = offset; | |
get_online_cpus(); | |
mutex_lock(_text_mutex); | |
_text_poke_smp(&addr[POKE_OFFSET], jmp_call, POKE_LENGTH); | |
mutex_unlock(_text_mutex); | |
put_online_cpus(); | |
printk("hotfix init return \n"); | |
return 0; | |
} | |
static void __exit hotfix_exit(void) | |
{ | |
printk("hotfix_exit enter\n"); | |
mod = find_module("ip_vs"); | |
if (!mod) { | |
printk("hotfix mod not found\n"); | |
return; | |
} | |
addr = (void *)_mod_find_symname(mod, "estimation_timer"); | |
if (!addr) { | |
printk("hotfix addr estimation_timer is NULL \n"); | |
return; | |
} | |
printk("estimation_timer addr: %p\n", addr); | |
get_online_cpus(); | |
mutex_lock(_text_mutex); | |
_text_poke_smp(&addr[POKE_OFFSET], &saved_inst[0], POKE_LENGTH); | |
mutex_unlock(_text_mutex); | |
put_online_cpus(); | |
} | |
module_init(hotfix_init); | |
module_exit(hotfix_exit); | |
MODULE_LICENSE("GPL"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://blog.csdn.net/dog250/article/details/105254739