1 // SPDX-License-Identifier: GPL-2.0
3 * sys_ipc() is the old de-multiplexer for the SysV IPC calls.
5 * This is really horribly ugly, and new architectures should just wire up
6 * the individual syscalls instead.
8 #include <linux/unistd.h>
9 #include <linux/syscalls.h>
10 #include <linux/security.h>
11 #include <linux/ipc_namespace.h>
14 #ifdef __ARCH_WANT_SYS_IPC
15 #include <linux/errno.h>
16 #include <linux/ipc.h>
17 #include <linux/shm.h>
18 #include <linux/uaccess.h>
20 int ksys_ipc(unsigned int call
, int first
, unsigned long second
,
21 unsigned long third
, void __user
* ptr
, long fifth
)
25 version
= call
>> 16; /* hack for backward compatibility */
30 return ksys_semtimedop(first
, (struct sembuf __user
*)ptr
,
33 if (IS_ENABLED(CONFIG_64BIT
))
34 return ksys_semtimedop(first
, ptr
, second
,
35 (const struct __kernel_timespec __user
*)fifth
);
36 else if (IS_ENABLED(CONFIG_COMPAT_32BIT_TIME
))
37 return compat_ksys_semtimedop(first
, ptr
, second
,
38 (const struct old_timespec32 __user
*)fifth
);
43 return ksys_semget(first
, second
, third
);
48 if (get_user(arg
, (unsigned long __user
*) ptr
))
50 return ksys_old_semctl(first
, second
, third
, arg
);
54 return ksys_msgsnd(first
, (struct msgbuf __user
*) ptr
,
59 struct ipc_kludge tmp
;
63 if (copy_from_user(&tmp
,
64 (struct ipc_kludge __user
*) ptr
,
67 return ksys_msgrcv(first
, tmp
.msgp
, second
,
71 return ksys_msgrcv(first
,
72 (struct msgbuf __user
*) ptr
,
73 second
, fifth
, third
);
76 return ksys_msgget((key_t
) first
, second
);
78 return ksys_old_msgctl(first
, second
,
79 (struct msqid_ds __user
*)ptr
);
85 ret
= do_shmat(first
, (char __user
*)ptr
,
86 second
, &raddr
, SHMLBA
);
89 return put_user(raddr
, (unsigned long __user
*) third
);
93 * This was the entry point for kernel-originating calls
94 * from iBCS2 in 2.2 days.
99 return ksys_shmdt((char __user
*)ptr
);
101 return ksys_shmget(first
, second
, third
);
103 return ksys_old_shmctl(first
, second
,
104 (struct shmid_ds __user
*) ptr
);
110 SYSCALL_DEFINE6(ipc
, unsigned int, call
, int, first
, unsigned long, second
,
111 unsigned long, third
, void __user
*, ptr
, long, fifth
)
113 return ksys_ipc(call
, first
, second
, third
, ptr
, fifth
);
118 #include <linux/compat.h>
120 #ifndef COMPAT_SHMLBA
121 #define COMPAT_SHMLBA SHMLBA
124 struct compat_ipc_kludge
{
126 compat_long_t msgtyp
;
129 #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
130 int compat_ksys_ipc(u32 call
, int first
, int second
,
131 u32 third
, compat_uptr_t ptr
, u32 fifth
)
136 version
= call
>> 16; /* hack for backward compatibility */
141 /* struct sembuf is the same on 32 and 64bit :)) */
142 return ksys_semtimedop(first
, compat_ptr(ptr
), second
, NULL
);
144 if (!IS_ENABLED(CONFIG_COMPAT_32BIT_TIME
))
146 return compat_ksys_semtimedop(first
, compat_ptr(ptr
), second
,
149 return ksys_semget(first
, second
, third
);
153 if (get_user(pad
, (u32 __user
*) compat_ptr(ptr
)))
155 return compat_ksys_old_semctl(first
, second
, third
, pad
);
158 return compat_ksys_msgsnd(first
, ptr
, second
, third
);
161 void __user
*uptr
= compat_ptr(ptr
);
163 if (first
< 0 || second
< 0)
167 struct compat_ipc_kludge ipck
;
170 if (copy_from_user(&ipck
, uptr
, sizeof(ipck
)))
172 return compat_ksys_msgrcv(first
, ipck
.msgp
, second
,
175 return compat_ksys_msgrcv(first
, ptr
, second
, fifth
, third
);
178 return ksys_msgget(first
, second
);
180 return compat_ksys_old_msgctl(first
, second
, compat_ptr(ptr
));
188 err
= do_shmat(first
, compat_ptr(ptr
), second
, &raddr
,
192 return put_user(raddr
, (compat_ulong_t __user
*)compat_ptr(third
));
195 return ksys_shmdt(compat_ptr(ptr
));
197 return ksys_shmget(first
, (unsigned int)second
, third
);
199 return compat_ksys_old_shmctl(first
, second
, compat_ptr(ptr
));
205 COMPAT_SYSCALL_DEFINE6(ipc
, u32
, call
, int, first
, int, second
,
206 u32
, third
, compat_uptr_t
, ptr
, u32
, fifth
)
208 return compat_ksys_ipc(call
, first
, second
, third
, ptr
, fifth
);