From: Zheng Yejian zhengyejian1@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4UAQ1
--------------------------------
Introduce 'arch_klp_save_old_code' preparing for moving func_node initializing codes out of stop_machine.
Signed-off-by: Zheng Yejian zhengyejian1@huawei.com Reviewed-by: Kuohai Xu xukuohai@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm/include/asm/livepatch.h | 2 ++ arch/arm/kernel/livepatch.c | 28 ++++++++++++++++---------- arch/arm64/include/asm/livepatch.h | 2 ++ arch/arm64/kernel/livepatch.c | 30 ++++++++++++++++++---------- arch/powerpc/include/asm/livepatch.h | 3 +++ arch/powerpc/kernel/livepatch_32.c | 24 +++++++++++++++------- arch/powerpc/kernel/livepatch_64.c | 26 ++++++++++++++++-------- arch/x86/include/asm/livepatch.h | 2 ++ arch/x86/kernel/livepatch.c | 9 +++++++-- 9 files changed, 88 insertions(+), 38 deletions(-)
diff --git a/arch/arm/include/asm/livepatch.h b/arch/arm/include/asm/livepatch.h index abeccf19f9ca..4f1cf4c72097 100644 --- a/arch/arm/include/asm/livepatch.h +++ b/arch/arm/include/asm/livepatch.h @@ -51,6 +51,8 @@ struct arch_klp_data { #endif };
+long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func); + #endif
#endif /* _ASM_ARM_LIVEPATCH_H */ diff --git a/arch/arm/kernel/livepatch.c b/arch/arm/kernel/livepatch.c index 6d53e8d250b0..ffecb1f0c968 100644 --- a/arch/arm/kernel/livepatch.c +++ b/arch/arm/kernel/livepatch.c @@ -353,6 +353,23 @@ long arm_insn_read(void *addr, u32 *insnp) return ret; }
+long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func) +{ + long ret; +#ifdef CONFIG_ARM_MODULE_PLTS + int i; + + for (i = 0; i < LJMP_INSN_SIZE; i++) { + ret = arm_insn_read((u32 *)old_func + i, &arch_data->old_insns[i]); + if (ret) + break; + } +#else + ret = arm_insn_read(old_func, &arch_data->old_insn); +#endif + return ret; +} + int arch_klp_patch_func(struct klp_func *func) { struct klp_func_node *func_node; @@ -372,16 +389,7 @@ int arch_klp_patch_func(struct klp_func *func)
INIT_LIST_HEAD(&func_node->func_stack); func_node->old_func = func->old_func; -#ifdef CONFIG_ARM_MODULE_PLTS - for (i = 0; i < LJMP_INSN_SIZE; i++) { - ret = arm_insn_read((u32 *)func->old_func + i, - &func_node->arch_data.old_insns[i]); - if (ret) - break; - } -#else - ret = arm_insn_read(func->old_func, &func_node->arch_data.old_insn); -#endif + ret = arch_klp_save_old_code(&func_node->arch_data, func->old_func); if (ret) { return -EPERM; } diff --git a/arch/arm64/include/asm/livepatch.h b/arch/arm64/include/asm/livepatch.h index 11a972c596cf..a9bc7ce4cc6e 100644 --- a/arch/arm64/include/asm/livepatch.h +++ b/arch/arm64/include/asm/livepatch.h @@ -61,6 +61,8 @@ struct arch_klp_data { #endif };
+long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func); + #endif
#endif /* _ASM_ARM64_LIVEPATCH_H */ diff --git a/arch/arm64/kernel/livepatch.c b/arch/arm64/kernel/livepatch.c index 3746c689a6f1..6683cb0a28fa 100644 --- a/arch/arm64/kernel/livepatch.c +++ b/arch/arm64/kernel/livepatch.c @@ -331,6 +331,24 @@ int klp_check_calltrace(struct klp_patch *patch, int enable) } #endif
+long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func) +{ + long ret; +#ifdef CONFIG_ARM64_MODULE_PLTS + int i; + + for (i = 0; i < LJMP_INSN_SIZE; i++) { + ret = aarch64_insn_read(((u32 *)old_func) + i, + &arch_data->old_insns[i]); + if (ret) + break; + } +#else + ret = aarch64_insn_read(old_func, &arch_data->old_insn); +#endif + return ret; +} + int arch_klp_patch_func(struct klp_func *func) { struct klp_func_node *func_node; @@ -353,17 +371,7 @@ int arch_klp_patch_func(struct klp_func *func) INIT_LIST_HEAD(&func_node->func_stack); func_node->old_func = func->old_func;
-#ifdef CONFIG_ARM64_MODULE_PLTS - for (i = 0; i < LJMP_INSN_SIZE; i++) { - ret = aarch64_insn_read(((u32 *)func->old_func) + i, - &func_node->arch_data.old_insns[i]); - if (ret) - break; - } -#else - ret = aarch64_insn_read((void *)func->old_func, - &func_node->arch_data.old_insn); -#endif + ret = arch_klp_save_old_code(&func_node->arch_data, func->old_func); if (ret) { return -EPERM; } diff --git a/arch/powerpc/include/asm/livepatch.h b/arch/powerpc/include/asm/livepatch.h index 5901e3069c07..fea12c6b915c 100644 --- a/arch/powerpc/include/asm/livepatch.h +++ b/arch/powerpc/include/asm/livepatch.h @@ -93,6 +93,7 @@ struct arch_klp_data {
#elif defined(CONFIG_PPC32)
+#define PPC32_INSN_SIZE 4 #define LJMP_INSN_SIZE 4 struct arch_klp_data { u32 old_insns[LJMP_INSN_SIZE]; @@ -100,6 +101,8 @@ struct arch_klp_data {
#endif /* CONFIG_PPC64 */
+long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func); + #endif /* CONFIG_LIVEPATCH_FTRACE */
#ifdef CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY diff --git a/arch/powerpc/kernel/livepatch_32.c b/arch/powerpc/kernel/livepatch_32.c index 638f18d88c33..ddc858294afb 100644 --- a/arch/powerpc/kernel/livepatch_32.c +++ b/arch/powerpc/kernel/livepatch_32.c @@ -378,6 +378,20 @@ static inline bool offset_in_range(unsigned long pc, unsigned long addr, return (offset >= -range && offset < range); }
+long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func) +{ + long ret; + int i; + + for (i = 0; i < LJMP_INSN_SIZE; i++) { + ret = copy_from_kernel_nofault(&arch_data->old_insns[i], + ((u32 *)old_func) + i, PPC32_INSN_SIZE); + if (ret) + break; + } + return ret; +} + int arch_klp_patch_func(struct klp_func *func) { struct klp_func_node *func_node; @@ -396,13 +410,9 @@ int arch_klp_patch_func(struct klp_func *func) memory_flag = 1; INIT_LIST_HEAD(&func_node->func_stack); func_node->old_func = func->old_func; - for (i = 0; i < LJMP_INSN_SIZE; i++) { - ret = copy_from_kernel_nofault(&func_node->arch_data.old_insns[i], - ((u32 *)func->old_func) + i, LJMP_INSN_SIZE); - if (ret) { - return -EPERM; - } - } + ret = arch_klp_save_old_code(&func_node->arch_data, func->old_func); + if (ret) + return -EPERM;
klp_add_func_node(func_node); } diff --git a/arch/powerpc/kernel/livepatch_64.c b/arch/powerpc/kernel/livepatch_64.c index c0d6fd5ead8e..6fa7c3c20528 100644 --- a/arch/powerpc/kernel/livepatch_64.c +++ b/arch/powerpc/kernel/livepatch_64.c @@ -424,11 +424,25 @@ int klp_check_calltrace(struct klp_patch *patch, int enable) #endif
#ifdef CONFIG_LIVEPATCH_WO_FTRACE + +long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func) +{ + long ret; + int i; + + for (i = 0; i < LJMP_INSN_SIZE; i++) { + ret = copy_from_kernel_nofault(&arch_data->old_insns[i], + ((u32 *)old_func) + i, PPC64_INSN_SIZE); + if (ret) + break; + } + return ret; +} + int arch_klp_patch_func(struct klp_func *func) { struct klp_func_node *func_node; unsigned long pc, new_addr; - int i; int memory_flag = 0; long ret;
@@ -441,13 +455,9 @@ int arch_klp_patch_func(struct klp_func *func) memory_flag = 1; INIT_LIST_HEAD(&func_node->func_stack); func_node->old_func = func->old_func; - for (i = 0; i < LJMP_INSN_SIZE; i++) { - ret = copy_from_kernel_nofault(&func_node->arch_data.old_insns[i], - ((u32 *)func->old_func) + i, 4); - if (ret) { - return -EPERM; - } - } + ret = arch_klp_save_old_code(&func_node->arch_data, func->old_func); + if (ret) + return -EPERM; klp_add_func_node(func_node); }
diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h index c89f20576ca7..e23c2da3c323 100644 --- a/arch/x86/include/asm/livepatch.h +++ b/arch/x86/include/asm/livepatch.h @@ -39,6 +39,8 @@ struct arch_klp_data { unsigned char old_code[JMP_E9_INSN_SIZE]; };
+long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func); + #endif
#endif /* _ASM_X86_LIVEPATCH_H */ diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c index 02c869ea18fb..d5c03869df00 100644 --- a/arch/x86/kernel/livepatch.c +++ b/arch/x86/kernel/livepatch.c @@ -388,6 +388,12 @@ void arch_klp_code_modify_post_process(void) mutex_unlock(&text_mutex); }
+long arch_klp_save_old_code(struct arch_klp_data *arch_data, void *old_func) +{ + return copy_from_kernel_nofault(arch_data->old_code, + old_func, JMP_E9_INSN_SIZE); +} + int arch_klp_patch_func(struct klp_func *func) { struct klp_func_node *func_node; @@ -404,8 +410,7 @@ int arch_klp_patch_func(struct klp_func *func)
INIT_LIST_HEAD(&func_node->func_stack); func_node->old_func = func->old_func; - ret = copy_from_kernel_nofault(func_node->arch_data.old_code, - (void *)ip, JMP_E9_INSN_SIZE); + ret = arch_klp_save_old_code(&func_node->arch_data, (void *)ip); if (ret) { return -EPERM; }