From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> The u64ilp32 reuses compat mode on the 64-bit Linux kernel, but the signal context is the same as the native 64-bit, not u32ilp32. So use the native signal procedure for u64ilp32 applications. Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> Signed-off-by: Guo Ren <guoren@xxxxxxxxxx> --- arch/riscv/include/asm/signal32.h | 9 ++++++ arch/riscv/kernel/compat_signal.c | 21 ++++-------- arch/riscv/kernel/signal.c | 53 ++++++++++++++++++++++--------- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/arch/riscv/include/asm/signal32.h b/arch/riscv/include/asm/signal32.h index 96dc56932e76..cda62d7eb0a5 100644 --- a/arch/riscv/include/asm/signal32.h +++ b/arch/riscv/include/asm/signal32.h @@ -6,6 +6,7 @@ #if IS_ENABLED(CONFIG_COMPAT) int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs); +long __riscv_compat_rt_sigreturn(void); #else static inline int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set, @@ -13,6 +14,14 @@ int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set, { return -1; } + +static inline +long __riscv_compat_rt_sigreturn(void) +{ + return -1; +} #endif +void __riscv_rt_sigreturn_badframe(void); + #endif diff --git a/arch/riscv/kernel/compat_signal.c b/arch/riscv/kernel/compat_signal.c index 8dea2012836e..955a638da2a4 100644 --- a/arch/riscv/kernel/compat_signal.c +++ b/arch/riscv/kernel/compat_signal.c @@ -116,18 +116,16 @@ static long compat_restore_sigcontext(struct pt_regs *regs, return err; } -COMPAT_SYSCALL_DEFINE0(rt_sigreturn) +long __riscv_compat_rt_sigreturn(void) { - struct pt_regs *regs = current_pt_regs(); - struct compat_rt_sigframe __user *frame; - struct task_struct *task; sigset_t set; + struct pt_regs *regs = current_pt_regs(); + struct compat_rt_sigframe __user *frame = + (struct compat_rt_sigframe __user *)kernel_stack_pointer(regs); /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; - frame = (struct compat_rt_sigframe __user *)regs->sp; - if (!access_ok(frame, sizeof(*frame))) goto badframe; @@ -142,17 +140,12 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn) if (compat_restore_altstack(&frame->uc.uc_stack)) goto badframe; + regs->cause = -1UL; + return regs->a0; badframe: - task = current; - if (show_unhandled_signals) { - pr_info_ratelimited( - "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n", - task->comm, task_pid_nr(task), __func__, - frame, (void *)regs->epc, (void *)regs->sp); - } - force_sig(SIGSEGV); + __riscv_rt_sigreturn_badframe(); return 0; } diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 95c4a8d8a3f5..1c51a6783c98 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -224,19 +224,34 @@ static size_t get_rt_frame_size(bool cal_all) return frame_size; } -SYSCALL_DEFINE0(rt_sigreturn) +void __riscv_rt_sigreturn_badframe(void) +{ + struct task_struct *task = current; + struct pt_regs *regs = task_pt_regs(task); + + if (show_unhandled_signals) { + pr_info_ratelimited( + "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n", + task->comm, task_pid_nr(task), __func__, + (void *)kernel_stack_pointer(regs), + (void *)instruction_pointer(regs), + (void *)kernel_stack_pointer(regs)); + } + + force_sig(SIGSEGV); +} + +static long __riscv_rt_sigreturn(void) { - struct pt_regs *regs = current_pt_regs(); - struct rt_sigframe __user *frame; - struct task_struct *task; sigset_t set; size_t frame_size = get_rt_frame_size(false); + struct pt_regs *regs = current_pt_regs(); + struct rt_sigframe __user *frame = + (struct rt_sigframe __user *)kernel_stack_pointer(regs); /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; - frame = (struct rt_sigframe __user *)regs->sp; - if (!access_ok(frame, frame_size)) goto badframe; @@ -256,17 +271,25 @@ SYSCALL_DEFINE0(rt_sigreturn) return regs->a0; badframe: - task = current; - if (show_unhandled_signals) { - pr_info_ratelimited( - "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n", - task->comm, task_pid_nr(task), __func__, - frame, (void *)regs->epc, (void *)regs->sp); - } - force_sig(SIGSEGV); + __riscv_rt_sigreturn_badframe(); return 0; } +SYSCALL_DEFINE0(rt_sigreturn) +{ + return __riscv_rt_sigreturn(); +} + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE0(rt_sigreturn) +{ + if (test_thread_flag(TIF_32BIT) && !test_thread_flag(TIF_64ILP32)) + return __riscv_compat_rt_sigreturn(); + else + return __riscv_rt_sigreturn(); +} +#endif + static long setup_sigcontext(struct rt_sigframe __user *frame, struct pt_regs *regs) { @@ -433,7 +456,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) rseq_signal_deliver(ksig, regs); /* Set up the stack frame */ - if (is_compat_task()) + if (test_thread_flag(TIF_32BIT) && !test_thread_flag(TIF_64ILP32)) ret = compat_setup_rt_frame(ksig, oldset, regs); else ret = setup_rt_frame(ksig, oldset, regs); -- 2.36.1