hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8MGE6
--------------------------------
Add arch_klp_module_check_calltrace to check whether stacks of all tasks are within the code segment of module.
Signed-off-by: Yang Jihong yangjihong1@huawei.com Signed-off-by: Zheng Yejian zhengyejian1@huawei.com --- arch/powerpc/include/asm/livepatch.h | 1 + arch/powerpc/kernel/livepatch.c | 33 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)
diff --git a/arch/powerpc/include/asm/livepatch.h b/arch/powerpc/include/asm/livepatch.h index e83f0cc7b267..3d2d9f608dbe 100644 --- a/arch/powerpc/include/asm/livepatch.h +++ b/arch/powerpc/include/asm/livepatch.h @@ -96,6 +96,7 @@ int klp_patch_text(u32 *dst, const u32 *src, int len); int klp_brk_handler(struct pt_regs *regs); int arch_klp_add_breakpoint(struct arch_klp_data *arch_data, void *old_func); void arch_klp_remove_breakpoint(struct arch_klp_data *arch_data, void *old_func); +int arch_klp_module_check_calltrace(void *data);
#endif /* CONFIG_LIVEPATCH_WO_FTRACE */
diff --git a/arch/powerpc/kernel/livepatch.c b/arch/powerpc/kernel/livepatch.c index c1f6c200d711..7511a09a75d3 100644 --- a/arch/powerpc/kernel/livepatch.c +++ b/arch/powerpc/kernel/livepatch.c @@ -261,6 +261,39 @@ int arch_klp_check_calltrace(bool (*check_func)(void *, int *, unsigned long), v return do_check_calltrace(&args, klp_check_jump_func); }
+static int klp_check_module_calltrace(struct stackframe *frame, void *ws_args) +{ + struct walk_stackframe_args *args = ws_args; + struct module *mod = args->data; + + /* check NIP when the exception stack switching */ + if (frame->nip && within_module_core(frame->nip, mod)) + goto err_out; + if (frame->link && !frame->nip_link_in_same_func && + within_module_core(frame->link, mod)) + goto err_out; + if (!frame->is_top_frame || frame->nip_link_in_same_func) { + if (within_module_core(frame->pc, mod)) + goto err_out; + } + + return 0; + +err_out: + pr_err("module %s is in use!\n", mod->name); + return (args->ret = -EBUSY); +} + +int arch_klp_module_check_calltrace(void *data) +{ + struct walk_stackframe_args args = { + .data = data, + .ret = 0 + }; + + return do_check_calltrace(&args, klp_check_module_calltrace); +} + int klp_patch_text(u32 *dst, const u32 *src, int len) { int i;