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