From 7d9b185c8e1ac5b9925cfecc1cf14db96d994b04 Mon Sep 17 00:00:00 2001 From: Zou Cao Date: Fri, 6 Mar 2020 10:54:54 +0800 Subject: [PATCH] alinux: arm64: add livepatch support Now we support FTRACE_WITH_REGS with -fpatchable-function-entry, here enable the livepatch support depend on FTRACE_WITH_REGS. Use task flag bit 6 to track patch transisiton state for the consistency model. Add it to the work mask so it gets cleared on all kernel exits to userland. Tell livepatch regs->pc + 2*AARCH64_INSN_SIZE is the place to change the return address. these codes have a big change against reference link, beacause we use new gcc featrue. References: https://patchwork.kernel.org/patch/10657431/ Based-on-code-from: Torsten Duwe Signed-off-by: Zou Cao Acked-by: Caspar Zhang --- arch/arm64/Kconfig | 3 ++ arch/arm64/include/asm/livepatch.h | 47 ++++++++++++++++++++++++++++ arch/arm64/include/asm/thread_info.h | 6 +++- arch/arm64/kernel/signal.c | 4 +++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/include/asm/livepatch.h diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 484e958e6cda..ddea6e67c3ed 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -170,6 +170,7 @@ config ARM64 select SWIOTLB select SYSCTL_EXCEPTION_TRACE select THREAD_INFO_IN_TASK + select HAVE_LIVEPATCH help ARM 64-bit (AArch64) Linux support. @@ -1359,6 +1360,8 @@ source "drivers/acpi/Kconfig" source "arch/arm64/kvm/Kconfig" +source "kernel/livepatch/Kconfig" + if CRYPTO source "arch/arm64/crypto/Kconfig" endif diff --git a/arch/arm64/include/asm/livepatch.h b/arch/arm64/include/asm/livepatch.h new file mode 100644 index 000000000000..c6fa43db198a --- /dev/null +++ b/arch/arm64/include/asm/livepatch.h @@ -0,0 +1,47 @@ +#ifndef _ASM_ARM64_LIVEPATCH_H +#define _ASM_ARM64_LIVEPATCH_H + +#include +#include + +#ifdef CONFIG_LIVEPATCH + +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +static inline int klp_check_compiler_support(void) +{ + return 0; +} + +static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long pc) +{ + regs->pc = pc + 2*AARCH64_INSN_SIZE; +} + +#define klp_get_ftrace_location klp_get_ftrace_location +static inline unsigned long klp_get_ftrace_location(unsigned long faddr) +{ + return faddr + AARCH64_INSN_SIZE; +} + +#else +static inline int klp_check_compiler_support(void) +{ + return 1; +} + +static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long pc) +{ +} + +#define klp_get_ftrace_location klp_get_ftrace_location +static inline unsigned long klp_get_ftrace_location(unsigned long faddr) +{ + return faddr + AARCH64_INSN_SIZE; +} +#endif + +#else +#error Live patching support is disabled; check CONFIG_LIVEPATCH +#endif + +#endif /* _ASM_ARM64_LIVEPATCH_H */ diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index cb2c10a8f0a8..2ecfe7a6c0a6 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -76,6 +76,7 @@ void arch_release_task_struct(struct task_struct *tsk); #define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */ #define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */ #define TIF_FSCHECK 5 /* Check FS is USER_DS on return */ +#define TIF_PATCH_PENDING 6 #define TIF_NOHZ 7 #define TIF_SYSCALL_TRACE 8 #define TIF_SYSCALL_AUDIT 9 @@ -94,6 +95,7 @@ void arch_release_task_struct(struct task_struct *tsk); #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_FOREIGN_FPSTATE (1 << TIF_FOREIGN_FPSTATE) +#define _TIF_PATCH_PENDING (1 << TIF_PATCH_PENDING) #define _TIF_NOHZ (1 << TIF_NOHZ) #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) @@ -106,7 +108,9 @@ void arch_release_task_struct(struct task_struct *tsk); #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \ - _TIF_UPROBE | _TIF_FSCHECK) + _TIF_UPROBE | _TIF_FSCHECK | \ + _TIF_PATCH_PENDING) + #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \ diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 5dcc942906db..c807406f0bad 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -937,6 +938,9 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, if (thread_flags & _TIF_UPROBE) uprobe_notify_resume(regs); + if (thread_flags & _TIF_PATCH_PENDING) + klp_update_patch_state(current); + if (thread_flags & _TIF_SIGPENDING) do_signal(regs); -- GitLab