From 9ac8822b66bb06a463a29ec86088cfe8adc1e6d4 Mon Sep 17 00:00:00 2001 From: Jiajie Li Date: Mon, 12 Oct 2020 14:45:03 +0800 Subject: [PATCH 34/89] kpatch_coro: Split function locate_start_context_symbol The function locate_start_context_symbol is arch related, so let's make two separate definations in arch/x86/arch_coro.c and arch/aarch64/arch_coro.c Signed-off-by: Jiajie Li Signed-off-by: Ying Fang --- src/arch/aarch64/arch_coro.c | 63 ++++++++++++++++++++++++++ src/arch/x86/arch_coro.c | 67 +++++++++++++++++++++++++++ src/include/kpatch_coro.h | 21 +++++++++ src/kpatch_coro.c | 87 ------------------------------------ 4 files changed, 151 insertions(+), 87 deletions(-) diff --git a/src/arch/aarch64/arch_coro.c b/src/arch/aarch64/arch_coro.c index b93581e..f485cf9 100644 --- a/src/arch/aarch64/arch_coro.c +++ b/src/arch/aarch64/arch_coro.c @@ -11,6 +11,69 @@ #include "include/kpatch_ptrace.h" #include "include/kpatch_log.h" +asm ( + "makecontext_call:\n" + "mov x29, sp\n" + "and x29,x29,#-16\n" + "sub x29, x29,#0x400\n" + "ldr x9,[x29,#-128]\n" + "str x9,[fp,#0x10]\n" + //"str #128,[fp.#0x20]\n" + "mov x0,fp\n" + "mov x1,#0x100\n" + "mov x2,#0\n" + "svc #0\n" + "brk #0\n" + "makecontext_call_end:" + ); + +extern unsigned char makecontext_call, makecontext_call_end; + +int +locate_start_context_symbol(struct kpatch_process *proc, + unsigned long *pstart_context) +{ + struct object_file *olibc; + struct user_regs_struct regs; + int rv; + unsigned long makecontext; + + olibc = kpatch_process_get_obj_by_regex(proc, "^libc-.*\\.so"); + if (olibc == NULL) { + kpdebug("FAIL. Can't find libc\n"); + return -1; + } + + rv = kpatch_resolve_undefined_single_dynamic(olibc, + "makecontext", + &makecontext); + makecontext = vaddr2addr(olibc, makecontext); + if (rv < 0 || makecontext == 0) { + kpdebug("FAIL. Can't find makecontext\n"); + return -1; + } + + regs.regs[8] = makecontext; + rv = kpatch_execute_remote(proc2pctx(proc), + &makecontext_call, + &makecontext_call_end - &makecontext_call, + ®s); + if (rv < 0) { + kpdebug("FAIL. Can't execute makecontext\n"); + return -1; + } + + rv = kpatch_process_mem_read(proc, + regs.regs[29]- STACK_OFFSET_START_CONTEXT, + pstart_context, + sizeof(*pstart_context)); + if (rv < 0) { + kpdebug("FAIL. Can't peek __start_context address\n"); + return -1; + } + return rv; +} + int get_ptr_guard(struct kpatch_process *proc, unsigned long *ptr_guard) { diff --git a/src/arch/x86/arch_coro.c b/src/arch/x86/arch_coro.c index 86bf12f..27c834b 100644 --- a/src/arch/x86/arch_coro.c +++ b/src/arch/x86/arch_coro.c @@ -15,6 +15,73 @@ #include "include/kpatch_ptrace.h" #include "include/kpatch_log.h" +asm ("makecontext_call:\n" + "mov %rsp, %rbp\n" + "and $-16, %rbp\n" + /* ucontext_t is 0x3a8 bytes */ + "sub $0x400, %rbp\n" + /* TODO interpolate these from the calculations above */ + + /* set uc_stack.ss_sp and uc_stack.ss_size */ + /* TODO magic -128 is used below as well */ + "lea -128(%rbp), %rbx\n" + "movq %rbx, 0x10(%rbp)\n" + "movq $128, 0x20(%rbp)\n" + "mov %rbp, %rdi\n" + "mov $0x100, %rsi\n" + "xor %rdx, %rdx\n" + /* call `makecontext` */ + "call *%rax\n" + "int3\n" + "makecontext_call_end:"); + +extern unsigned char makecontext_call, makecontext_call_end; + +int +locate_start_context_symbol(struct kpatch_process *proc, + unsigned long *pstart_context) +{ + struct object_file *olibc; + struct user_regs_struct regs; + int rv; + unsigned long makecontext; + + olibc = kpatch_process_get_obj_by_regex(proc, "^libc-.*\\.so"); + if (olibc == NULL) { + kpdebug("FAIL. Can't find libc\n"); + return -1; + } + + rv = kpatch_resolve_undefined_single_dynamic(olibc, + "makecontext", + &makecontext); + makecontext = vaddr2addr(olibc, makecontext); + if (rv < 0 || makecontext == 0) { + kpdebug("FAIL. Can't find makecontext\n"); + return -1; + } + + regs.rax = makecontext; + rv = kpatch_execute_remote(proc2pctx(proc), + &makecontext_call, + &makecontext_call_end - &makecontext_call, + ®s); + if (rv < 0) { + kpdebug("FAIL. Can't execute makecontext\n"); + return -1; + } + + rv = kpatch_process_mem_read(proc, + regs.rbp - STACK_OFFSET_START_CONTEXT, + pstart_context, + sizeof(*pstart_context)); + if (rv < 0) { + kpdebug("FAIL. Can't peek __start_context address\n"); + return -1; + } + return rv; +} + int get_ptr_guard(struct kpatch_process *proc, unsigned long *ptr_guard) { diff --git a/src/include/kpatch_coro.h b/src/include/kpatch_coro.h index 272855e..0b3a9a1 100644 --- a/src/include/kpatch_coro.h +++ b/src/include/kpatch_coro.h @@ -30,10 +30,31 @@ struct UCORO_info { int _UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, void *arg); +#define PTR_DEMANGLE(ptr, key) ((((ptr) >> 0x11) | ((ptr) << 47)) ^ key) +#define JB_RBX 0 +#define JB_RBP 1 +#define JB_R12 2 +#define JB_R13 3 +#define JB_R14 4 +#define JB_R15 5 +#define JB_RSP 6 +#define JB_RIP 7 + +#define STACK_OFFSET_UC_LINK (2 * sizeof(long)) +#define STACK_OFFSET_START_CONTEXT (3 * sizeof(long)) +#define STACK_OFFSET_UC_LINK_PTR (4 * sizeof(long)) +#define STACK_OFFSET_COROUTINE_UCONTEXT (7 * sizeof(long)) +#define STACK_OFFSET_COROUTINE (8 * sizeof(long)) + +#define UCONTEXT_OFFSET_JMPBUF 0x38 + #define GLIBC_TLS_PTR_GUARD 0x30 int get_ptr_guard(struct kpatch_process *proc, unsigned long *ptr_guard); +int locate_start_context_symbol(struct kpatch_process *proc, + unsigned long *pstart_context); + int kpatch_coroutines_init(struct kpatch_process *proc); int kpatch_coroutines_find(struct kpatch_process *proc); diff --git a/src/kpatch_coro.c b/src/kpatch_coro.c index ea4050f..8457800 100644 --- a/src/kpatch_coro.c +++ b/src/kpatch_coro.c @@ -95,93 +95,6 @@ kpatch_coro_free(struct kpatch_coro *c) * some kind of persistency (to allow kernelcare updates). This * service also can listen to netlink events about new processes. */ -#define PTR_DEMANGLE(ptr, key) ((((ptr) >> 0x11) | ((ptr) << 47)) ^ key) -#define JB_RBX 0 -#define JB_RBP 1 -#define JB_R12 2 -#define JB_R13 3 -#define JB_R14 4 -#define JB_R15 5 -#define JB_RSP 6 -#define JB_RIP 7 - -#define STACK_OFFSET_UC_LINK (2 * sizeof(long)) -#define STACK_OFFSET_START_CONTEXT (3 * sizeof(long)) -#define STACK_OFFSET_UC_LINK_PTR (4 * sizeof(long)) -#define STACK_OFFSET_COROUTINE_UCONTEXT (7 * sizeof(long)) -#define STACK_OFFSET_COROUTINE (8 * sizeof(long)) - -#define UCONTEXT_OFFSET_JMPBUF 0x38 - -#define UCONTEXT_OFFSET_UC_STACK_SS_SP offsetof(ucontext_t, uc_stack.ss_sp) -#define UCONTEXT_OFFSET_UC_STACK_SS_SIZE offsetof(ucontext_t, uc_stack.ss_size) - -asm ("makecontext_call:\n" - "mov %rsp, %rbp\n" - "and $-16, %rbp\n" - /* ucontext_t is 0x3a8 bytes */ - "sub $0x400, %rbp\n" - /* TODO interpolate these from the calculations above */ - - /* set uc_stack.ss_sp and uc_stack.ss_size */ - /* TODO magic -128 is used below as well */ - "lea -128(%rbp), %rbx\n" - "movq %rbx, 0x10(%rbp)\n" - "movq $128, 0x20(%rbp)\n" - "mov %rbp, %rdi\n" - "mov $0x100, %rsi\n" - "xor %rdx, %rdx\n" - /* call `makecontext` */ - "call *%rax\n" - "int3\n" - "makecontext_call_end:"); - -extern unsigned char makecontext_call, makecontext_call_end; - -static int -locate_start_context_symbol(struct kpatch_process *proc, - unsigned long *pstart_context) -{ - struct object_file *olibc; - struct user_regs_struct regs; - int rv; - unsigned long makecontext; - - olibc = kpatch_process_get_obj_by_regex(proc, "^libc-.*\\.so"); - if (olibc == NULL) { - kpdebug("FAIL. Can't find libc\n"); - return -1; - } - - rv = kpatch_resolve_undefined_single_dynamic(olibc, - "makecontext", - &makecontext); - makecontext = vaddr2addr(olibc, makecontext); - if (rv < 0 || makecontext == 0) { - kpdebug("FAIL. Can't find makecontext\n"); - return -1; - } - - regs.rax = makecontext; - rv = kpatch_execute_remote(proc2pctx(proc), - &makecontext_call, - &makecontext_call_end - &makecontext_call, - ®s); - if (rv < 0) { - kpdebug("FAIL. Can't execute makecontext\n"); - return -1; - } - - rv = kpatch_process_mem_read(proc, - regs.rbp - STACK_OFFSET_START_CONTEXT, - pstart_context, - sizeof(*pstart_context)); - if (rv < 0) { - kpdebug("FAIL. Can't peek __start_context address\n"); - return -1; - } - return rv; -} static int is_test_target(struct kpatch_process *proc, const char *procname) -- 2.23.0