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