1 /*	$NetBSD: ibcs2_ipc.c,v 1.27 2007/12/20 23:02:49 dsl Exp $	*/
2 
3 /*
4  * Copyright (c) 1995 Scott Bartram
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. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: ibcs2_ipc.c,v 1.27 2007/12/20 23:02:49 dsl Exp $");
29 
30 #if defined(_KERNEL_OPT)
31 #include "opt_sysv.h"
32 #endif
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/namei.h>
37 #include <sys/proc.h>
38 #include <sys/file.h>
39 #include <sys/stat.h>
40 #include <sys/filedesc.h>
41 #include <sys/ioctl.h>
42 #include <sys/ipc.h>
43 #include <sys/kernel.h>
44 #include <sys/mbuf.h>
45 #include <sys/mman.h>
46 #include <sys/mount.h>
47 #include <sys/reboot.h>
48 #include <sys/resource.h>
49 #include <sys/resourcevar.h>
50 #include <sys/signal.h>
51 #include <sys/signalvar.h>
52 #include <sys/socket.h>
53 #include <sys/time.h>
54 #include <sys/times.h>
55 #include <sys/vnode.h>
56 #include <sys/uio.h>
57 #include <sys/wait.h>
58 #include <sys/utsname.h>
59 #include <sys/unistd.h>
60 #include <sys/msg.h>
61 #include <sys/sem.h>
62 #include <sys/shm.h>
63 #include <sys/syscallargs.h>
64 
65 #include <compat/ibcs2/ibcs2_types.h>
66 #include <compat/ibcs2/ibcs2_signal.h>
67 #include <compat/ibcs2/ibcs2_syscallargs.h>
68 #include <compat/ibcs2/ibcs2_util.h>
69 
70 #include <compat/sys/sem.h>
71 #include <compat/sys/shm.h>
72 #include <compat/sys/msg.h>
73 
74 /* Verify that the standard values are correct. */
75 typedef char x[IPC_RMID == 0 && IPC_SET == 1 && IPC_STAT == 2 ? 1 : -1];
76 
77 struct ibcs2_ipc_perm {
78 	ibcs2_uid_t uid;
79 	ibcs2_gid_t gid;
80 	ibcs2_uid_t cuid;
81 	ibcs2_gid_t cgid;
82 	ibcs2_mode_t mode;
83 	u_short seq;
84 	ibcs2_key_t key;
85 };
86 
87 struct ibcs2_msqid_ds {
88 	struct ibcs2_ipc_perm msg_perm;
89 	struct __msg *msg_first;	/* kernel address don't copyout */
90 	struct __msg *msg_last;		/* kernel address don't copyout */
91 	u_short msg_cbytes;
92 	u_short msg_qnum;
93 	u_short msg_qbytes;
94 	u_short msg_lspid;
95 	u_short msg_lrpid;
96 	ibcs2_time_t msg_stime;
97 	ibcs2_time_t msg_rtime;
98 	ibcs2_time_t msg_ctime;
99 };
100 
101 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
102 static void
cvt_perm2iperm(const struct ipc_perm * bp,struct ibcs2_ipc_perm * ibp)103 cvt_perm2iperm(const struct ipc_perm *bp, struct ibcs2_ipc_perm *ibp)
104 {
105 	ibp->cuid = bp->cuid;
106 	ibp->cgid = bp->cgid;
107 	ibp->uid = bp->uid;
108 	ibp->gid = bp->gid;
109 	ibp->mode = bp->mode;
110 	ibp->seq = bp->_seq;
111 	ibp->key = bp->_key;
112 }
113 
114 static void
cvt_iperm2perm(const struct ibcs2_ipc_perm * ibp,struct ipc_perm * bp)115 cvt_iperm2perm(const struct ibcs2_ipc_perm *ibp, struct ipc_perm *bp)
116 {
117 	bp->cuid = ibp->cuid;
118 	bp->cgid = ibp->cgid;
119 	bp->uid = ibp->uid;
120 	bp->gid = ibp->gid;
121 	bp->mode = ibp->mode;
122 	bp->_seq = ibp->seq;
123 	bp->_key = ibp->key;
124 }
125 #endif /* SYSVMSG || SYSVSEM || SYSVMSG */
126 
127 #ifdef SYSVMSG
128 
129 /*
130  * iBCS2 msgsys call
131  */
132 
133 static void
cvt_msqid2imsqid(const struct msqid_ds * bp,struct ibcs2_msqid_ds * ibp)134 cvt_msqid2imsqid(const struct msqid_ds *bp, struct ibcs2_msqid_ds *ibp)
135 {
136 	cvt_perm2iperm(&bp->msg_perm, &ibp->msg_perm);
137 	ibp->msg_first = NULL;
138 	ibp->msg_last = NULL;
139 	ibp->msg_cbytes = bp->_msg_cbytes;
140 	ibp->msg_qnum = bp->msg_qnum;
141 	ibp->msg_qbytes = bp->msg_qbytes;
142 	ibp->msg_lspid = bp->msg_lspid;
143 	ibp->msg_lrpid = bp->msg_lrpid;
144 	ibp->msg_stime = bp->msg_stime;
145 	ibp->msg_rtime = bp->msg_rtime;
146 	ibp->msg_ctime = bp->msg_ctime;
147 }
148 
149 static void
cvt_imsqid2msqid(struct ibcs2_msqid_ds * ibp,struct msqid_ds * bp)150 cvt_imsqid2msqid(struct ibcs2_msqid_ds *ibp, struct msqid_ds *bp)
151 {
152 	cvt_iperm2perm(&ibp->msg_perm, &bp->msg_perm);
153 	bp->_msg_first = NULL;
154 	bp->_msg_last = NULL;
155 	bp->_msg_cbytes = ibp->msg_cbytes;
156 	bp->msg_qnum = ibp->msg_qnum;
157 	bp->msg_qbytes = ibp->msg_qbytes;
158 	bp->msg_lspid = ibp->msg_lspid;
159 	bp->msg_lrpid = ibp->msg_lrpid;
160 	bp->msg_stime = ibp->msg_stime;
161 	bp->msg_rtime = ibp->msg_rtime;
162 	bp->msg_ctime = ibp->msg_ctime;
163 }
164 
165 static int
do_compat_10_sys_msgsys(struct lwp * l,const struct ibcs2_sys_msgsys_args * uap,register_t * retval,int which)166 do_compat_10_sys_msgsys(struct lwp *l, const struct ibcs2_sys_msgsys_args *uap,
167     register_t *retval, int which)
168 {
169     struct compat_10_sys_msgsys_args bsd_ua;
170 
171     SCARG(&bsd_ua, which) = which;
172     SCARG(&bsd_ua, a2) = SCARG(uap, a2);
173     SCARG(&bsd_ua, a3) = SCARG(uap, a3);
174     SCARG(&bsd_ua, a4) = SCARG(uap, a4);
175     SCARG(&bsd_ua, a5) = SCARG(uap, a5);
176     SCARG(&bsd_ua, a6) = SCARG(uap, a6);
177 
178     return compat_10_sys_msgsys(l, &bsd_ua, retval);
179 }
180 
181 int
ibcs2_sys_msgsys(struct lwp * l,const struct ibcs2_sys_msgsys_args * uap,register_t * retval)182 ibcs2_sys_msgsys(struct lwp *l, const struct ibcs2_sys_msgsys_args *uap, register_t *retval)
183 {
184 #ifdef SYSVMSG
185 	/* {
186 		syscallarg(int) which;
187 		syscallarg(int) a2;
188 		syscallarg(int) a3;
189 		syscallarg(int) a4;
190 		syscallarg(int) a5;
191 		syscallarg(int) a6;
192 	} */
193 	int error;
194 	struct msqid_ds msqbuf;
195 	struct ibcs2_msqid_ds msqbuf_ibcs2, *ibp;
196 
197 	switch (SCARG(uap, which)) {
198 	case 0:				/* msgget */
199 		return do_compat_10_sys_msgsys(l, uap, retval, 1);
200 	case 1: 			/* msgctl */
201 		ibp = (void *)SCARG(uap, a4);
202 		switch (SCARG(uap, a3)) {
203 		case IPC_STAT:
204 			error = msgctl1(l, SCARG(uap, a2), IPC_STAT, &msqbuf);
205 			if (error == 0) {
206 				cvt_msqid2imsqid(&msqbuf, &msqbuf_ibcs2);
207 				error = copyout(&msqbuf_ibcs2, ibp,
208 				    sizeof msqbuf_ibcs2);
209 			}
210 			return error;
211 		case IPC_SET:
212 			error = copyin(ibp, &msqbuf_ibcs2, sizeof msqbuf_ibcs2);
213 			if (error == 0) {
214 				cvt_imsqid2msqid(&msqbuf_ibcs2, &msqbuf);
215 				error = msgctl1(l, SCARG(uap, a2),
216 				    IPC_SET, &msqbuf);
217 			}
218 			return error;
219 		case IPC_RMID:
220 			return msgctl1(l, SCARG(uap, a2), IPC_RMID, NULL);
221 		}
222 		return EINVAL;
223 	case 2:				/* msgrcv */
224 		return do_compat_10_sys_msgsys(l, uap, retval, 3);
225 	case 3:				/* msgsnd */
226 		return do_compat_10_sys_msgsys(l, uap, retval, 2);
227 	default:
228 		break;
229 	}
230 #endif
231 	return EINVAL;
232 }
233 
234 #endif /* SYSVMSG */
235 
236 #ifdef SYSVSEM
237 
238 /*
239  * iBCS2 semsys call
240  */
241 
242 struct ibcs2_semid_ds {
243 	struct ibcs2_ipc_perm sem_perm;
244 	struct ibcs2_sem *sem_base;
245 	u_short sem_nsems;
246 	u_short pad1;
247 	ibcs2_time_t sem_otime;
248 	ibcs2_time_t sem_ctime;
249 };
250 
251 struct ibcs2_sem {
252         u_short semval;
253 	ibcs2_pid_t sempid;
254 	u_short semncnt;
255 	u_short semzcnt;
256 };
257 
258 #ifdef notdef
259 static void cvt_sem2isem(struct sem *, struct ibcs2_sem *);
260 static void cvt_isem2sem(struct ibcs2_sem *, struct sem *);
261 
262 static void
cvt_sem2isem(struct __sem * bp,struct ibcs2_sem * ibp)263 cvt_sem2isem(struct __sem *bp, struct ibcs2_sem *ibp)
264 {
265 	ibp->semval = bp->semval;
266 	ibp->sempid = bp->sempid;
267 	ibp->semncnt = bp->semncnt;
268 	ibp->semzcnt = bp->semzcnt;
269 }
270 
271 static void
cvt_isem2sem(struct ibcs2_sem * ibp,struct __sem * bp)272 cvt_isem2sem(struct ibcs2_sem *ibp, struct __sem *bp)
273 {
274 	bp->semval = ibp->semval;
275 	bp->sempid = ibp->sempid;
276 	bp->semncnt = ibp->semncnt;
277 	bp->semzcnt = ibp->semzcnt;
278 }
279 #endif
280 
281 static void
cvt_semid2isemid(const struct semid_ds * bp,struct ibcs2_semid_ds * ibp)282 cvt_semid2isemid(const struct semid_ds *bp, struct ibcs2_semid_ds *ibp)
283 {
284 	cvt_perm2iperm(&bp->sem_perm, &ibp->sem_perm);
285 	ibp->sem_base = (struct ibcs2_sem *)bp->_sem_base;
286 	ibp->sem_nsems = bp->sem_nsems;
287 	ibp->sem_otime = bp->sem_otime;
288 	ibp->sem_ctime = bp->sem_ctime;
289 }
290 
291 
292 static void
cvt_isemid2semid(const struct ibcs2_semid_ds * ibp,struct semid_ds * bp)293 cvt_isemid2semid(const struct ibcs2_semid_ds *ibp, struct semid_ds *bp)
294 {
295 	cvt_iperm2perm(&ibp->sem_perm, &bp->sem_perm);
296 	bp->_sem_base = (struct __sem *)ibp->sem_base;
297 	bp->sem_nsems = ibp->sem_nsems;
298 	bp->sem_otime = ibp->sem_otime;
299 	bp->sem_ctime = ibp->sem_ctime;
300 }
301 
302 int
ibcs2_sys_semsys(struct lwp * l,const struct ibcs2_sys_semsys_args * uap,register_t * retval)303 ibcs2_sys_semsys(struct lwp *l, const struct ibcs2_sys_semsys_args *uap, register_t *retval)
304 {
305 #ifdef SYSVSEM
306 	/* {
307 		syscallarg(int) which;
308 		syscallarg(int) a2;
309 		syscallarg(int) a3;
310 		syscallarg(int) a4;
311 		syscallarg(int) a5;
312 	} */
313 	struct semid_ds sembuf;
314 	struct ibcs2_semid_ds isembuf;
315 	void *pass_arg;
316 	int a5 = SCARG(uap, a5);
317 	int error;
318 
319 	switch (SCARG(uap, which)) {
320 	case 0:					/* semctl */
321 #define	semctl_semid	SCARG(uap, a2)
322 #define	semctl_semnum	SCARG(uap, a3)
323 #define	semctl_cmd	SCARG(uap, a4)
324 #define	semctl_arg	((union __semun *)&a5)
325 		pass_arg = get_semctl_arg(semctl_cmd, &sembuf, semctl_arg);
326 		if (semctl_cmd == IPC_SET) {
327 			error = copyin(semctl_arg->buf, &isembuf, sizeof isembuf);
328 			if (error != 0)
329 				return error;
330 			cvt_isemid2semid(&isembuf, &sembuf);
331 		}
332 		error = semctl1(l, semctl_semid, semctl_semnum, semctl_cmd,
333 		    pass_arg, retval);
334 		if (error == 0 && semctl_cmd == IPC_STAT) {
335 			cvt_semid2isemid(&sembuf, &isembuf);
336 			error = copyout(&isembuf, semctl_arg->buf, sizeof(isembuf));
337 		}
338 		return error;
339 #undef	semctl_semid
340 #undef	semctl_semnum
341 #undef	semctl_cmd
342 #undef	semctl_arg
343 
344 	case 1:				/* semget */
345 		return compat_10_sys_semsys(l, (const void *)uap, retval);
346 
347 	case 2:				/* semop */
348 		return compat_10_sys_semsys(l, (const void *)uap, retval);
349 	}
350 #endif
351 	return EINVAL;
352 }
353 
354 #endif /* SYSVSEM */
355 
356 #ifdef SYSVSHM
357 
358 /*
359  * iBCS2 shmsys call
360  */
361 
362 struct ibcs2_shmid_ds {
363         struct ibcs2_ipc_perm shm_perm;
364 	int shm_segsz;
365 	int pad1;
366 	char pad2[4];
367 	u_short shm_lpid;
368 	u_short shm_cpid;
369 	u_short shm_nattch;
370 	u_short shm_cnattch;
371 	ibcs2_time_t shm_atime;
372 	ibcs2_time_t shm_dtime;
373 	ibcs2_time_t shm_ctime;
374 };
375 
376 static void
cvt_shmid2ishmid(const struct shmid_ds * bp,struct ibcs2_shmid_ds * ibp)377 cvt_shmid2ishmid(const struct shmid_ds *bp, struct ibcs2_shmid_ds *ibp)
378 {
379 	cvt_perm2iperm(&bp->shm_perm, &ibp->shm_perm);
380 	ibp->shm_segsz = bp->shm_segsz;
381 	ibp->shm_lpid = bp->shm_lpid;
382 	ibp->shm_cpid = bp->shm_cpid;
383 	ibp->shm_nattch = bp->shm_nattch;
384 	ibp->shm_cnattch = 0;			/* ignored anyway */
385 	ibp->shm_atime = bp->shm_atime;
386 	ibp->shm_dtime = bp->shm_dtime;
387 	ibp->shm_ctime = bp->shm_ctime;
388 }
389 
390 static void
cvt_ishmid2shmid(const struct ibcs2_shmid_ds * ibp,struct shmid_ds * bp)391 cvt_ishmid2shmid(const struct ibcs2_shmid_ds *ibp, struct shmid_ds *bp)
392 {
393 	cvt_iperm2perm(&ibp->shm_perm, &bp->shm_perm);
394 	bp->shm_segsz = ibp->shm_segsz;
395 	bp->shm_lpid = ibp->shm_lpid;
396 	bp->shm_cpid = ibp->shm_cpid;
397 	bp->shm_nattch = ibp->shm_nattch;
398 	bp->shm_atime = ibp->shm_atime;
399 	bp->shm_dtime = ibp->shm_dtime;
400 	bp->shm_ctime = ibp->shm_ctime;
401 	bp->_shm_internal = (void *)0;		/* ignored anyway */
402 	return;
403 }
404 
405 int
ibcs2_sys_shmsys(struct lwp * l,const struct ibcs2_sys_shmsys_args * uap,register_t * retval)406 ibcs2_sys_shmsys(struct lwp *l, const struct ibcs2_sys_shmsys_args *uap, register_t *retval)
407 {
408 #ifdef SYSVSHM
409 	/* {
410 		syscallarg(int) which;
411 		syscallarg(int) a2;
412 		syscallarg(int) a3;
413 		syscallarg(int) a4;
414 	} */
415 	struct shmid_ds shmbuf;
416 	struct ibcs2_shmid_ds *isp, ishmbuf;
417 	int cmd, error;
418 
419 	switch (SCARG(uap, which)) {
420 	case 0:						/* shmat */
421 		break;
422 
423 	case 1:						/* shmctl */
424 		cmd = SCARG(uap, a3);
425 		isp = (struct ibcs2_shmid_ds *)SCARG(uap, a4);
426 		if (cmd == IPC_SET) {
427 			error = copyin(isp, &ishmbuf, sizeof(ishmbuf));
428 			if (error)
429 				return error;
430 			cvt_ishmid2shmid(&ishmbuf, &shmbuf);
431 		}
432 
433 		error = shmctl1(l, SCARG(uap, a2), cmd,
434 		    (cmd == IPC_SET || cmd == IPC_STAT) ? &shmbuf : NULL);
435 
436 		if (error == 0 && cmd == IPC_STAT) {
437 			cvt_shmid2ishmid(&shmbuf, &ishmbuf);
438 			error = copyout(&ishmbuf, isp, sizeof(ishmbuf));
439 		}
440 		return error;
441 
442 	case 2:						/* shmdt */
443 		break;
444 
445 	case 3:						/* shmget */
446 		break;
447 
448 	default:
449 		return EINVAL;
450 	}
451 	return compat_10_sys_shmsys(l, (const void *)uap, retval);
452 #else
453 	return EINVAL;
454 #endif
455 }
456 
457 #endif /* SYSVSHM */
458