xref: /netbsd-src/sys/compat/netbsd32/netbsd32_ipc.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: netbsd32_ipc.c,v 1.13 2007/12/08 18:36:19 dsl 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  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_ipc.c,v 1.13 2007/12/08 18:36:19 dsl Exp $");
33 
34 #if defined(_KERNEL_OPT)
35 #include "opt_sysv.h"
36 #endif
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/ipc.h>
41 #include <sys/msg.h>
42 #include <sys/sem.h>
43 #include <sys/shm.h>
44 #include <sys/mount.h>
45 #include <sys/dirent.h>
46 
47 #include <sys/syscallargs.h>
48 #include <sys/proc.h>
49 
50 #include <compat/netbsd32/netbsd32.h>
51 #include <compat/netbsd32/netbsd32_syscallargs.h>
52 #include <compat/netbsd32/netbsd32_conv.h>
53 
54 #if defined(SYSVSEM)
55 
56 int
57 netbsd32___semctl14(struct lwp *l, void *v, register_t *retval)
58 {
59 	return do_netbsd32___semctl14(l, v, retval, NULL);
60 }
61 
62 int
63 do_netbsd32___semctl14(struct lwp *l, void *v, register_t *retval, void *vkarg)
64 {
65 	struct netbsd32___semctl14_args /* {
66 		syscallarg(int) semid;
67 		syscallarg(int) semnum;
68 		syscallarg(int) cmd;
69 		syscallarg(netbsd32_semunp_t) arg;
70 	} */ *uap = v;
71 	struct semid_ds sembuf;
72 	struct netbsd32_semid_ds sembuf32;
73 	int cmd, error;
74 	void *pass_arg;
75 	union __semun karg;
76 	union netbsd32_semun karg32;
77 
78 	cmd = SCARG(uap, cmd);
79 
80 	switch (cmd) {
81 	case IPC_SET:
82 	case IPC_STAT:
83 		pass_arg = &sembuf;
84 		break;
85 
86 	case GETALL:
87 	case SETVAL:
88 	case SETALL:
89 		pass_arg = &karg;
90 		break;
91 	default:
92 		pass_arg = NULL;
93 		break;
94 	}
95 
96 	if (pass_arg) {
97 		if (vkarg != NULL)
98 			karg32 = *(union netbsd32_semun *)vkarg;
99 		else {
100 			error = copyin(SCARG_P32(uap, arg), &karg32,
101 					sizeof(karg32));
102 			if (error)
103 				return error;
104 		}
105 		if (pass_arg == &karg) {
106 			switch (cmd) {
107 			case GETALL:
108 			case SETALL:
109 				karg.array = NETBSD32PTR64(karg32.array);
110 				break;
111 			case SETVAL:
112 				karg.val = karg32.val;
113 				break;
114 			}
115 		}
116 		if (cmd == IPC_SET) {
117 			error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32,
118 			    sizeof(sembuf32));
119 			if (error)
120 				return (error);
121 			netbsd32_to_semid_ds(&sembuf32, &sembuf);
122 		}
123 	}
124 
125 	error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd,
126 	    pass_arg, retval);
127 
128 	if (error == 0 && cmd == IPC_STAT) {
129 		netbsd32_from_semid_ds(&sembuf, &sembuf32);
130 		error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf),
131 		    sizeof(sembuf32));
132 	}
133 
134 	return (error);
135 }
136 
137 int
138 netbsd32_semget(struct lwp *l, void *v, register_t *retval)
139 {
140 	struct netbsd32_semget_args /* {
141 		syscallarg(netbsd32_key_t) key;
142 		syscallarg(int) nsems;
143 		syscallarg(int) semflg;
144 	} */ *uap = v;
145 	struct sys_semget_args ua;
146 
147 	NETBSD32TOX_UAP(key, key_t);
148 	NETBSD32TO64_UAP(nsems);
149 	NETBSD32TO64_UAP(semflg);
150 	return (sys_semget(l, &ua, retval));
151 }
152 
153 int
154 netbsd32_semop(struct lwp *l, void *v, register_t *retval)
155 {
156 	struct netbsd32_semop_args /* {
157 		syscallarg(int) semid;
158 		syscallarg(netbsd32_sembufp_t) sops;
159 		syscallarg(netbsd32_size_t) nsops;
160 	} */ *uap = v;
161 	struct sys_semop_args ua;
162 
163 	NETBSD32TO64_UAP(semid);
164 	NETBSD32TOP_UAP(sops, struct sembuf);
165 	NETBSD32TOX_UAP(nsops, size_t);
166 	return (sys_semop(l, &ua, retval));
167 }
168 
169 int
170 netbsd32_semconfig(struct lwp *l, void *v, register_t *retval)
171 {
172 	struct netbsd32_semconfig_args /* {
173 		syscallarg(int) flag;
174 	} */ *uap = v;
175 	struct sys_semconfig_args ua;
176 
177 	NETBSD32TO64_UAP(flag);
178 	return (sys_semconfig(l, &ua, retval));
179 }
180 #endif /* SYSVSEM */
181 
182 #if defined(SYSVMSG)
183 
184 int
185 netbsd32___msgctl13(struct lwp *l, void *v, register_t *retval)
186 {
187 	struct netbsd32___msgctl13_args /* {
188 		syscallarg(int) msqid;
189 		syscallarg(int) cmd;
190 		syscallarg(netbsd32_msqid_dsp_t) buf;
191 	} */ *uap = v;
192 	struct msqid_ds ds;
193 	struct netbsd32_msqid_ds ds32;
194 	int error, cmd;
195 
196 	cmd = SCARG(uap, cmd);
197 	if (cmd == IPC_SET) {
198 		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32));
199 		if (error)
200 			return error;
201 		netbsd32_to_msqid_ds(&ds32, &ds);
202 	}
203 
204 	error = msgctl1(l, SCARG(uap, msqid), cmd,
205 	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL);
206 
207 	if (error == 0 && cmd == IPC_STAT) {
208 		netbsd32_from_msqid_ds(&ds, &ds32);
209 		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32));
210 	}
211 
212 	return error;
213 }
214 
215 int
216 netbsd32_msgget(struct lwp *l, void *v, register_t *retval)
217 {
218 	struct netbsd32_msgget_args /* {
219 		syscallarg(netbsd32_key_t) key;
220 		syscallarg(int) msgflg;
221 	} */ *uap = v;
222 	struct sys_msgget_args ua;
223 
224 	NETBSD32TOX_UAP(key, key_t);
225 	NETBSD32TO64_UAP(msgflg);
226 	return sys_msgget(l, &ua, retval);
227 }
228 
229 static int
230 netbsd32_msgsnd_fetch_type(const void *src, void *dst, size_t size)
231 {
232 	netbsd32_long l32;
233 	long *l = dst;
234 	int error;
235 
236 	KASSERT(size == sizeof(netbsd32_long));
237 
238 	error = copyin(src, &l32, sizeof(l32));
239 	if (!error)
240 		*l = l32;
241 	return error;
242 }
243 
244 int
245 netbsd32_msgsnd(struct lwp *l, void *v, register_t *retval)
246 {
247 	struct netbsd32_msgsnd_args /* {
248 		syscallarg(int) msqid;
249 		syscallarg(const netbsd32_voidp) msgp;
250 		syscallarg(netbsd32_size_t) msgsz;
251 		syscallarg(int) msgflg;
252 	} */ *uap = v;
253 
254 	return msgsnd1(l, SCARG(uap, msqid),
255 	    SCARG_P32(uap, msgp), SCARG(uap, msgsz),
256 	    SCARG(uap, msgflg), sizeof(netbsd32_long),
257 	    netbsd32_msgsnd_fetch_type);
258 }
259 
260 static int
261 netbsd32_msgrcv_put_type(const void *src, void *dst, size_t size)
262 {
263 	netbsd32_long l32;
264 	const long *l = src;
265 
266 	KASSERT(size == sizeof(netbsd32_long));
267 
268 	l32 = (netbsd32_long)(*l);
269 	return copyout(&l32, dst, sizeof(l32));
270 }
271 
272 int
273 netbsd32_msgrcv(struct lwp *l, void *v, register_t *retval)
274 {
275 	struct netbsd32_msgrcv_args /* {
276 		syscallarg(int) msqid;
277 		syscallarg(netbsd32_voidp) msgp;
278 		syscallarg(netbsd32_size_t) msgsz;
279 		syscallarg(netbsd32_long) msgtyp;
280 		syscallarg(int) msgflg;
281 	} */ *uap = v;
282 
283 	return msgrcv1(l, SCARG(uap, msqid),
284 	    SCARG_P32(uap, msgp), SCARG(uap, msgsz),
285 	    SCARG(uap, msgtyp), SCARG(uap, msgflg), sizeof(netbsd32_long),
286 	    netbsd32_msgrcv_put_type, retval);
287 }
288 #endif /* SYSVMSG */
289 
290 #if defined(SYSVSHM)
291 
292 int
293 netbsd32_shmat(struct lwp *l, void *v, register_t *retval)
294 {
295 	struct netbsd32_shmat_args /* {
296 		syscallarg(int) shmid;
297 		syscallarg(const netbsd32_voidp) shmaddr;
298 		syscallarg(int) shmflg;
299 	} */ *uap = v;
300 	struct sys_shmat_args ua;
301 
302 	NETBSD32TO64_UAP(shmid);
303 	NETBSD32TOP_UAP(shmaddr, void);
304 	NETBSD32TO64_UAP(shmflg);
305 	return sys_shmat(l, &ua, retval);
306 }
307 
308 int
309 netbsd32___shmctl13(struct lwp *l, void *v, register_t *retval)
310 {
311 	struct netbsd32___shmctl13_args /* {
312 		syscallarg(int) shmid;
313 		syscallarg(int) cmd;
314 		syscallarg(netbsd32_shmid_dsp_t) buf;
315 	} */ *uap = v;
316 	struct shmid_ds ds;
317 	struct netbsd32_shmid_ds ds32;
318 	int error, cmd;
319 
320 	cmd = SCARG(uap, cmd);
321 	if (cmd == IPC_SET) {
322 		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32));
323 		if (error)
324 			return error;
325 		netbsd32_to_shmid_ds(&ds32, &ds);
326 	}
327 
328 	error = shmctl1(l, SCARG(uap, shmid), cmd,
329 	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL);
330 
331 	if (error == 0 && cmd == IPC_STAT) {
332 		netbsd32_from_shmid_ds(&ds, &ds32);
333 		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32));
334 	}
335 
336 	return error;
337 }
338 
339 int
340 netbsd32_shmdt(struct lwp *l, void *v, register_t *retval)
341 {
342 	struct netbsd32_shmdt_args /* {
343 		syscallarg(const netbsd32_voidp) shmaddr;
344 	} */ *uap = v;
345 	struct sys_shmdt_args ua;
346 
347 	NETBSD32TOP_UAP(shmaddr, const char);
348 	return (sys_shmdt(l, &ua, retval));
349 }
350 
351 int
352 netbsd32_shmget(struct lwp *l, void *v, register_t *retval)
353 {
354 	struct netbsd32_shmget_args /* {
355 		syscallarg(netbsd32_key_t) key;
356 		syscallarg(netbsd32_size_t) size;
357 		syscallarg(int) shmflg;
358 	} */ *uap = v;
359 	struct sys_shmget_args ua;
360 
361 	NETBSD32TOX_UAP(key, key_t)
362 	NETBSD32TOX_UAP(size, size_t)
363 	NETBSD32TO64_UAP(shmflg);
364 	return (sys_shmget(l, &ua, retval));
365 }
366 #endif /* SYSVSHM */
367