syscall.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * sys_ipc() is the old de-multiplexer for the SysV IPC calls.
  4. *
  5. * This is really horribly ugly, and new architectures should just wire up
  6. * the individual syscalls instead.
  7. */
  8. #include <linux/unistd.h>
  9. #include <linux/syscalls.h>
  10. #include <linux/security.h>
  11. #include <linux/ipc_namespace.h>
  12. #include "util.h"
  13. #ifdef __ARCH_WANT_SYS_IPC
  14. #include <linux/errno.h>
  15. #include <linux/ipc.h>
  16. #include <linux/shm.h>
  17. #include <linux/uaccess.h>
  18. int ksys_ipc(unsigned int call, int first, unsigned long second,
  19. unsigned long third, void __user * ptr, long fifth)
  20. {
  21. int version, ret;
  22. version = call >> 16; /* hack for backward compatibility */
  23. call &= 0xffff;
  24. switch (call) {
  25. case SEMOP:
  26. return ksys_semtimedop(first, (struct sembuf __user *)ptr,
  27. second, NULL);
  28. case SEMTIMEDOP:
  29. if (IS_ENABLED(CONFIG_64BIT))
  30. return ksys_semtimedop(first, ptr, second,
  31. (const struct __kernel_timespec __user *)fifth);
  32. else if (IS_ENABLED(CONFIG_COMPAT_32BIT_TIME))
  33. return compat_ksys_semtimedop(first, ptr, second,
  34. (const struct old_timespec32 __user *)fifth);
  35. else
  36. return -ENOSYS;
  37. case SEMGET:
  38. return ksys_semget(first, second, third);
  39. case SEMCTL: {
  40. unsigned long arg;
  41. if (!ptr)
  42. return -EINVAL;
  43. if (get_user(arg, (unsigned long __user *) ptr))
  44. return -EFAULT;
  45. return ksys_old_semctl(first, second, third, arg);
  46. }
  47. case MSGSND:
  48. return ksys_msgsnd(first, (struct msgbuf __user *) ptr,
  49. second, third);
  50. case MSGRCV:
  51. switch (version) {
  52. case 0: {
  53. struct ipc_kludge tmp;
  54. if (!ptr)
  55. return -EINVAL;
  56. if (copy_from_user(&tmp,
  57. (struct ipc_kludge __user *) ptr,
  58. sizeof(tmp)))
  59. return -EFAULT;
  60. return ksys_msgrcv(first, tmp.msgp, second,
  61. tmp.msgtyp, third);
  62. }
  63. default:
  64. return ksys_msgrcv(first,
  65. (struct msgbuf __user *) ptr,
  66. second, fifth, third);
  67. }
  68. case MSGGET:
  69. return ksys_msgget((key_t) first, second);
  70. case MSGCTL:
  71. return ksys_old_msgctl(first, second,
  72. (struct msqid_ds __user *)ptr);
  73. case SHMAT:
  74. switch (version) {
  75. default: {
  76. unsigned long raddr;
  77. ret = do_shmat(first, (char __user *)ptr,
  78. second, &raddr, SHMLBA);
  79. if (ret)
  80. return ret;
  81. return put_user(raddr, (unsigned long __user *) third);
  82. }
  83. case 1:
  84. /*
  85. * This was the entry point for kernel-originating calls
  86. * from iBCS2 in 2.2 days.
  87. */
  88. return -EINVAL;
  89. }
  90. case SHMDT:
  91. return ksys_shmdt((char __user *)ptr);
  92. case SHMGET:
  93. return ksys_shmget(first, second, third);
  94. case SHMCTL:
  95. return ksys_old_shmctl(first, second,
  96. (struct shmid_ds __user *) ptr);
  97. default:
  98. return -ENOSYS;
  99. }
  100. }
  101. SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
  102. unsigned long, third, void __user *, ptr, long, fifth)
  103. {
  104. return ksys_ipc(call, first, second, third, ptr, fifth);
  105. }
  106. #endif
  107. #ifdef CONFIG_COMPAT
  108. #include <linux/compat.h>
  109. #ifndef COMPAT_SHMLBA
  110. #define COMPAT_SHMLBA SHMLBA
  111. #endif
  112. struct compat_ipc_kludge {
  113. compat_uptr_t msgp;
  114. compat_long_t msgtyp;
  115. };
  116. #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
  117. int compat_ksys_ipc(u32 call, int first, int second,
  118. u32 third, compat_uptr_t ptr, u32 fifth)
  119. {
  120. int version;
  121. u32 pad;
  122. version = call >> 16; /* hack for backward compatibility */
  123. call &= 0xffff;
  124. switch (call) {
  125. case SEMOP:
  126. /* struct sembuf is the same on 32 and 64bit :)) */
  127. return ksys_semtimedop(first, compat_ptr(ptr), second, NULL);
  128. case SEMTIMEDOP:
  129. if (!IS_ENABLED(CONFIG_COMPAT_32BIT_TIME))
  130. return -ENOSYS;
  131. return compat_ksys_semtimedop(first, compat_ptr(ptr), second,
  132. compat_ptr(fifth));
  133. case SEMGET:
  134. return ksys_semget(first, second, third);
  135. case SEMCTL:
  136. if (!ptr)
  137. return -EINVAL;
  138. if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
  139. return -EFAULT;
  140. return compat_ksys_old_semctl(first, second, third, pad);
  141. case MSGSND:
  142. return compat_ksys_msgsnd(first, ptr, second, third);
  143. case MSGRCV: {
  144. void __user *uptr = compat_ptr(ptr);
  145. if (first < 0 || second < 0)
  146. return -EINVAL;
  147. if (!version) {
  148. struct compat_ipc_kludge ipck;
  149. if (!uptr)
  150. return -EINVAL;
  151. if (copy_from_user(&ipck, uptr, sizeof(ipck)))
  152. return -EFAULT;
  153. return compat_ksys_msgrcv(first, ipck.msgp, second,
  154. ipck.msgtyp, third);
  155. }
  156. return compat_ksys_msgrcv(first, ptr, second, fifth, third);
  157. }
  158. case MSGGET:
  159. return ksys_msgget(first, second);
  160. case MSGCTL:
  161. return compat_ksys_old_msgctl(first, second, compat_ptr(ptr));
  162. case SHMAT: {
  163. int err;
  164. unsigned long raddr;
  165. if (version == 1)
  166. return -EINVAL;
  167. err = do_shmat(first, compat_ptr(ptr), second, &raddr,
  168. COMPAT_SHMLBA);
  169. if (err < 0)
  170. return err;
  171. return put_user(raddr, (compat_ulong_t __user *)compat_ptr(third));
  172. }
  173. case SHMDT:
  174. return ksys_shmdt(compat_ptr(ptr));
  175. case SHMGET:
  176. return ksys_shmget(first, (unsigned int)second, third);
  177. case SHMCTL:
  178. return compat_ksys_old_shmctl(first, second, compat_ptr(ptr));
  179. }
  180. return -ENOSYS;
  181. }
  182. COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
  183. u32, third, compat_uptr_t, ptr, u32, fifth)
  184. {
  185. return compat_ksys_ipc(call, first, second, third, ptr, fifth);
  186. }
  187. #endif
  188. #endif