1 /*	$NetBSD: netbsd32_ipc.c,v 1.18 2015/12/03 10:38:21 pgoyette Exp $	*/
2 
3 /*
4  * Copyright (c) 1998, 2001 Matthew R. Green
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_ipc.c,v 1.18 2015/12/03 10:38:21 pgoyette Exp $");
31 
32 #if defined(_KERNEL_OPT)
33 #include "opt_sysv.h"
34 #endif
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/ipc.h>
39 #include <sys/msg.h>
40 #include <sys/sem.h>
41 #include <sys/shm.h>
42 #include <sys/mount.h>
43 #include <sys/module.h>
44 #include <sys/dirent.h>
45 #include <sys/syscallvar.h>
46 
47 #include <sys/syscallargs.h>
48 #include <sys/proc.h>
49 
50 #include <compat/netbsd32/netbsd32.h>
51 #include <compat/netbsd32/netbsd32_syscall.h>
52 #include <compat/netbsd32/netbsd32_syscallargs.h>
53 #include <compat/netbsd32/netbsd32_conv.h>
54 
55 extern struct emul emul_netbsd32;
56 
57 #define _PKG_ENTRY(name)	\
58 	{ NETBSD32_SYS_ ## name, 0, (sy_call_t *)name }
59 
60 #define _PKG_ENTRY2(code, name)	\
61 	{ NETBSD32_SYS_ ## code, 0, (sy_call_t *)name }
62 
63 static const struct syscall_package compat_sysvipc_syscalls[] = {
64 #if defined(SYSVSEM)
65 	_PKG_ENTRY(netbsd32_____semctl50),
66 	_PKG_ENTRY(netbsd32_semget),
67 	_PKG_ENTRY(netbsd32_semop),
68 	_PKG_ENTRY(netbsd32_semconfig),
69 #if defined(COMPAT_10)
70 	_PKG_ENTRY2(compat_10_osemsys, compat_10_netbsd32_semsys),
71 #endif
72 #if defined(COMPAT_14)
73 	_PKG_ENTRY(compat_14_netbsd32___semctl),
74 #endif
75 #if defined(COMPAT_50)
76 	_PKG_ENTRY(compat_50_netbsd32___semctl14),
77 #endif
78 #endif /* SYSVSEM */
79 
80 #if defined(SYSVSHM)
81 	_PKG_ENTRY(netbsd32_shmat),
82 	_PKG_ENTRY(netbsd32___shmctl50),
83 	_PKG_ENTRY(netbsd32_shmdt),
84 	_PKG_ENTRY(netbsd32_shmget),
85 #if defined(COMPAT_10)
86 	_PKG_ENTRY2(compat_10_oshmsys, compat_10_netbsd32_shmsys),
87 #endif
88 #if defined(COMPAT_14)
89 	_PKG_ENTRY(compat_14_netbsd32_shmctl),
90 #endif
91 #if defined(COMPAT_50)
92 	_PKG_ENTRY(compat_50_netbsd32___shmctl13),
93 #endif
94 #endif /* SYSVSHM */
95 
96 #if defined(SYSVMSG)
97 	_PKG_ENTRY(netbsd32___msgctl50),
98 	_PKG_ENTRY(netbsd32_msgget),
99 	_PKG_ENTRY(netbsd32_msgsnd),
100 	_PKG_ENTRY(netbsd32_msgrcv),
101 #if defined(COMPAT_10)
102 	_PKG_ENTRY2(compat_10_omsgsys, compat_10_netbsd32_msgsys),
103 #endif
104 #if defined(COMPAT_14)
105 	_PKG_ENTRY(compat_14_netbsd32_msgctl),
106 #endif
107 #if defined(COMPAT_50)
108 	_PKG_ENTRY(compat_50_netbsd32___msgctl13),
109 #endif
110 #endif /* SYSVMSG */
111 	{ 0, 0, NULL }
112 };
113 
114 MODULE(MODULE_CLASS_EXEC, compat_netbsd32_sysvipc, "sysv_ipc,compat_netbsd32");
115 
116 static int
compat_netbsd32_sysvipc_modcmd(modcmd_t cmd,void * arg)117 compat_netbsd32_sysvipc_modcmd(modcmd_t cmd, void *arg)
118 {
119 	int error;
120 
121 	switch (cmd) {
122 	case MODULE_CMD_INIT:
123 		error = syscall_establish(&emul_netbsd32,
124 		    compat_sysvipc_syscalls);
125 		break;
126 	case MODULE_CMD_FINI:
127 		error = syscall_disestablish(&emul_netbsd32,
128 		    compat_sysvipc_syscalls);
129 		break;
130 	default:
131 		error = ENOTTY;
132 		break;
133 	}
134 	return error;
135 }
136 
137 
138 #if defined(SYSVSEM)
139 
140 int
netbsd32_____semctl50(struct lwp * l,const struct netbsd32_____semctl50_args * uap,register_t * retval)141 netbsd32_____semctl50(struct lwp *l, const struct netbsd32_____semctl50_args *uap, register_t *retval)
142 {
143 	/* {
144 		syscallarg(int) semid;
145 		syscallarg(int) semnum;
146 		syscallarg(int) cmd;
147 		syscallarg(netbsd32_semunp_t) arg;
148 	} */
149 	struct semid_ds sembuf;
150 	struct netbsd32_semid_ds sembuf32;
151 	int cmd, error;
152 	void *pass_arg;
153 	union __semun karg;
154 	union netbsd32_semun karg32;
155 
156 	cmd = SCARG(uap, cmd);
157 
158 	switch (cmd) {
159 	case IPC_SET:
160 	case IPC_STAT:
161 		pass_arg = &sembuf;
162 		break;
163 
164 	case GETALL:
165 	case SETVAL:
166 	case SETALL:
167 		pass_arg = &karg;
168 		break;
169 	default:
170 		pass_arg = NULL;
171 		break;
172 	}
173 
174 	if (pass_arg) {
175 		error = copyin(SCARG_P32(uap, arg), &karg32, sizeof(karg32));
176 		if (error)
177 			return error;
178 		if (pass_arg == &karg) {
179 			switch (cmd) {
180 			case GETALL:
181 			case SETALL:
182 				karg.array = NETBSD32PTR64(karg32.array);
183 				break;
184 			case SETVAL:
185 				karg.val = karg32.val;
186 				break;
187 			}
188 		}
189 		if (cmd == IPC_SET) {
190 			error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32,
191 			    sizeof(sembuf32));
192 			if (error)
193 				return (error);
194 			netbsd32_to_semid_ds(&sembuf32, &sembuf);
195 		}
196 	}
197 
198 	error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd,
199 	    pass_arg, retval);
200 
201 	if (error == 0 && cmd == IPC_STAT) {
202 		netbsd32_from_semid_ds(&sembuf, &sembuf32);
203 		error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf),
204 		    sizeof(sembuf32));
205 	}
206 
207 	return (error);
208 }
209 
210 int
netbsd32_semget(struct lwp * l,const struct netbsd32_semget_args * uap,register_t * retval)211 netbsd32_semget(struct lwp *l, const struct netbsd32_semget_args *uap, register_t *retval)
212 {
213 	/* {
214 		syscallarg(netbsd32_key_t) key;
215 		syscallarg(int) nsems;
216 		syscallarg(int) semflg;
217 	} */
218 	struct sys_semget_args ua;
219 
220 	NETBSD32TOX_UAP(key, key_t);
221 	NETBSD32TO64_UAP(nsems);
222 	NETBSD32TO64_UAP(semflg);
223 	return (sys_semget(l, &ua, retval));
224 }
225 
226 int
netbsd32_semop(struct lwp * l,const struct netbsd32_semop_args * uap,register_t * retval)227 netbsd32_semop(struct lwp *l, const struct netbsd32_semop_args *uap, register_t *retval)
228 {
229 	/* {
230 		syscallarg(int) semid;
231 		syscallarg(netbsd32_sembufp_t) sops;
232 		syscallarg(netbsd32_size_t) nsops;
233 	} */
234 	struct sys_semop_args ua;
235 
236 	NETBSD32TO64_UAP(semid);
237 	NETBSD32TOP_UAP(sops, struct sembuf);
238 	NETBSD32TOX_UAP(nsops, size_t);
239 	return (sys_semop(l, &ua, retval));
240 }
241 
242 int
netbsd32_semconfig(struct lwp * l,const struct netbsd32_semconfig_args * uap,register_t * retval)243 netbsd32_semconfig(struct lwp *l, const struct netbsd32_semconfig_args *uap, register_t *retval)
244 {
245 	/* {
246 		syscallarg(int) flag;
247 	} */
248 	struct sys_semconfig_args ua;
249 
250 	NETBSD32TO64_UAP(flag);
251 	return (sys_semconfig(l, &ua, retval));
252 }
253 #endif /* SYSVSEM */
254 
255 #if defined(SYSVMSG)
256 
257 int
netbsd32___msgctl50(struct lwp * l,const struct netbsd32___msgctl50_args * uap,register_t * retval)258 netbsd32___msgctl50(struct lwp *l, const struct netbsd32___msgctl50_args *uap,
259     register_t *retval)
260 {
261 	/* {
262 		syscallarg(int) msqid;
263 		syscallarg(int) cmd;
264 		syscallarg(netbsd32_msqid_dsp_t) buf;
265 	} */
266 	struct msqid_ds ds;
267 	struct netbsd32_msqid_ds ds32;
268 	int error, cmd;
269 
270 	cmd = SCARG(uap, cmd);
271 	if (cmd == IPC_SET) {
272 		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32));
273 		if (error)
274 			return error;
275 		netbsd32_to_msqid_ds(&ds32, &ds);
276 	}
277 
278 	error = msgctl1(l, SCARG(uap, msqid), cmd,
279 	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL);
280 
281 	if (error == 0 && cmd == IPC_STAT) {
282 		netbsd32_from_msqid_ds(&ds, &ds32);
283 		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32));
284 	}
285 
286 	return error;
287 }
288 
289 int
netbsd32_msgget(struct lwp * l,const struct netbsd32_msgget_args * uap,register_t * retval)290 netbsd32_msgget(struct lwp *l, const struct netbsd32_msgget_args *uap, register_t *retval)
291 {
292 	/* {
293 		syscallarg(netbsd32_key_t) key;
294 		syscallarg(int) msgflg;
295 	} */
296 	struct sys_msgget_args ua;
297 
298 	NETBSD32TOX_UAP(key, key_t);
299 	NETBSD32TO64_UAP(msgflg);
300 	return sys_msgget(l, &ua, retval);
301 }
302 
303 static int
netbsd32_msgsnd_fetch_type(const void * src,void * dst,size_t size)304 netbsd32_msgsnd_fetch_type(const void *src, void *dst, size_t size)
305 {
306 	netbsd32_long l32;
307 	long *l = dst;
308 	int error;
309 
310 	KASSERT(size == sizeof(netbsd32_long));
311 
312 	error = copyin(src, &l32, sizeof(l32));
313 	if (!error)
314 		*l = l32;
315 	return error;
316 }
317 
318 int
netbsd32_msgsnd(struct lwp * l,const struct netbsd32_msgsnd_args * uap,register_t * retval)319 netbsd32_msgsnd(struct lwp *l, const struct netbsd32_msgsnd_args *uap, register_t *retval)
320 {
321 	/* {
322 		syscallarg(int) msqid;
323 		syscallarg(const netbsd32_voidp) msgp;
324 		syscallarg(netbsd32_size_t) msgsz;
325 		syscallarg(int) msgflg;
326 	} */
327 
328 	return msgsnd1(l, SCARG(uap, msqid),
329 	    SCARG_P32(uap, msgp), SCARG(uap, msgsz),
330 	    SCARG(uap, msgflg), sizeof(netbsd32_long),
331 	    netbsd32_msgsnd_fetch_type);
332 }
333 
334 static int
netbsd32_msgrcv_put_type(const void * src,void * dst,size_t size)335 netbsd32_msgrcv_put_type(const void *src, void *dst, size_t size)
336 {
337 	netbsd32_long l32;
338 	const long *l = src;
339 
340 	KASSERT(size == sizeof(netbsd32_long));
341 
342 	l32 = (netbsd32_long)(*l);
343 	return copyout(&l32, dst, sizeof(l32));
344 }
345 
346 int
netbsd32_msgrcv(struct lwp * l,const struct netbsd32_msgrcv_args * uap,register_t * retval)347 netbsd32_msgrcv(struct lwp *l, const struct netbsd32_msgrcv_args *uap, register_t *retval)
348 {
349 	/* {
350 		syscallarg(int) msqid;
351 		syscallarg(netbsd32_voidp) msgp;
352 		syscallarg(netbsd32_size_t) msgsz;
353 		syscallarg(netbsd32_long) msgtyp;
354 		syscallarg(int) msgflg;
355 	} */
356 
357 	return msgrcv1(l, SCARG(uap, msqid),
358 	    SCARG_P32(uap, msgp), SCARG(uap, msgsz),
359 	    SCARG(uap, msgtyp), SCARG(uap, msgflg), sizeof(netbsd32_long),
360 	    netbsd32_msgrcv_put_type, retval);
361 }
362 #endif /* SYSVMSG */
363 
364 #if defined(SYSVSHM)
365 
366 int
netbsd32_shmat(struct lwp * l,const struct netbsd32_shmat_args * uap,register_t * retval)367 netbsd32_shmat(struct lwp *l, const struct netbsd32_shmat_args *uap, register_t *retval)
368 {
369 	/* {
370 		syscallarg(int) shmid;
371 		syscallarg(const netbsd32_voidp) shmaddr;
372 		syscallarg(int) shmflg;
373 	} */
374 	struct sys_shmat_args ua;
375 
376 	NETBSD32TO64_UAP(shmid);
377 	NETBSD32TOP_UAP(shmaddr, void);
378 	NETBSD32TO64_UAP(shmflg);
379 	return sys_shmat(l, &ua, retval);
380 }
381 
382 int
netbsd32___shmctl50(struct lwp * l,const struct netbsd32___shmctl50_args * uap,register_t * retval)383 netbsd32___shmctl50(struct lwp *l, const struct netbsd32___shmctl50_args *uap,
384     register_t *retval)
385 {
386 	/* {
387 		syscallarg(int) shmid;
388 		syscallarg(int) cmd;
389 		syscallarg(netbsd32_shmid_dsp_t) buf;
390 	} */
391 	struct shmid_ds ds;
392 	struct netbsd32_shmid_ds ds32;
393 	int error, cmd;
394 
395 	cmd = SCARG(uap, cmd);
396 	if (cmd == IPC_SET) {
397 		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32));
398 		if (error)
399 			return error;
400 		netbsd32_to_shmid_ds(&ds32, &ds);
401 	}
402 
403 	error = shmctl1(l, SCARG(uap, shmid), cmd,
404 	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL);
405 
406 	if (error == 0 && cmd == IPC_STAT) {
407 		netbsd32_from_shmid_ds(&ds, &ds32);
408 		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32));
409 	}
410 
411 	return error;
412 }
413 
414 int
netbsd32_shmdt(struct lwp * l,const struct netbsd32_shmdt_args * uap,register_t * retval)415 netbsd32_shmdt(struct lwp *l, const struct netbsd32_shmdt_args *uap, register_t *retval)
416 {
417 	/* {
418 		syscallarg(const netbsd32_voidp) shmaddr;
419 	} */
420 	struct sys_shmdt_args ua;
421 
422 	NETBSD32TOP_UAP(shmaddr, const char);
423 	return (sys_shmdt(l, &ua, retval));
424 }
425 
426 int
netbsd32_shmget(struct lwp * l,const struct netbsd32_shmget_args * uap,register_t * retval)427 netbsd32_shmget(struct lwp *l, const struct netbsd32_shmget_args *uap, register_t *retval)
428 {
429 	/* {
430 		syscallarg(netbsd32_key_t) key;
431 		syscallarg(netbsd32_size_t) size;
432 		syscallarg(int) shmflg;
433 	} */
434 	struct sys_shmget_args ua;
435 
436 	NETBSD32TOX_UAP(key, key_t);
437 	NETBSD32TOX_UAP(size, size_t);
438 	NETBSD32TO64_UAP(shmflg);
439 	return (sys_shmget(l, &ua, retval));
440 }
441 #endif /* SYSVSHM */
442