linux_ipccall.c revision 1.15 1 /* $NetBSD: linux_ipccall.c,v 1.15 1998/10/03 20:17:41 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Eric Haszlakiewicz.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1995 Frank van der Linden
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed for the NetBSD Project
54 * by Frank van der Linden
55 * 4. The name of the author may not be used to endorse or promote products
56 * derived from this software without specific prior written permission
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 */
69
70 #include <sys/types.h>
71 #include <sys/param.h>
72 #include <sys/shm.h>
73 #include <sys/sem.h>
74 #include <sys/msg.h>
75 #include <sys/proc.h>
76 #include <sys/systm.h>
77
78 /* real syscalls */
79 #include <sys/mount.h>
80 #include <sys/syscallargs.h>
81
82
83 /* sys_ipc + args prototype */
84 #include <compat/linux/common/linux_types.h>
85 #include <compat/linux/common/linux_signal.h>
86
87 #include <compat/linux/linux_syscallargs.h>
88 #include <compat/linux/linux_syscall.h>
89
90 /* general ipc defines */
91 #include <compat/linux/common/linux_ipc.h>
92
93 /* prototypes for real/normal linux-emul syscalls */
94 #include <compat/linux/common/linux_msg.h>
95 #include <compat/linux/common/linux_shm.h>
96 #include <compat/linux/common/linux_sem.h>
97
98 /* prototypes for sys_ipc stuff */
99 #include <compat/linux/common/linux_ipccall.h>
100
101
102 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */
103 /* Not used on: alpha */
104
105 /*
106 * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux.
107 * The main difference is, that Linux handles it all via one
108 * system call, which has the usual maximum amount of 5 arguments.
109 * This results in a kludge for calls that take 6 of them.
110 *
111 * The SYSV??? options have to be enabled to get the appropriate
112 * functions to work.
113 */
114
115 int
116 linux_sys_ipc(p, v, retval)
117 struct proc *p;
118 void *v;
119 register_t *retval;
120 {
121 struct linux_sys_ipc_args /* {
122 syscallarg(int) what;
123 syscallarg(int) a1;
124 syscallarg(int) a2;
125 syscallarg(int) a3;
126 syscallarg(caddr_t) ptr;
127 } */ *uap = v;
128
129 switch (SCARG(uap, what)) {
130 #ifdef SYSVSEM
131 case LINUX_SYS_semop:
132 return linux_semop(p, uap, retval);
133 case LINUX_SYS_semget:
134 return linux_semget(p, uap, retval);
135 case LINUX_SYS_semctl: {
136 struct linux_sys_semctl_args bsa;
137 union linux_semun arg;
138 int error;
139
140 SCARG(&bsa, semid) = SCARG(uap, a1);
141 SCARG(&bsa, semnum) = SCARG(uap, a2);
142 SCARG(&bsa, cmd) = SCARG(uap, a3);
143 /* Convert from (union linux_semun *) to (union linux_semun) */
144 if ((error = copyin(SCARG(uap, ptr), &arg, sizeof arg)))
145 return error;
146 SCARG(&bsa, arg) = arg;
147
148 return linux_sys_semctl(p, &bsa, retval);
149 }
150 #endif
151 #ifdef SYSVMSG
152 case LINUX_SYS_msgsnd:
153 return linux_msgsnd(p, uap, retval);
154 case LINUX_SYS_msgrcv:
155 return linux_msgrcv(p, uap, retval);
156 case LINUX_SYS_msgget:
157 return linux_msgget(p, uap, retval);
158 case LINUX_SYS_msgctl: {
159 struct linux_sys_msgctl_args bsa;
160
161 SCARG(&bsa, msqid) = SCARG(uap, a1);
162 SCARG(&bsa, cmd) = SCARG(uap, a2);
163 SCARG(&bsa, buf) = (struct linux_msqid_ds *)SCARG(uap, ptr);
164
165 return linux_sys_msgctl(p, &bsa, retval);
166 }
167 #endif
168 #ifdef SYSVSHM
169 case LINUX_SYS_shmat: {
170 struct linux_sys_shmat_args bsa;
171
172 SCARG(&bsa, shmid) = SCARG(uap, a1);
173 SCARG(&bsa, shmaddr) = (void *)SCARG(uap, ptr);
174 SCARG(&bsa, shmflg) = SCARG(uap, a2);
175 /* XXX passing pointer inside int here */
176 SCARG(&bsa, raddr) = (u_long *)SCARG(uap, a3);
177
178 return linux_sys_shmat(p, &bsa, retval);
179 }
180 case LINUX_SYS_shmdt:
181 return linux_shmdt(p, uap, retval);
182 case LINUX_SYS_shmget:
183 return linux_shmget(p, uap, retval);
184 case LINUX_SYS_shmctl: {
185 struct linux_sys_shmctl_args bsa;
186
187 SCARG(&bsa, shmid) = SCARG(uap, a1);
188 SCARG(&bsa, cmd) = SCARG(uap, a2);
189 SCARG(&bsa, buf) = (struct linux_shmid_ds *)SCARG(uap, ptr);
190
191 return linux_sys_shmctl(p, &bsa, retval);
192 }
193 #endif
194 default:
195 return ENOSYS;
196 }
197 }
198
199 #ifdef SYSVSEM
200 inline int
201 linux_semop(p, uap, retval)
202 struct proc *p;
203 struct linux_sys_ipc_args /* {
204 syscallarg(int) what;
205 syscallarg(int) a1;
206 syscallarg(int) a2;
207 syscallarg(int) a3;
208 syscallarg(caddr_t) ptr;
209 } */ *uap;
210 register_t *retval;
211 {
212 struct sys_semop_args bsa;
213
214 SCARG(&bsa, semid) = SCARG(uap, a1);
215 SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
216 SCARG(&bsa, nsops) = SCARG(uap, a2);
217
218 return sys_semop(p, &bsa, retval);
219 }
220
221 inline int
222 linux_semget(p, uap, retval)
223 struct proc *p;
224 struct linux_sys_ipc_args /* {
225 syscallarg(int) what;
226 syscallarg(int) a1;
227 syscallarg(int) a2;
228 syscallarg(int) a3;
229 syscallarg(caddr_t) ptr;
230 } */ *uap;
231 register_t *retval;
232 {
233 struct sys_semget_args bsa;
234
235 SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
236 SCARG(&bsa, nsems) = SCARG(uap, a2);
237 SCARG(&bsa, semflg) = SCARG(uap, a3);
238
239 return sys_semget(p, &bsa, retval);
240 }
241
242 #endif /* SYSVSEM */
243
244 #ifdef SYSVMSG
245
246 inline int
247 linux_msgsnd(p, uap, retval)
248 struct proc *p;
249 struct linux_sys_ipc_args /* {
250 syscallarg(int) what;
251 syscallarg(int) a1;
252 syscallarg(int) a2;
253 syscallarg(int) a3;
254 syscallarg(caddr_t) ptr;
255 } */ *uap;
256 register_t *retval;
257 {
258 struct sys_msgsnd_args bma;
259
260 SCARG(&bma, msqid) = SCARG(uap, a1);
261 SCARG(&bma, msgp) = SCARG(uap, ptr);
262 SCARG(&bma, msgsz) = SCARG(uap, a2);
263 SCARG(&bma, msgflg) = SCARG(uap, a3);
264
265 return sys_msgsnd(p, &bma, retval);
266 }
267
268 inline int
269 linux_msgrcv(p, uap, retval)
270 struct proc *p;
271 struct linux_sys_ipc_args /* {
272 syscallarg(int) what;
273 syscallarg(int) a1;
274 syscallarg(int) a2;
275 syscallarg(int) a3;
276 syscallarg(caddr_t) ptr;
277 } */ *uap;
278 register_t *retval;
279 {
280 struct sys_msgrcv_args bma;
281 struct linux_msgrcv_msgarg kluge;
282 int error;
283
284 if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge)))
285 return error;
286
287 SCARG(&bma, msqid) = SCARG(uap, a1);
288 SCARG(&bma, msgp) = kluge.msg;
289 SCARG(&bma, msgsz) = SCARG(uap, a2);
290 SCARG(&bma, msgtyp) = kluge.type;
291 SCARG(&bma, msgflg) = SCARG(uap, a3);
292
293 return sys_msgrcv(p, &bma, retval);
294 }
295
296 inline int
297 linux_msgget(p, uap, retval)
298 struct proc *p;
299 struct linux_sys_ipc_args /* {
300 syscallarg(int) what;
301 syscallarg(int) a1;
302 syscallarg(int) a2;
303 syscallarg(int) a3;
304 syscallarg(caddr_t) ptr;
305 } */ *uap;
306 register_t *retval;
307 {
308 struct sys_msgget_args bma;
309
310 SCARG(&bma, key) = (key_t)SCARG(uap, a1);
311 SCARG(&bma, msgflg) = SCARG(uap, a2);
312
313 return sys_msgget(p, &bma, retval);
314 }
315
316 #endif /* SYSVMSG */
317
318 #ifdef SYSVSHM
319 /*
320 * shmdt(): this could have been mapped directly, if it wasn't for
321 * the extra indirection by the linux_ipc system call.
322 */
323 inline int
324 linux_shmdt(p, uap, retval)
325 struct proc *p;
326 struct linux_sys_ipc_args /* {
327 syscallarg(int) what;
328 syscallarg(int) a1;
329 syscallarg(int) a2;
330 syscallarg(int) a3;
331 syscallarg(caddr_t) ptr;
332 } */ *uap;
333 register_t *retval;
334 {
335 struct sys_shmdt_args bsa;
336
337 SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
338
339 return sys_shmdt(p, &bsa, retval);
340 }
341
342 /*
343 * Same story as shmdt.
344 */
345 inline int
346 linux_shmget(p, uap, retval)
347 struct proc *p;
348 struct linux_sys_ipc_args /* {
349 syscallarg(int) what;
350 syscallarg(int) a1;
351 syscallarg(int) a2;
352 syscallarg(int) a3;
353 syscallarg(caddr_t) ptr;
354 } */ *uap;
355 register_t *retval;
356 {
357 struct sys_shmget_args bsa;
358
359 SCARG(&bsa, key) = SCARG(uap, a1);
360 SCARG(&bsa, size) = SCARG(uap, a2);
361 SCARG(&bsa, shmflg) = SCARG(uap, a3);
362
363 return sys_shmget(p, &bsa, retval);
364 }
365
366 #endif /* SYSVSHM */
367