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 SYSCALL_DEFINE6(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
) || !IS_ENABLED(CONFIG_64BIT_TIME
))
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 compat_timespec __user
*)fifth
);
43 return ksys_semget(first
, second
, third
);
48 if (get_user(arg
, (unsigned long __user
*) ptr
))
50 return ksys_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_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_shmctl(first
, second
,
104 (struct shmid_ds __user
*) ptr
);
112 #include <linux/compat.h>
114 #ifndef COMPAT_SHMLBA
115 #define COMPAT_SHMLBA SHMLBA
118 struct compat_ipc_kludge
{
120 compat_long_t msgtyp
;
123 #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
124 COMPAT_SYSCALL_DEFINE6(ipc
, u32
, call
, int, first
, int, second
,
125 u32
, third
, compat_uptr_t
, ptr
, u32
, fifth
)
130 version
= call
>> 16; /* hack for backward compatibility */
135 /* struct sembuf is the same on 32 and 64bit :)) */
136 return ksys_semtimedop(first
, compat_ptr(ptr
), second
, NULL
);
138 if (!IS_ENABLED(CONFIG_COMPAT_32BIT_TIME
))
140 return compat_ksys_semtimedop(first
, compat_ptr(ptr
), second
,
143 return ksys_semget(first
, second
, third
);
147 if (get_user(pad
, (u32 __user
*) compat_ptr(ptr
)))
149 return compat_ksys_semctl(first
, second
, third
, pad
);
152 return compat_ksys_msgsnd(first
, ptr
, second
, third
);
155 void __user
*uptr
= compat_ptr(ptr
);
157 if (first
< 0 || second
< 0)
161 struct compat_ipc_kludge ipck
;
164 if (copy_from_user(&ipck
, uptr
, sizeof(ipck
)))
166 return compat_ksys_msgrcv(first
, ipck
.msgp
, second
,
169 return compat_ksys_msgrcv(first
, ptr
, second
, fifth
, third
);
172 return ksys_msgget(first
, second
);
174 return compat_ksys_msgctl(first
, second
, compat_ptr(ptr
));
182 err
= do_shmat(first
, compat_ptr(ptr
), second
, &raddr
,
186 return put_user(raddr
, (compat_ulong_t __user
*)compat_ptr(third
));
189 return ksys_shmdt(compat_ptr(ptr
));
191 return ksys_shmget(first
, (unsigned int)second
, third
);
193 return compat_ksys_shmctl(first
, second
, compat_ptr(ptr
));