signal_compat.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/compat.h>
  3. #include <linux/uaccess.h>
  4. #include <linux/ptrace.h>
  5. /*
  6. * The compat_siginfo_t structure and handing code is very easy
  7. * to break in several ways. It must always be updated when new
  8. * updates are made to the main siginfo_t, and
  9. * copy_siginfo_to_user32() must be updated when the
  10. * (arch-independent) copy_siginfo_to_user() is updated.
  11. *
  12. * It is also easy to put a new member in the compat_siginfo_t
  13. * which has implicit alignment which can move internal structure
  14. * alignment around breaking the ABI. This can happen if you,
  15. * for instance, put a plain 64-bit value in there.
  16. */
  17. static inline void signal_compat_build_tests(void)
  18. {
  19. int _sifields_offset = offsetof(compat_siginfo_t, _sifields);
  20. /*
  21. * If adding a new si_code, there is probably new data in
  22. * the siginfo. Make sure folks bumping the si_code
  23. * limits also have to look at this code. Make sure any
  24. * new fields are handled in copy_siginfo_to_user32()!
  25. */
  26. BUILD_BUG_ON(NSIGILL != 11);
  27. BUILD_BUG_ON(NSIGFPE != 13);
  28. BUILD_BUG_ON(NSIGSEGV != 4);
  29. BUILD_BUG_ON(NSIGBUS != 5);
  30. BUILD_BUG_ON(NSIGTRAP != 4);
  31. BUILD_BUG_ON(NSIGCHLD != 6);
  32. BUILD_BUG_ON(NSIGSYS != 1);
  33. /* This is part of the ABI and can never change in size: */
  34. BUILD_BUG_ON(sizeof(compat_siginfo_t) != 128);
  35. /*
  36. * The offsets of all the (unioned) si_fields are fixed
  37. * in the ABI, of course. Make sure none of them ever
  38. * move and are always at the beginning:
  39. */
  40. BUILD_BUG_ON(offsetof(compat_siginfo_t, _sifields) != 3 * sizeof(int));
  41. #define CHECK_CSI_OFFSET(name) BUILD_BUG_ON(_sifields_offset != offsetof(compat_siginfo_t, _sifields.name))
  42. /*
  43. * Ensure that the size of each si_field never changes.
  44. * If it does, it is a sign that the
  45. * copy_siginfo_to_user32() code below needs to updated
  46. * along with the size in the CHECK_SI_SIZE().
  47. *
  48. * We repeat this check for both the generic and compat
  49. * siginfos.
  50. *
  51. * Note: it is OK for these to grow as long as the whole
  52. * structure stays within the padding size (checked
  53. * above).
  54. */
  55. #define CHECK_CSI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((compat_siginfo_t *)0)->_sifields.name))
  56. #define CHECK_SI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((siginfo_t *)0)->_sifields.name))
  57. CHECK_CSI_OFFSET(_kill);
  58. CHECK_CSI_SIZE (_kill, 2*sizeof(int));
  59. CHECK_SI_SIZE (_kill, 2*sizeof(int));
  60. CHECK_CSI_OFFSET(_timer);
  61. CHECK_CSI_SIZE (_timer, 3*sizeof(int));
  62. CHECK_SI_SIZE (_timer, 6*sizeof(int));
  63. CHECK_CSI_OFFSET(_rt);
  64. CHECK_CSI_SIZE (_rt, 3*sizeof(int));
  65. CHECK_SI_SIZE (_rt, 4*sizeof(int));
  66. CHECK_CSI_OFFSET(_sigchld);
  67. CHECK_CSI_SIZE (_sigchld, 5*sizeof(int));
  68. CHECK_SI_SIZE (_sigchld, 8*sizeof(int));
  69. #ifdef CONFIG_X86_X32_ABI
  70. CHECK_CSI_OFFSET(_sigchld_x32);
  71. CHECK_CSI_SIZE (_sigchld_x32, 7*sizeof(int));
  72. /* no _sigchld_x32 in the generic siginfo_t */
  73. #endif
  74. CHECK_CSI_OFFSET(_sigfault);
  75. CHECK_CSI_SIZE (_sigfault, 4*sizeof(int));
  76. CHECK_SI_SIZE (_sigfault, 8*sizeof(int));
  77. CHECK_CSI_OFFSET(_sigpoll);
  78. CHECK_CSI_SIZE (_sigpoll, 2*sizeof(int));
  79. CHECK_SI_SIZE (_sigpoll, 4*sizeof(int));
  80. CHECK_CSI_OFFSET(_sigsys);
  81. CHECK_CSI_SIZE (_sigsys, 3*sizeof(int));
  82. CHECK_SI_SIZE (_sigsys, 4*sizeof(int));
  83. /* any new si_fields should be added here */
  84. }
  85. void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
  86. {
  87. signal_compat_build_tests();
  88. /* Don't leak in-kernel non-uapi flags to user-space */
  89. if (oact)
  90. oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
  91. if (!act)
  92. return;
  93. /* Don't let flags to be set from userspace */
  94. act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
  95. if (in_ia32_syscall())
  96. act->sa.sa_flags |= SA_IA32_ABI;
  97. if (in_x32_syscall())
  98. act->sa.sa_flags |= SA_X32_ABI;
  99. }