hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9R2TB
--------------------------------
Signed-off-by: Zheng Yejian zhengyejian1@huawei.com --- arch/x86/include/asm/livepatch.h | 5 -- arch/x86/kernel/livepatch.c | 96 ++++---------------------------- include/linux/livepatch.h | 5 ++ kernel/livepatch/core.c | 88 ++++++++++++++++++++++++++++- 4 files changed, 102 insertions(+), 92 deletions(-)
diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h index e2cef5b2d8aa..5ffd1de9ce48 100644 --- a/arch/x86/include/asm/livepatch.h +++ b/arch/x86/include/asm/livepatch.h @@ -26,11 +26,6 @@ int arch_klp_patch_func(struct klp_func *func); void arch_klp_unpatch_func(struct klp_func *func); #endif
-#ifdef CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY -int klp_check_calltrace(struct klp_patch *patch, int enable); -#endif - - #if defined(CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY) || \ defined(CONFIG_LIVEPATCH_WO_FTRACE)
diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c index fa5880d3cc22..1fc4ac526943 100644 --- a/arch/x86/kernel/livepatch.c +++ b/arch/x86/kernel/livepatch.c @@ -52,16 +52,6 @@ static bool is_jump_insn(u8 *insn) return false; }
-static inline unsigned long klp_size_to_check(unsigned long func_size, - int force) -{ - unsigned long size = func_size; - - if (force == KLP_STACK_OPTIMIZE && size > JMP_E9_INSN_SIZE) - size = JMP_E9_INSN_SIZE; - return size; -} - static bool check_jump_insn(unsigned long func_addr) { int len = JMP_E9_INSN_SIZE; @@ -82,32 +72,8 @@ static bool check_jump_insn(unsigned long func_addr) return false; }
-static int add_func_to_list(struct klp_func_list **funcs, struct klp_func_list **func, - unsigned long func_addr, unsigned long func_size, const char *func_name, - int force) -{ - if (*func == NULL) { - *funcs = (struct klp_func_list*)kzalloc(sizeof(**funcs), GFP_ATOMIC); - if (!(*funcs)) - return -ENOMEM; - *func = *funcs; - } else { - (*func)->next = (struct klp_func_list*)kzalloc(sizeof(**funcs), - GFP_ATOMIC); - if (!(*func)->next) - return -ENOMEM; - *func = (*func)->next; - } - (*func)->func_addr = func_addr; - (*func)->func_size = func_size; - (*func)->func_name = func_name; - (*func)->force = force; - (*func)->next = NULL; - return 0; -} - -static int klp_check_activeness_func(struct klp_patch *patch, int enable, - struct klp_func_list **check_funcs) +int arch_klp_check_activeness_func(struct klp_patch *patch, int enable, + klp_add_func_t add_func, struct klp_func_list **func_list) { int ret; struct klp_object *obj; @@ -160,7 +126,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable, if (IS_ENABLED(CONFIG_PREEMPTION) || (func->force == KLP_NORMAL_FORCE) || check_jump_insn(func_addr)) { - ret = add_func_to_list(check_funcs, &pcheck, + ret = add_func(func_list, &pcheck, func_addr, func_size, func->old_name, func->force); if (ret) @@ -200,7 +166,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable, func_addr = (unsigned long)prev->new_func; func_size = prev->new_size; } - ret = add_func_to_list(check_funcs, &pcheck, func_addr, + ret = add_func(func_list, &pcheck, func_addr, func_size, func->old_name, 0); if (ret) return ret; @@ -214,7 +180,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
func_addr = (unsigned long)func->new_func; func_size = func->new_size; - ret = add_func_to_list(check_funcs, &pcheck, func_addr, + ret = add_func(func_list, &pcheck, func_addr, func_size, func->old_name, 0); if (ret) return ret; @@ -255,21 +221,6 @@ static void klp_print_stack_trace(void *trace_ptr, int trace_len) #endif #define MAX_STACK_ENTRIES 100
-static bool check_func_list(void *data, int *ret, unsigned long pc) -{ - struct klp_func_list *funcs = (struct klp_func_list *)data; - - while (funcs != NULL) { - *ret = klp_compare_address(pc, funcs->func_addr, funcs->func_name, - klp_size_to_check(funcs->func_size, funcs->force)); - if (*ret) { - return false; - } - funcs = funcs->next; - } - return true; -} - static int klp_check_stack(void *trace_ptr, int trace_len, bool (*fn)(void *, int *, unsigned long), void *data) { @@ -301,17 +252,6 @@ static int klp_check_stack(void *trace_ptr, int trace_len, return 0; }
-static void free_list(struct klp_func_list **funcs) -{ - struct klp_func_list *p; - - while (*funcs != NULL) { - p = *funcs; - *funcs = (*funcs)->next; - kfree(p); - } -} - static int do_check_calltrace(bool (*fn)(void *, int *, unsigned long), void *data) { struct task_struct *g, *t; @@ -360,27 +300,6 @@ static int do_check_calltrace(bool (*fn)(void *, int *, unsigned long), void *da return 0; }
-int klp_check_calltrace(struct klp_patch *patch, int enable) -{ - int ret = 0; - struct klp_func_list *check_funcs = NULL; - - ret = klp_check_activeness_func(patch, enable, &check_funcs); - if (ret) { - pr_err("collect active functions failed, ret=%d\n", ret); - goto out; - } - - if (!check_funcs) - goto out; - - ret = do_check_calltrace(check_func_list, (void *)check_funcs); - -out: - free_list(&check_funcs); - return ret; -} - static bool check_module_calltrace(void *data, int *ret, unsigned long pc) { struct module *mod = (struct module *)data; @@ -393,6 +312,11 @@ static bool check_module_calltrace(void *data, int *ret, unsigned long pc) return true; }
+int arch_klp_check_calltrace(bool (*check_func)(void *, int *, unsigned long), void *data) +{ + return do_check_calltrace(check_func, data); +} + int arch_klp_module_check_calltrace(void *data) { return do_check_calltrace(check_module_calltrace, data); diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h index 23fb19d74311..b4cf90c03d29 100644 --- a/include/linux/livepatch.h +++ b/include/linux/livepatch.h @@ -266,6 +266,11 @@ struct klp_func_list { const char *func_name; int force; }; + +typedef int (*klp_add_func_t)(struct klp_func_list **funcs, struct klp_func_list **func, + unsigned long func_addr, unsigned long func_size, + const char *func_name, int force); + #endif
int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 978dcede41a1..050c75d59f21 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -1339,11 +1339,97 @@ static int __klp_disable_patch(struct klp_patch *patch) return 0; } #elif defined(CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY) -int __weak klp_check_calltrace(struct klp_patch *patch, int enable) +int __weak arch_klp_check_calltrace(bool (*fn)(void *, int *, unsigned long), void *data) +{ + return -EINVAL; +} + +int __weak arch_klp_check_activeness_func(struct klp_patch *patch, int enable, + klp_add_func_t add_func, + struct klp_func_list **func_list) +{ + return -EINVAL; +} + +static inline unsigned long klp_size_to_check(unsigned long func_size, + int force) +{ + unsigned long size = func_size; + + if (force == KLP_STACK_OPTIMIZE && size > KLP_MAX_REPLACE_SIZE) + size = KLP_MAX_REPLACE_SIZE; + return size; +} + +static bool check_func_list(void *data, int *ret, unsigned long pc) { + struct klp_func_list *funcs = (struct klp_func_list *)data; + + while (funcs != NULL) { + *ret = klp_compare_address(pc, funcs->func_addr, funcs->func_name, + klp_size_to_check(funcs->func_size, funcs->force)); + if (*ret) + return false; + funcs = funcs->next; + } + return true; +} + +static int add_func_to_list(struct klp_func_list **funcs, struct klp_func_list **func, + unsigned long func_addr, unsigned long func_size, const char *func_name, + int force) +{ + if (*func == NULL) { + *funcs = kzalloc(sizeof(**funcs), GFP_ATOMIC); + if (!(*funcs)) + return -ENOMEM; + *func = *funcs; + } else { + (*func)->next = kzalloc(sizeof(**funcs), GFP_ATOMIC); + if (!(*func)->next) + return -ENOMEM; + *func = (*func)->next; + } + (*func)->func_addr = func_addr; + (*func)->func_size = func_size; + (*func)->func_name = func_name; + (*func)->force = force; + (*func)->next = NULL; return 0; }
+static void free_func_list(struct klp_func_list **funcs) +{ + struct klp_func_list *p; + + while (*funcs != NULL) { + p = *funcs; + *funcs = (*funcs)->next; + kfree(p); + } +} + +int __weak klp_check_calltrace(struct klp_patch *patch, int enable) +{ + int ret = 0; + struct klp_func_list *func_list = NULL; + + ret = arch_klp_check_activeness_func(patch, enable, add_func_to_list, &func_list); + if (ret) { + pr_err("collect active functions failed, ret=%d\n", ret); + goto out; + } + + if (!func_list) + goto out; + + ret = arch_klp_check_calltrace(check_func_list, (void *)func_list); + +out: + free_func_list(&func_list); + return ret; +} + static LIST_HEAD(klp_func_list);
/*