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
55extern 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
63static 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
114MODULE(MODULE_CLASS_EXEC, compat_netbsd32_sysvipc, "sysv_ipc,compat_netbsd32");
115
116static int
117compat_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
140int
141netbsd32_____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
210int
211netbsd32_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
226int
227netbsd32_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
242int
243netbsd32_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
257int
258netbsd32___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
289int
290netbsd32_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
303static int
304netbsd32_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
318int
319netbsd32_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
334static int
335netbsd32_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
346int
347netbsd32_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
366int
367netbsd32_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
382int
383netbsd32___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
414int
415netbsd32_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
426int
427netbsd32_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