signal32.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 <asm/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((short)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 (from->si_code >> 16) {
  85. case __SI_TIMER >> 16:
  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 __SI_CHLD >> 16:
  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. default:
  95. err |= __put_user(from->si_pid, &to->si_pid);
  96. err |= __put_user(from->si_uid, &to->si_uid);
  97. break;
  98. case __SI_FAULT >> 16:
  99. err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
  100. break;
  101. case __SI_POLL >> 16:
  102. err |= __put_user(from->si_band, &to->si_band);
  103. err |= __put_user(from->si_fd, &to->si_fd);
  104. break;
  105. case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
  106. case __SI_MESGQ >> 16:
  107. err |= __put_user(from->si_pid, &to->si_pid);
  108. err |= __put_user(from->si_uid, &to->si_uid);
  109. err |= __put_user(from->si_int, &to->si_int);
  110. break;
  111. case __SI_SYS >> 16:
  112. err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
  113. sizeof(compat_uptr_t));
  114. err |= __put_user(from->si_syscall, &to->si_syscall);
  115. err |= __put_user(from->si_arch, &to->si_arch);
  116. break;
  117. }
  118. }
  119. return err;
  120. }
  121. int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
  122. {
  123. if (copy_from_user(to, from, 3*sizeof(int)) ||
  124. copy_from_user(to->_sifields._pad,
  125. from->_sifields._pad, SI_PAD_SIZE32))
  126. return -EFAULT;
  127. return 0;
  128. }