compat_signal.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include <linux/compat.h>
  3. #include <linux/signal.h>
  4. #include <linux/uaccess.h>
  5. #include <linux/syscalls.h>
  6. #include <linux/linkage.h>
  7. #include <asm/csr.h>
  8. #include <asm/signal32.h>
  9. #include <asm/switch_to.h>
  10. #include <asm/ucontext.h>
  11. #include <asm/vdso.h>
  12. #define COMPAT_DEBUG_SIG 0
  13. struct compat_sigcontext {
  14. struct compat_user_regs_struct sc_regs;
  15. union __riscv_fp_state sc_fpregs;
  16. };
  17. struct compat_ucontext {
  18. compat_ulong_t uc_flags;
  19. struct compat_ucontext *uc_link;
  20. compat_stack_t uc_stack;
  21. sigset_t uc_sigmask;
  22. /* There's some padding here to allow sigset_t to be expanded in the
  23. * future. Though this is unlikely, other architectures put uc_sigmask
  24. * at the end of this structure and explicitly state it can be
  25. * expanded, so we didn't want to box ourselves in here. */
  26. __u8 __unused[1024 / 8 - sizeof(sigset_t)];
  27. /* We can't put uc_sigmask at the end of this structure because we need
  28. * to be able to expand sigcontext in the future. For example, the
  29. * vector ISA extension will almost certainly add ISA state. We want
  30. * to ensure all user-visible ISA state can be saved and restored via a
  31. * ucontext, so we're putting this at the end in order to allow for
  32. * infinite extensibility. Since we know this will be extended and we
  33. * assume sigset_t won't be extended an extreme amount, we're
  34. * prioritizing this. */
  35. struct compat_sigcontext uc_mcontext;
  36. };
  37. struct compat_rt_sigframe {
  38. struct compat_siginfo info;
  39. struct compat_ucontext uc;
  40. };
  41. #ifdef CONFIG_FPU
  42. static long compat_restore_fp_state(struct pt_regs *regs,
  43. union __riscv_fp_state __user *sc_fpregs)
  44. {
  45. long err;
  46. struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
  47. size_t i;
  48. err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
  49. if (unlikely(err))
  50. return err;
  51. fstate_restore(current, regs);
  52. /* We support no other extension state at this time. */
  53. for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
  54. u32 value;
  55. err = __get_user(value, &sc_fpregs->q.reserved[i]);
  56. if (unlikely(err))
  57. break;
  58. if (value != 0)
  59. return -EINVAL;
  60. }
  61. return err;
  62. }
  63. static long compat_save_fp_state(struct pt_regs *regs,
  64. union __riscv_fp_state __user *sc_fpregs)
  65. {
  66. long err;
  67. struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
  68. size_t i;
  69. fstate_save(current, regs);
  70. err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
  71. if (unlikely(err))
  72. return err;
  73. /* We support no other extension state at this time. */
  74. for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
  75. err = __put_user(0, &sc_fpregs->q.reserved[i]);
  76. if (unlikely(err))
  77. break;
  78. }
  79. return err;
  80. }
  81. #else
  82. #define compat_save_fp_state(task, regs) (0)
  83. #define compat_restore_fp_state(task, regs) (0)
  84. #endif
  85. static long compat_restore_sigcontext(struct pt_regs *regs,
  86. struct compat_sigcontext __user *sc)
  87. {
  88. long err;
  89. struct compat_user_regs_struct cregs;
  90. /* sc_regs is structured the same as the start of pt_regs */
  91. err = __copy_from_user(&cregs, &sc->sc_regs, sizeof(sc->sc_regs));
  92. cregs_to_regs(&cregs, regs);
  93. /* Restore the floating-point state. */
  94. if (has_fpu())
  95. err |= compat_restore_fp_state(regs, &sc->sc_fpregs);
  96. return err;
  97. }
  98. COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
  99. {
  100. struct pt_regs *regs = current_pt_regs();
  101. struct compat_rt_sigframe __user *frame;
  102. struct task_struct *task;
  103. sigset_t set;
  104. /* Always make any pending restarted system calls return -EINTR */
  105. current->restart_block.fn = do_no_restart_syscall;
  106. frame = (struct compat_rt_sigframe __user *)regs->sp;
  107. if (!access_ok(frame, sizeof(*frame)))
  108. goto badframe;
  109. if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
  110. goto badframe;
  111. set_current_blocked(&set);
  112. if (compat_restore_sigcontext(regs, &frame->uc.uc_mcontext))
  113. goto badframe;
  114. if (compat_restore_altstack(&frame->uc.uc_stack))
  115. goto badframe;
  116. return regs->a0;
  117. badframe:
  118. task = current;
  119. if (show_unhandled_signals) {
  120. pr_info_ratelimited(
  121. "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
  122. task->comm, task_pid_nr(task), __func__,
  123. frame, (void *)regs->epc, (void *)regs->sp);
  124. }
  125. force_sig(SIGSEGV);
  126. return 0;
  127. }
  128. static long compat_setup_sigcontext(struct compat_rt_sigframe __user *frame,
  129. struct pt_regs *regs)
  130. {
  131. struct compat_sigcontext __user *sc = &frame->uc.uc_mcontext;
  132. struct compat_user_regs_struct cregs;
  133. long err;
  134. regs_to_cregs(&cregs, regs);
  135. /* sc_regs is structured the same as the start of pt_regs */
  136. err = __copy_to_user(&sc->sc_regs, &cregs, sizeof(sc->sc_regs));
  137. /* Save the floating-point state. */
  138. if (has_fpu())
  139. err |= compat_save_fp_state(regs, &sc->sc_fpregs);
  140. return err;
  141. }
  142. static inline void __user *compat_get_sigframe(struct ksignal *ksig,
  143. struct pt_regs *regs, size_t framesize)
  144. {
  145. unsigned long sp;
  146. /* Default to using normal stack */
  147. sp = regs->sp;
  148. /*
  149. * If we are on the alternate signal stack and would overflow it, don't.
  150. * Return an always-bogus address instead so we will die with SIGSEGV.
  151. */
  152. if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
  153. return (void __user __force *)(-1UL);
  154. /* This is the X/Open sanctioned signal stack switching. */
  155. sp = sigsp(sp, ksig) - framesize;
  156. /* Align the stack frame. */
  157. sp &= ~0xfUL;
  158. return (void __user *)sp;
  159. }
  160. int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
  161. struct pt_regs *regs)
  162. {
  163. struct compat_rt_sigframe __user *frame;
  164. long err = 0;
  165. frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
  166. if (!access_ok(frame, sizeof(*frame)))
  167. return -EFAULT;
  168. err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
  169. /* Create the ucontext. */
  170. err |= __put_user(0, &frame->uc.uc_flags);
  171. err |= __put_user(NULL, &frame->uc.uc_link);
  172. err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
  173. err |= compat_setup_sigcontext(frame, regs);
  174. err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
  175. if (err)
  176. return -EFAULT;
  177. regs->ra = (unsigned long)COMPAT_VDSO_SYMBOL(
  178. current->mm->context.vdso, rt_sigreturn);
  179. /*
  180. * Set up registers for signal handler.
  181. * Registers that we don't modify keep the value they had from
  182. * user-space at the time we took the signal.
  183. * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
  184. * since some things rely on this (e.g. glibc's debug/segfault.c).
  185. */
  186. regs->epc = (unsigned long)ksig->ka.sa.sa_handler;
  187. regs->sp = (unsigned long)frame;
  188. regs->a0 = ksig->sig; /* a0: signal number */
  189. regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
  190. regs->a2 = (unsigned long)(&frame->uc); /* a2: ucontext pointer */
  191. #if COMPAT_DEBUG_SIG
  192. pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
  193. current->comm, task_pid_nr(current), ksig->sig,
  194. (void *)regs->epc, (void *)regs->ra, frame);
  195. #endif
  196. return 0;
  197. }