signal32.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 1991, 1992 Linus Torvalds
  7. * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
  8. * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  9. * Copyright (C) 2016, Imagination Technologies Ltd.
  10. */
  11. #include <linux/compiler.h>
  12. #include <linux/errno.h>
  13. #include <linux/kernel.h>
  14. #include <linux/signal.h>
  15. #include <linux/syscalls.h>
  16. #include <asm/compat.h>
  17. #include <asm/compat-signal.h>
  18. #include <linux/uaccess.h>
  19. #include <asm/unistd.h>
  20. #include "signal-common.h"
  21. /* 32-bit compatibility types */
  22. typedef unsigned int __sighandler32_t;
  23. typedef void (*vfptr_t)(void);
  24. /*
  25. * Atomically swap in the new signal mask, and wait for a signal.
  26. */
  27. asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
  28. {
  29. return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
  30. }
  31. SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
  32. struct compat_sigaction __user *, oact)
  33. {
  34. struct k_sigaction new_ka, old_ka;
  35. int ret;
  36. int err = 0;
  37. if (act) {
  38. old_sigset_t mask;
  39. s32 handler;
  40. if (!access_ok(VERIFY_READ, act, sizeof(*act)))
  41. return -EFAULT;
  42. err |= __get_user(handler, &act->sa_handler);
  43. new_ka.sa.sa_handler = (void __user *)(s64)handler;
  44. err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
  45. err |= __get_user(mask, &act->sa_mask.sig[0]);
  46. if (err)
  47. return -EFAULT;
  48. siginitset(&new_ka.sa.sa_mask, mask);
  49. }
  50. ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
  51. if (!ret && oact) {
  52. if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
  53. return -EFAULT;
  54. err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
  55. err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
  56. &oact->sa_handler);
  57. err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
  58. err |= __put_user(0, &oact->sa_mask.sig[1]);
  59. err |= __put_user(0, &oact->sa_mask.sig[2]);
  60. err |= __put_user(0, &oact->sa_mask.sig[3]);
  61. if (err)
  62. return -EFAULT;
  63. }
  64. return ret;
  65. }
  66. int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
  67. {
  68. int err;
  69. if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
  70. return -EFAULT;
  71. /* If you change siginfo_t structure, please be sure
  72. this code is fixed accordingly.
  73. It should never copy any pad contained in the structure
  74. to avoid security leaks, but must copy the generic
  75. 3 ints plus the relevant union member.
  76. This routine must convert siginfo from 64bit to 32bit as well
  77. at the same time. */
  78. err = __put_user(from->si_signo, &to->si_signo);
  79. err |= __put_user(from->si_errno, &to->si_errno);
  80. err |= __put_user(from->si_code, &to->si_code);
  81. if (from->si_code < 0)
  82. err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
  83. else {
  84. switch (siginfo_layout(from->si_signo, from->si_code)) {
  85. case SIL_TIMER:
  86. err |= __put_user(from->si_tid, &to->si_tid);
  87. err |= __put_user(from->si_overrun, &to->si_overrun);
  88. err |= __put_user(from->si_int, &to->si_int);
  89. break;
  90. case SIL_CHLD:
  91. err |= __put_user(from->si_utime, &to->si_utime);
  92. err |= __put_user(from->si_stime, &to->si_stime);
  93. err |= __put_user(from->si_status, &to->si_status);
  94. case SIL_KILL:
  95. err |= __put_user(from->si_pid, &to->si_pid);
  96. err |= __put_user(from->si_uid, &to->si_uid);
  97. break;
  98. case SIL_FAULT:
  99. err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
  100. break;
  101. case SIL_POLL:
  102. err |= __put_user(from->si_band, &to->si_band);
  103. err |= __put_user(from->si_fd, &to->si_fd);
  104. break;
  105. case SIL_RT:
  106. err |= __put_user(from->si_pid, &to->si_pid);
  107. err |= __put_user(from->si_uid, &to->si_uid);
  108. err |= __put_user(from->si_int, &to->si_int);
  109. break;
  110. case SIL_SYS:
  111. err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
  112. sizeof(compat_uptr_t));
  113. err |= __put_user(from->si_syscall, &to->si_syscall);
  114. err |= __put_user(from->si_arch, &to->si_arch);
  115. break;
  116. }
  117. }
  118. return err;
  119. }
  120. int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
  121. {
  122. if (copy_from_user(to, from, 3*sizeof(int)) ||
  123. copy_from_user(to->_sifields._pad,
  124. from->_sifields._pad, SI_PAD_SIZE32))
  125. return -EFAULT;
  126. return 0;
  127. }