17383ee05SGuo Ren // SPDX-License-Identifier: GPL-2.0-or-later
27383ee05SGuo Ren
37383ee05SGuo Ren #include <linux/compat.h>
47383ee05SGuo Ren #include <linux/signal.h>
57383ee05SGuo Ren #include <linux/uaccess.h>
67383ee05SGuo Ren #include <linux/syscalls.h>
77383ee05SGuo Ren #include <linux/linkage.h>
87383ee05SGuo Ren
97383ee05SGuo Ren #include <asm/csr.h>
107383ee05SGuo Ren #include <asm/signal32.h>
117383ee05SGuo Ren #include <asm/switch_to.h>
127383ee05SGuo Ren #include <asm/ucontext.h>
137383ee05SGuo Ren #include <asm/vdso.h>
147383ee05SGuo Ren
157383ee05SGuo Ren #define COMPAT_DEBUG_SIG 0
167383ee05SGuo Ren
177383ee05SGuo Ren struct compat_sigcontext {
187383ee05SGuo Ren struct compat_user_regs_struct sc_regs;
197383ee05SGuo Ren union __riscv_fp_state sc_fpregs;
207383ee05SGuo Ren };
217383ee05SGuo Ren
227383ee05SGuo Ren struct compat_ucontext {
237383ee05SGuo Ren compat_ulong_t uc_flags;
247383ee05SGuo Ren struct compat_ucontext *uc_link;
257383ee05SGuo Ren compat_stack_t uc_stack;
267383ee05SGuo Ren sigset_t uc_sigmask;
277383ee05SGuo Ren /* There's some padding here to allow sigset_t to be expanded in the
287383ee05SGuo Ren * future. Though this is unlikely, other architectures put uc_sigmask
297383ee05SGuo Ren * at the end of this structure and explicitly state it can be
307383ee05SGuo Ren * expanded, so we didn't want to box ourselves in here. */
317383ee05SGuo Ren __u8 __unused[1024 / 8 - sizeof(sigset_t)];
327383ee05SGuo Ren /* We can't put uc_sigmask at the end of this structure because we need
337383ee05SGuo Ren * to be able to expand sigcontext in the future. For example, the
347383ee05SGuo Ren * vector ISA extension will almost certainly add ISA state. We want
357383ee05SGuo Ren * to ensure all user-visible ISA state can be saved and restored via a
367383ee05SGuo Ren * ucontext, so we're putting this at the end in order to allow for
377383ee05SGuo Ren * infinite extensibility. Since we know this will be extended and we
387383ee05SGuo Ren * assume sigset_t won't be extended an extreme amount, we're
397383ee05SGuo Ren * prioritizing this. */
407383ee05SGuo Ren struct compat_sigcontext uc_mcontext;
417383ee05SGuo Ren };
427383ee05SGuo Ren
437383ee05SGuo Ren struct compat_rt_sigframe {
447383ee05SGuo Ren struct compat_siginfo info;
457383ee05SGuo Ren struct compat_ucontext uc;
467383ee05SGuo Ren };
477383ee05SGuo Ren
487383ee05SGuo Ren #ifdef CONFIG_FPU
compat_restore_fp_state(struct pt_regs * regs,union __riscv_fp_state __user * sc_fpregs)497383ee05SGuo Ren static long compat_restore_fp_state(struct pt_regs *regs,
507383ee05SGuo Ren union __riscv_fp_state __user *sc_fpregs)
517383ee05SGuo Ren {
527383ee05SGuo Ren long err;
537383ee05SGuo Ren struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
547383ee05SGuo Ren size_t i;
557383ee05SGuo Ren
567383ee05SGuo Ren err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state));
577383ee05SGuo Ren if (unlikely(err))
587383ee05SGuo Ren return err;
597383ee05SGuo Ren
607383ee05SGuo Ren fstate_restore(current, regs);
617383ee05SGuo Ren
627383ee05SGuo Ren /* We support no other extension state at this time. */
637383ee05SGuo Ren for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
647383ee05SGuo Ren u32 value;
657383ee05SGuo Ren
667383ee05SGuo Ren err = __get_user(value, &sc_fpregs->q.reserved[i]);
677383ee05SGuo Ren if (unlikely(err))
687383ee05SGuo Ren break;
697383ee05SGuo Ren if (value != 0)
707383ee05SGuo Ren return -EINVAL;
717383ee05SGuo Ren }
727383ee05SGuo Ren
737383ee05SGuo Ren return err;
747383ee05SGuo Ren }
757383ee05SGuo Ren
compat_save_fp_state(struct pt_regs * regs,union __riscv_fp_state __user * sc_fpregs)767383ee05SGuo Ren static long compat_save_fp_state(struct pt_regs *regs,
777383ee05SGuo Ren union __riscv_fp_state __user *sc_fpregs)
787383ee05SGuo Ren {
797383ee05SGuo Ren long err;
807383ee05SGuo Ren struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
817383ee05SGuo Ren size_t i;
827383ee05SGuo Ren
837383ee05SGuo Ren fstate_save(current, regs);
847383ee05SGuo Ren err = __copy_to_user(state, ¤t->thread.fstate, sizeof(*state));
857383ee05SGuo Ren if (unlikely(err))
867383ee05SGuo Ren return err;
877383ee05SGuo Ren
887383ee05SGuo Ren /* We support no other extension state at this time. */
897383ee05SGuo Ren for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
907383ee05SGuo Ren err = __put_user(0, &sc_fpregs->q.reserved[i]);
917383ee05SGuo Ren if (unlikely(err))
927383ee05SGuo Ren break;
937383ee05SGuo Ren }
947383ee05SGuo Ren
957383ee05SGuo Ren return err;
967383ee05SGuo Ren }
977383ee05SGuo Ren #else
987383ee05SGuo Ren #define compat_save_fp_state(task, regs) (0)
997383ee05SGuo Ren #define compat_restore_fp_state(task, regs) (0)
1007383ee05SGuo Ren #endif
1017383ee05SGuo Ren
compat_restore_sigcontext(struct pt_regs * regs,struct compat_sigcontext __user * sc)1027383ee05SGuo Ren static long compat_restore_sigcontext(struct pt_regs *regs,
1037383ee05SGuo Ren struct compat_sigcontext __user *sc)
1047383ee05SGuo Ren {
1057383ee05SGuo Ren long err;
1067383ee05SGuo Ren struct compat_user_regs_struct cregs;
1077383ee05SGuo Ren
1087383ee05SGuo Ren /* sc_regs is structured the same as the start of pt_regs */
1097383ee05SGuo Ren err = __copy_from_user(&cregs, &sc->sc_regs, sizeof(sc->sc_regs));
1107383ee05SGuo Ren
1117383ee05SGuo Ren cregs_to_regs(&cregs, regs);
1127383ee05SGuo Ren
1137383ee05SGuo Ren /* Restore the floating-point state. */
1147383ee05SGuo Ren if (has_fpu())
1157383ee05SGuo Ren err |= compat_restore_fp_state(regs, &sc->sc_fpregs);
1167383ee05SGuo Ren return err;
1177383ee05SGuo Ren }
1187383ee05SGuo Ren
COMPAT_SYSCALL_DEFINE0(rt_sigreturn)1197383ee05SGuo Ren COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
1207383ee05SGuo Ren {
1217383ee05SGuo Ren struct pt_regs *regs = current_pt_regs();
1227383ee05SGuo Ren struct compat_rt_sigframe __user *frame;
1237383ee05SGuo Ren struct task_struct *task;
1247383ee05SGuo Ren sigset_t set;
1257383ee05SGuo Ren
1267383ee05SGuo Ren /* Always make any pending restarted system calls return -EINTR */
1277383ee05SGuo Ren current->restart_block.fn = do_no_restart_syscall;
1287383ee05SGuo Ren
1297383ee05SGuo Ren frame = (struct compat_rt_sigframe __user *)regs->sp;
1307383ee05SGuo Ren
1317383ee05SGuo Ren if (!access_ok(frame, sizeof(*frame)))
1327383ee05SGuo Ren goto badframe;
1337383ee05SGuo Ren
1347383ee05SGuo Ren if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
1357383ee05SGuo Ren goto badframe;
1367383ee05SGuo Ren
1377383ee05SGuo Ren set_current_blocked(&set);
1387383ee05SGuo Ren
1397383ee05SGuo Ren if (compat_restore_sigcontext(regs, &frame->uc.uc_mcontext))
1407383ee05SGuo Ren goto badframe;
1417383ee05SGuo Ren
1427383ee05SGuo Ren if (compat_restore_altstack(&frame->uc.uc_stack))
1437383ee05SGuo Ren goto badframe;
1447383ee05SGuo Ren
1457383ee05SGuo Ren return regs->a0;
1467383ee05SGuo Ren
1477383ee05SGuo Ren badframe:
1487383ee05SGuo Ren task = current;
1497383ee05SGuo Ren if (show_unhandled_signals) {
1507383ee05SGuo Ren pr_info_ratelimited(
1517383ee05SGuo Ren "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
1527383ee05SGuo Ren task->comm, task_pid_nr(task), __func__,
1537383ee05SGuo Ren frame, (void *)regs->epc, (void *)regs->sp);
1547383ee05SGuo Ren }
1557383ee05SGuo Ren force_sig(SIGSEGV);
1567383ee05SGuo Ren return 0;
1577383ee05SGuo Ren }
1587383ee05SGuo Ren
compat_setup_sigcontext(struct compat_rt_sigframe __user * frame,struct pt_regs * regs)1597383ee05SGuo Ren static long compat_setup_sigcontext(struct compat_rt_sigframe __user *frame,
1607383ee05SGuo Ren struct pt_regs *regs)
1617383ee05SGuo Ren {
1627383ee05SGuo Ren struct compat_sigcontext __user *sc = &frame->uc.uc_mcontext;
1637383ee05SGuo Ren struct compat_user_regs_struct cregs;
1647383ee05SGuo Ren long err;
1657383ee05SGuo Ren
1667383ee05SGuo Ren regs_to_cregs(&cregs, regs);
1677383ee05SGuo Ren
1687383ee05SGuo Ren /* sc_regs is structured the same as the start of pt_regs */
1697383ee05SGuo Ren err = __copy_to_user(&sc->sc_regs, &cregs, sizeof(sc->sc_regs));
1707383ee05SGuo Ren /* Save the floating-point state. */
1717383ee05SGuo Ren if (has_fpu())
1727383ee05SGuo Ren err |= compat_save_fp_state(regs, &sc->sc_fpregs);
1737383ee05SGuo Ren return err;
1747383ee05SGuo Ren }
1757383ee05SGuo Ren
compat_get_sigframe(struct ksignal * ksig,struct pt_regs * regs,size_t framesize)1767383ee05SGuo Ren static inline void __user *compat_get_sigframe(struct ksignal *ksig,
1777383ee05SGuo Ren struct pt_regs *regs, size_t framesize)
1787383ee05SGuo Ren {
1797383ee05SGuo Ren unsigned long sp;
1807383ee05SGuo Ren /* Default to using normal stack */
1817383ee05SGuo Ren sp = regs->sp;
1827383ee05SGuo Ren
1837383ee05SGuo Ren /*
1847383ee05SGuo Ren * If we are on the alternate signal stack and would overflow it, don't.
1857383ee05SGuo Ren * Return an always-bogus address instead so we will die with SIGSEGV.
1867383ee05SGuo Ren */
1877383ee05SGuo Ren if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
1887383ee05SGuo Ren return (void __user __force *)(-1UL);
1897383ee05SGuo Ren
1907383ee05SGuo Ren /* This is the X/Open sanctioned signal stack switching. */
1917383ee05SGuo Ren sp = sigsp(sp, ksig) - framesize;
1927383ee05SGuo Ren
1937383ee05SGuo Ren /* Align the stack frame. */
1947383ee05SGuo Ren sp &= ~0xfUL;
1957383ee05SGuo Ren
1967383ee05SGuo Ren return (void __user *)sp;
1977383ee05SGuo Ren }
1987383ee05SGuo Ren
compat_setup_rt_frame(struct ksignal * ksig,sigset_t * set,struct pt_regs * regs)1997383ee05SGuo Ren int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
2007383ee05SGuo Ren struct pt_regs *regs)
2017383ee05SGuo Ren {
2027383ee05SGuo Ren struct compat_rt_sigframe __user *frame;
2037383ee05SGuo Ren long err = 0;
2047383ee05SGuo Ren
2057383ee05SGuo Ren frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
2067383ee05SGuo Ren if (!access_ok(frame, sizeof(*frame)))
2077383ee05SGuo Ren return -EFAULT;
2087383ee05SGuo Ren
2097383ee05SGuo Ren err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
2107383ee05SGuo Ren
2117383ee05SGuo Ren /* Create the ucontext. */
2127383ee05SGuo Ren err |= __put_user(0, &frame->uc.uc_flags);
2137383ee05SGuo Ren err |= __put_user(NULL, &frame->uc.uc_link);
2147383ee05SGuo Ren err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
2157383ee05SGuo Ren err |= compat_setup_sigcontext(frame, regs);
2167383ee05SGuo Ren err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
2177383ee05SGuo Ren if (err)
2187383ee05SGuo Ren return -EFAULT;
2197383ee05SGuo Ren
2207383ee05SGuo Ren regs->ra = (unsigned long)COMPAT_VDSO_SYMBOL(
2217383ee05SGuo Ren current->mm->context.vdso, rt_sigreturn);
2227383ee05SGuo Ren
2237383ee05SGuo Ren /*
2247383ee05SGuo Ren * Set up registers for signal handler.
2257383ee05SGuo Ren * Registers that we don't modify keep the value they had from
2267383ee05SGuo Ren * user-space at the time we took the signal.
2277383ee05SGuo Ren * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
2287383ee05SGuo Ren * since some things rely on this (e.g. glibc's debug/segfault.c).
2297383ee05SGuo Ren */
2307383ee05SGuo Ren regs->epc = (unsigned long)ksig->ka.sa.sa_handler;
2317383ee05SGuo Ren regs->sp = (unsigned long)frame;
2327383ee05SGuo Ren regs->a0 = ksig->sig; /* a0: signal number */
2337383ee05SGuo Ren regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
2347383ee05SGuo Ren regs->a2 = (unsigned long)(&frame->uc); /* a2: ucontext pointer */
2357383ee05SGuo Ren
2367383ee05SGuo Ren #if COMPAT_DEBUG_SIG
2377383ee05SGuo Ren pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
2387383ee05SGuo Ren current->comm, task_pid_nr(current), ksig->sig,
2397383ee05SGuo Ren (void *)regs->epc, (void *)regs->ra, frame);
2407383ee05SGuo Ren #endif
2417383ee05SGuo Ren
2427383ee05SGuo Ren return 0;
2437383ee05SGuo Ren }
244