From 4f165eacd6d1d64cc43a58dd54e35017663d99e2 Mon Sep 17 00:00:00 2001 From: Jiajie Li Date: Mon, 12 Oct 2020 14:58:18 +0800 Subject: [PATCH 35/89] kpatch_patch: Split function patch_apply_hunk The function patch_apply_hunk is arch related, so make two separate definations in arch/x86/arch_patch.c and arch/aarch64/arch_patch.c Signed-off-by: Jiajie Li Signed-off-by: Ying Fang --- src/arch/aarch64/arch_patch.c | 68 +++++++++++++++++++++++++++++++++++ src/arch/x86/arch_patch.c | 66 ++++++++++++++++++++++++++++++++++ src/include/kpatch_patch.h | 2 ++ src/kpatch_patch.c | 44 ++--------------------- 4 files changed, 139 insertions(+), 41 deletions(-) diff --git a/src/arch/aarch64/arch_patch.c b/src/arch/aarch64/arch_patch.c index e69de29..9102621 100644 --- a/src/arch/aarch64/arch_patch.c +++ b/src/arch/aarch64/arch_patch.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "include/kpatch_patch.h" +#include "include/kpatch_user.h" +#include "include/kpatch_storage.h" +#include "include/kpatch_process.h" +#include "include/kpatch_file.h" +#include "include/kpatch_common.h" +#include "include/kpatch_elf.h" +#include "include/kpatch_ptrace.h" +#include "include/list.h" +#include "include/kpatch_log.h" + + +/***************************************************************************** + * Patch application subroutines + ****************************************************************************/ +/* + * This flag is local, i.e. it is never stored to the + * patch applied to patient's memory. + */ +int PATCH_APPLIED = (1 << 31); +int HUNK_SIZE = 4; + +int patch_apply_hunk(struct object_file *o, size_t nhunk) +{ + int ret; + unsigned char code[] = {0x00, 0x00, 0x00, 0x00}; /* ins: b IMM */ + struct kpatch_info *info = &o->info[nhunk]; + unsigned long pundo; + + if (is_new_func(info)) + return 0; + + pundo = o->kpta + o->kpfile.patch->user_undo + nhunk * HUNK_SIZE; + kpinfo("%s origcode from 0x%lx+0x%x to 0x%lx\n", + o->name, info->daddr, HUNK_SIZE, pundo); + ret = kpatch_process_memcpy(o->proc, pundo, + info->daddr, HUNK_SIZE); + if (ret < 0) + return ret; + + kpinfo("%s hunk 0x%lx+0x%x -> 0x%lx+0x%x\n", + o->name, info->daddr, info->dlen, info->saddr, info->slen); + + *(unsigned int *)(code) = (unsigned int)(info->saddr - info->daddr) / 4; + code[3] &= 0x3; + code[3] |= 0x14; + + ret = kpatch_process_mem_write(o->proc, + code, + info->daddr, + sizeof(code)); + /* + * NOTE(pboldin): This is only stored locally, as information have + * been copied to patient's memory already. + */ + info->flags |= PATCH_APPLIED; + return ret ? -1 : 0; +} diff --git a/src/arch/x86/arch_patch.c b/src/arch/x86/arch_patch.c index e69de29..a6e794d 100644 --- a/src/arch/x86/arch_patch.c +++ b/src/arch/x86/arch_patch.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "include/kpatch_patch.h" +#include "include/kpatch_user.h" +#include "include/kpatch_storage.h" +#include "include/kpatch_process.h" +#include "include/kpatch_file.h" +#include "include/kpatch_common.h" +#include "include/kpatch_elf.h" +#include "include/kpatch_ptrace.h" +#include "include/list.h" +#include "include/kpatch_log.h" + +/***************************************************************************** + * Patch application subroutines + ****************************************************************************/ +/* + * This flag is local, i.e. it is never stored to the + * patch applied to patient's memory. + */ +int PATCH_APPLIED = (1 << 31); +int HUNK_SIZE = 5; + +int patch_apply_hunk(struct object_file *o, size_t nhunk) +{ + int ret; + char code[] = {0xe9, 0x00, 0x00, 0x00, 0x00}; /* jmp IMM */ + struct kpatch_info *info = &o->info[nhunk]; + unsigned long pundo; + + if (is_new_func(info)) + return 0; + + pundo = o->kpta + o->kpfile.patch->user_undo + nhunk * HUNK_SIZE; + kpinfo("%s origcode from 0x%lx+0x%x to 0x%lx\n", + o->name, info->daddr, HUNK_SIZE, pundo); + ret = kpatch_process_memcpy(o->proc, pundo, + info->daddr, HUNK_SIZE); + if (ret < 0) + return ret; + + kpinfo("%s hunk 0x%lx+0x%x -> 0x%lx+0x%x\n", + o->name, info->daddr, info->dlen, info->saddr, info->slen); + *(unsigned int *)(code + 1) = (unsigned int)(info->saddr - info->daddr - 5); + ret = kpatch_process_mem_write(o->proc, + code, + info->daddr, + sizeof(code)); + /* + * NOTE(pboldin): This is only stored locally, as information have + * been copied to patient's memory already. + */ + info->flags |= PATCH_APPLIED; + return ret ? -1 : 0; +} + diff --git a/src/include/kpatch_patch.h b/src/include/kpatch_patch.h index 44806ab..fa96b08 100644 --- a/src/include/kpatch_patch.h +++ b/src/include/kpatch_patch.h @@ -25,4 +25,6 @@ struct unpatch_data { int process_patch(int pid, void *_data); int process_unpatch(int pid, void *_data); +int patch_apply_hunk(struct object_file *o, size_t nhunk); + #endif diff --git a/src/kpatch_patch.c b/src/kpatch_patch.c index 21a160a..4a1d149 100644 --- a/src/kpatch_patch.c +++ b/src/kpatch_patch.c @@ -270,47 +270,6 @@ patch_ensure_safety(struct object_file *o, /***************************************************************************** * Patch application subroutines ****************************************************************************/ -/* - * This flag is local, i.e. it is never stored to the - * patch applied to patient's memory. - */ -#define PATCH_APPLIED (1 << 31) - -#define HUNK_SIZE 5 - -static int -patch_apply_hunk(struct object_file *o, size_t nhunk) -{ - int ret; - char code[HUNK_SIZE] = {0xe9, 0x00, 0x00, 0x00, 0x00}; /* jmp IMM */ - struct kpatch_info *info = &o->info[nhunk]; - unsigned long pundo; - - if (is_new_func(info)) - return 0; - - pundo = o->kpta + o->kpfile.patch->user_undo + nhunk * HUNK_SIZE; - kpinfo("%s origcode from 0x%lx+0x%x to 0x%lx\n", - o->name, info->daddr, HUNK_SIZE, pundo); - ret = kpatch_process_memcpy(o->proc, pundo, - info->daddr, HUNK_SIZE); - if (ret < 0) - return ret; - - kpinfo("%s hunk 0x%lx+0x%x -> 0x%lx+0x%x\n", - o->name, info->daddr, info->dlen, info->saddr, info->slen); - *(unsigned int *)(code + 1) = (unsigned int)(info->saddr - info->daddr - 5); - ret = kpatch_process_mem_write(o->proc, - code, - info->daddr, - sizeof(code)); - /* - * NOTE(pboldin): This is only stored locally, as information have - * been copied to patient's memory already. - */ - info->flags |= PATCH_APPLIED; - return ret ? -1 : 0; -} static int duplicate_kp_file(struct object_file *o) @@ -328,6 +287,9 @@ duplicate_kp_file(struct object_file *o) return 0; } +extern int PATCH_APPLIED; +extern int HUNK_SIZE; + static int object_apply_patch(struct object_file *o) { -- 2.23.0