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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 | |