xref: /netbsd-src/sys/compat/linux/common/linux_ipccall.c (revision 93f9db1b75d415b78f73ed629beeb86235153473)
1 /*	$NetBSD: linux_ipccall.c,v 1.16 1998/10/04 00:02:35 fvdl 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 Frank van der Linden and 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 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/shm.h>
42 #include <sys/sem.h>
43 #include <sys/msg.h>
44 #include <sys/proc.h>
45 #include <sys/systm.h>
46 
47 /* real syscalls */
48 #include <sys/mount.h>
49 #include <sys/syscallargs.h>
50 
51 
52 /* sys_ipc + args prototype */
53 #include <compat/linux/common/linux_types.h>
54 #include <compat/linux/common/linux_signal.h>
55 
56 #include <compat/linux/linux_syscallargs.h>
57 #include <compat/linux/linux_syscall.h>
58 
59 /* general ipc defines */
60 #include <compat/linux/common/linux_ipc.h>
61 
62 /* prototypes for real/normal linux-emul syscalls */
63 #include <compat/linux/common/linux_msg.h>
64 #include <compat/linux/common/linux_shm.h>
65 #include <compat/linux/common/linux_sem.h>
66 
67 /* prototypes for sys_ipc stuff */
68 #include <compat/linux/common/linux_ipccall.h>
69 
70 
71 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */
72 /* Not used on: alpha */
73 
74 /*
75  * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux.
76  * The main difference is, that Linux handles it all via one
77  * system call, which has the usual maximum amount of 5 arguments.
78  * This results in a kludge for calls that take 6 of them.
79  *
80  * The SYSV??? options have to be enabled to get the appropriate
81  * functions to work.
82  */
83 
84 int
85 linux_sys_ipc(p, v, retval)
86 	struct proc *p;
87 	void *v;
88 	register_t *retval;
89 {
90 	struct linux_sys_ipc_args /* {
91 		syscallarg(int) what;
92 		syscallarg(int) a1;
93 		syscallarg(int) a2;
94 		syscallarg(int) a3;
95 		syscallarg(caddr_t) ptr;
96 	} */ *uap = v;
97 
98 	switch (SCARG(uap, what)) {
99 #ifdef SYSVSEM
100 	case LINUX_SYS_semop:
101 		return linux_semop(p, uap, retval);
102 	case LINUX_SYS_semget:
103 		return linux_semget(p, uap, retval);
104 	case LINUX_SYS_semctl: {
105 		struct linux_sys_semctl_args bsa;
106 		union linux_semun arg;
107 		int error;
108 
109 		SCARG(&bsa, semid) = SCARG(uap, a1);
110 		SCARG(&bsa, semnum) = SCARG(uap, a2);
111 		SCARG(&bsa, cmd) = SCARG(uap, a3);
112 		/* Convert from (union linux_semun *) to (union linux_semun) */
113 		if ((error = copyin(SCARG(uap, ptr), &arg, sizeof arg)))
114 			return error;
115 		SCARG(&bsa, arg) = arg;
116 
117 		return linux_sys_semctl(p, &bsa, retval);
118 	    }
119 #endif
120 #ifdef SYSVMSG
121 	case LINUX_SYS_msgsnd:
122 		return linux_msgsnd(p, uap, retval);
123 	case LINUX_SYS_msgrcv:
124 		return linux_msgrcv(p, uap, retval);
125 	case LINUX_SYS_msgget:
126 		return linux_msgget(p, uap, retval);
127 	case LINUX_SYS_msgctl: {
128 		struct linux_sys_msgctl_args bsa;
129 
130 		SCARG(&bsa, msqid) = SCARG(uap, a1);
131 		SCARG(&bsa, cmd) = SCARG(uap, a2);
132 		SCARG(&bsa, buf) = (struct linux_msqid_ds *)SCARG(uap, ptr);
133 
134 		return linux_sys_msgctl(p, &bsa, retval);
135 	    }
136 #endif
137 #ifdef SYSVSHM
138 	case LINUX_SYS_shmat: {
139 		struct linux_sys_shmat_args bsa;
140 
141 		SCARG(&bsa, shmid) = SCARG(uap, a1);
142 		SCARG(&bsa, shmaddr) = (void *)SCARG(uap, ptr);
143 		SCARG(&bsa, shmflg) = SCARG(uap, a2);
144 		/* XXX passing pointer inside int here */
145 		SCARG(&bsa, raddr) = (u_long *)SCARG(uap, a3);
146 
147 		return linux_sys_shmat(p, &bsa, retval);
148 	    }
149 	case LINUX_SYS_shmdt:
150 		return linux_shmdt(p, uap, retval);
151 	case LINUX_SYS_shmget:
152 		return linux_shmget(p, uap, retval);
153 	case LINUX_SYS_shmctl: {
154 		struct linux_sys_shmctl_args bsa;
155 
156 		SCARG(&bsa, shmid) = SCARG(uap, a1);
157 		SCARG(&bsa, cmd) = SCARG(uap, a2);
158 		SCARG(&bsa, buf) = (struct linux_shmid_ds *)SCARG(uap, ptr);
159 
160 		return linux_sys_shmctl(p, &bsa, retval);
161 	    }
162 #endif
163 	default:
164 		return ENOSYS;
165 	}
166 }
167 
168 #ifdef SYSVSEM
169 inline int
170 linux_semop(p, uap, retval)
171 	struct proc *p;
172 	struct linux_sys_ipc_args /* {
173 		syscallarg(int) what;
174 		syscallarg(int) a1;
175 		syscallarg(int) a2;
176 		syscallarg(int) a3;
177 		syscallarg(caddr_t) ptr;
178 	} */ *uap;
179 	register_t *retval;
180 {
181 	struct sys_semop_args bsa;
182 
183 	SCARG(&bsa, semid) = SCARG(uap, a1);
184 	SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
185 	SCARG(&bsa, nsops) = SCARG(uap, a2);
186 
187 	return sys_semop(p, &bsa, retval);
188 }
189 
190 inline int
191 linux_semget(p, uap, retval)
192 	struct proc *p;
193 	struct linux_sys_ipc_args /* {
194 		syscallarg(int) what;
195 		syscallarg(int) a1;
196 		syscallarg(int) a2;
197 		syscallarg(int) a3;
198 		syscallarg(caddr_t) ptr;
199 	} */ *uap;
200 	register_t *retval;
201 {
202 	struct sys_semget_args bsa;
203 
204 	SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
205 	SCARG(&bsa, nsems) = SCARG(uap, a2);
206 	SCARG(&bsa, semflg) = SCARG(uap, a3);
207 
208 	return sys_semget(p, &bsa, retval);
209 }
210 
211 #endif /* SYSVSEM */
212 
213 #ifdef SYSVMSG
214 
215 inline int
216 linux_msgsnd(p, uap, retval)
217 	struct proc *p;
218 	struct linux_sys_ipc_args /* {
219 		syscallarg(int) what;
220 		syscallarg(int) a1;
221 		syscallarg(int) a2;
222 		syscallarg(int) a3;
223 		syscallarg(caddr_t) ptr;
224 	} */ *uap;
225 	register_t *retval;
226 {
227 	struct sys_msgsnd_args bma;
228 
229 	SCARG(&bma, msqid) = SCARG(uap, a1);
230 	SCARG(&bma, msgp) = SCARG(uap, ptr);
231 	SCARG(&bma, msgsz) = SCARG(uap, a2);
232 	SCARG(&bma, msgflg) = SCARG(uap, a3);
233 
234 	return sys_msgsnd(p, &bma, retval);
235 }
236 
237 inline int
238 linux_msgrcv(p, uap, retval)
239 	struct proc *p;
240 	struct linux_sys_ipc_args /* {
241 		syscallarg(int) what;
242 		syscallarg(int) a1;
243 		syscallarg(int) a2;
244 		syscallarg(int) a3;
245 		syscallarg(caddr_t) ptr;
246 	} */ *uap;
247 	register_t *retval;
248 {
249 	struct sys_msgrcv_args bma;
250 	struct linux_msgrcv_msgarg kluge;
251 	int error;
252 
253 	if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge)))
254 		return error;
255 
256 	SCARG(&bma, msqid) = SCARG(uap, a1);
257 	SCARG(&bma, msgp) = kluge.msg;
258 	SCARG(&bma, msgsz) = SCARG(uap, a2);
259 	SCARG(&bma, msgtyp) = kluge.type;
260 	SCARG(&bma, msgflg) = SCARG(uap, a3);
261 
262 	return sys_msgrcv(p, &bma, retval);
263 }
264 
265 inline int
266 linux_msgget(p, uap, retval)
267 	struct proc *p;
268 	struct linux_sys_ipc_args /* {
269 		syscallarg(int) what;
270 		syscallarg(int) a1;
271 		syscallarg(int) a2;
272 		syscallarg(int) a3;
273 		syscallarg(caddr_t) ptr;
274 	} */ *uap;
275 	register_t *retval;
276 {
277 	struct sys_msgget_args bma;
278 
279 	SCARG(&bma, key) = (key_t)SCARG(uap, a1);
280 	SCARG(&bma, msgflg) = SCARG(uap, a2);
281 
282 	return sys_msgget(p, &bma, retval);
283 }
284 
285 #endif /* SYSVMSG */
286 
287 #ifdef SYSVSHM
288 /*
289  * shmdt(): this could have been mapped directly, if it wasn't for
290  * the extra indirection by the linux_ipc system call.
291  */
292 inline int
293 linux_shmdt(p, uap, retval)
294 	struct proc *p;
295 	struct linux_sys_ipc_args /* {
296 		syscallarg(int) what;
297 		syscallarg(int) a1;
298 		syscallarg(int) a2;
299 		syscallarg(int) a3;
300 		syscallarg(caddr_t) ptr;
301 	} */ *uap;
302 	register_t *retval;
303 {
304 	struct sys_shmdt_args bsa;
305 
306 	SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
307 
308 	return sys_shmdt(p, &bsa, retval);
309 }
310 
311 /*
312  * Same story as shmdt.
313  */
314 inline int
315 linux_shmget(p, uap, retval)
316 	struct proc *p;
317 	struct linux_sys_ipc_args /* {
318 		syscallarg(int) what;
319 		syscallarg(int) a1;
320 		syscallarg(int) a2;
321 		syscallarg(int) a3;
322 		syscallarg(caddr_t) ptr;
323 	} */ *uap;
324 	register_t *retval;
325 {
326 	struct sys_shmget_args bsa;
327 
328 	SCARG(&bsa, key) = SCARG(uap, a1);
329 	SCARG(&bsa, size) = SCARG(uap, a2);
330 	SCARG(&bsa, shmflg) = SCARG(uap, a3);
331 
332 	return sys_shmget(p, &bsa, retval);
333 }
334 
335 #endif /* SYSVSHM */
336