svr4_ipc.c revision 225617
1/*-
2 * Copyright (c) 1995 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Christos Zoulas.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *        This product includes software developed by the NetBSD
19 *        Foundation, Inc. and its contributors.
20 * 4. Neither the name of The NetBSD Foundation nor the names of its
21 *    contributors may be used to endorse or promote products derived
22 *    from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36/*-
37 * Portions of this code have been derived from software contributed
38 * to the FreeBSD Project by Mark Newton.
39 *
40 * Copyright (c) 1999 Mark Newton
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 *    notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 *    notice, this list of conditions and the following disclaimer in the
50 *    documentation and/or other materials provided with the distribution.
51 * 3. The name of the author may not be used to endorse or promote products
52 *    derived from this software without specific prior written permission
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
58 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 *
65 * XXX- This code is presently a no-op on FreeBSD (and isn't compiled due
66 * to preprocessor conditionals).  A nice project for a kernel hacking
67 * novice might be to MakeItGo, but I have more important fish to fry
68 * at present.
69 *
70 *	Derived from: $NetBSD: svr4_ipc.c,v 1.7 1998/10/19 22:43:00 tron Exp $
71 */
72
73#include <sys/cdefs.h>
74__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_ipc.c 225617 2011-09-16 13:58:51Z kmacy $");
75
76#include "opt_sysvipc.h"
77
78#include <sys/param.h>
79#include <sys/ipc.h>
80#include <sys/msg.h>
81#include <sys/proc.h>
82#include <sys/sem.h>
83#include <sys/shm.h>
84#include <sys/syscallsubr.h>
85#include <sys/sysproto.h>
86#include <sys/systm.h>
87#include <sys/time.h>
88
89#include <compat/svr4/svr4.h>
90#include <compat/svr4/svr4_types.h>
91#include <compat/svr4/svr4_signal.h>
92#include <compat/svr4/svr4_proto.h>
93#include <compat/svr4/svr4_util.h>
94#include <compat/svr4/svr4_ipc.h>
95
96#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM)
97static void svr4_to_bsd_ipc_perm(const struct svr4_ipc_perm *,
98				      struct ipc_perm *);
99static void bsd_to_svr4_ipc_perm(const struct ipc_perm *,
100				      struct svr4_ipc_perm *);
101#endif
102
103#ifdef SYSVSEM
104static void bsd_to_svr4_semid_ds(const struct semid_ds *,
105				      struct svr4_semid_ds *);
106static void svr4_to_bsd_semid_ds(const struct svr4_semid_ds *,
107				      struct semid_ds *);
108static int svr4_semop(struct thread *, void *);
109static int svr4_semget(struct thread *, void *);
110static int svr4_semctl(struct thread *, void *);
111#endif
112
113#ifdef SYSVMSG
114static void bsd_to_svr4_msqid_ds(const struct msqid_ds *,
115				      struct svr4_msqid_ds *);
116static void svr4_to_bsd_msqid_ds(const struct svr4_msqid_ds *,
117				      struct msqid_ds *);
118static int svr4_msgsnd(struct thread *, void *);
119static int svr4_msgrcv(struct thread *, void *);
120static int svr4_msgget(struct thread *, void *);
121static int svr4_msgctl(struct thread *, void *);
122#endif
123
124#ifdef SYSVSHM
125static void bsd_to_svr4_shmid_ds(const struct shmid_ds *,
126				      struct svr4_shmid_ds *);
127static void svr4_to_bsd_shmid_ds(const struct svr4_shmid_ds *,
128				      struct shmid_ds *);
129static int svr4_shmat(struct thread *, void *);
130static int svr4_shmdt(struct thread *, void *);
131static int svr4_shmget(struct thread *, void *);
132static int svr4_shmctl(struct thread *, void *);
133#endif
134
135#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM)
136
137static void
138svr4_to_bsd_ipc_perm(spp, bpp)
139	const struct svr4_ipc_perm *spp;
140	struct ipc_perm *bpp;
141{
142	bpp->key = spp->key;
143	bpp->uid = spp->uid;
144	bpp->gid = spp->gid;
145	bpp->cuid = spp->cuid;
146	bpp->cgid = spp->cgid;
147	bpp->mode = spp->mode;
148	bpp->seq = spp->seq;
149}
150
151static void
152bsd_to_svr4_ipc_perm(bpp, spp)
153	const struct ipc_perm *bpp;
154	struct svr4_ipc_perm *spp;
155{
156	spp->key = bpp->key;
157	spp->uid = bpp->uid;
158	spp->gid = bpp->gid;
159	spp->cuid = bpp->cuid;
160	spp->cgid = bpp->cgid;
161	spp->mode = bpp->mode;
162	spp->seq = bpp->seq;
163}
164#endif
165
166#ifdef SYSVSEM
167static void
168bsd_to_svr4_semid_ds(bds, sds)
169	const struct semid_ds *bds;
170	struct svr4_semid_ds *sds;
171{
172	bzero(sds, sizeof(*sds));
173	bsd_to_svr4_ipc_perm(&bds->sem_perm, &sds->sem_perm);
174	sds->sem_base = (struct svr4_sem *) bds->sem_base;
175	sds->sem_nsems = bds->sem_nsems;
176	sds->sem_otime = bds->sem_otime;
177	sds->sem_ctime = bds->sem_ctime;
178}
179
180static void
181svr4_to_bsd_semid_ds(sds, bds)
182	const struct svr4_semid_ds *sds;
183	struct semid_ds *bds;
184{
185	svr4_to_bsd_ipc_perm(&sds->sem_perm, &bds->sem_perm);
186	bds->sem_base = (struct sem *) bds->sem_base;
187	bds->sem_nsems = sds->sem_nsems;
188	bds->sem_otime = sds->sem_otime;
189	bds->sem_ctime = sds->sem_ctime;
190}
191
192struct svr4_sys_semctl_args {
193	int what;
194	int semid;
195	int semnum;
196	int cmd;
197	union semun arg;
198};
199
200static int
201svr4_semctl(td, v)
202	struct thread *td;
203	void *v;
204{
205	struct svr4_sys_semctl_args *uap = v;
206	struct svr4_semid_ds ss;
207	struct semid_ds bs;
208	union semun semun;
209	register_t rval;
210	int cmd, error;
211
212	switch (uap->cmd) {
213	case SVR4_SEM_GETZCNT:
214		cmd = GETZCNT;
215		break;
216
217	case SVR4_SEM_GETNCNT:
218		cmd = GETNCNT;
219		break;
220
221	case SVR4_SEM_GETPID:
222		cmd = GETPID;
223		break;
224
225	case SVR4_SEM_GETVAL:
226		cmd = GETVAL;
227		break;
228
229	case SVR4_SEM_SETVAL:
230		cmd = SETVAL;
231		break;
232
233	case SVR4_SEM_GETALL:
234		cmd = GETVAL;
235		break;
236
237	case SVR4_SEM_SETALL:
238		cmd = SETVAL;
239		break;
240
241	case SVR4_IPC_STAT:
242		cmd = IPC_STAT;
243		semun.buf = &bs;
244		error = kern_semctl(td, uap->semid, uap->semnum, cmd, &semun,
245		    &rval);
246		if (error)
247                        return (error);
248                bsd_to_svr4_semid_ds(&bs, &ss);
249		error = copyout(&ss, uap->arg.buf, sizeof(ss));
250		if (error == 0)
251			td->td_retval[0] = rval;
252		return (error);
253
254	case SVR4_IPC_SET:
255		cmd = IPC_SET;
256		error = copyin(uap->arg.buf, (caddr_t) &ss, sizeof ss);
257                if (error)
258                        return (error);
259                svr4_to_bsd_semid_ds(&ss, &bs);
260		semun.buf = &bs;
261		return (kern_semctl(td, uap->semid, uap->semnum, cmd, &semun,
262		    td->td_retval));
263
264	case SVR4_IPC_RMID:
265		cmd = IPC_RMID;
266		break;
267
268	default:
269		return EINVAL;
270	}
271
272	return (kern_semctl(td, uap->semid, uap->semnum, cmd, &uap->arg,
273	    td->td_retval));
274}
275
276struct svr4_sys_semget_args {
277	int what;
278	svr4_key_t key;
279	int nsems;
280	int semflg;
281};
282
283static int
284svr4_semget(td, v)
285	struct thread *td;
286	void *v;
287{
288	struct svr4_sys_semget_args *uap = v;
289	struct semget_args ap;
290
291	ap.key = uap->key;
292	ap.nsems = uap->nsems;
293	ap.semflg = uap->semflg;
294
295	return sys_semget(td, &ap);
296}
297
298struct svr4_sys_semop_args {
299	int what;
300	int semid;
301	struct svr4_sembuf * sops;
302	u_int nsops;
303};
304
305static int
306svr4_semop(td, v)
307	struct thread *td;
308	void *v;
309{
310	struct svr4_sys_semop_args *uap = v;
311	struct semop_args ap;
312
313	ap.semid = uap->semid;
314	/* These are the same */
315	ap.sops = (struct sembuf *) uap->sops;
316	ap.nsops = uap->nsops;
317
318	return sys_semop(td, &ap);
319}
320
321int
322svr4_sys_semsys(td, uap)
323	struct thread *td;
324	struct svr4_sys_semsys_args *uap;
325{
326
327	DPRINTF(("svr4_semsys(%d)\n", uap->what));
328
329	switch (uap->what) {
330	case SVR4_semctl:
331		return svr4_semctl(td, uap);
332	case SVR4_semget:
333		return svr4_semget(td, uap);
334	case SVR4_semop:
335		return svr4_semop(td, uap);
336	default:
337		return EINVAL;
338	}
339}
340
341MODULE_DEPEND(svr4elf, sysvsem, 1, 1, 1);
342#endif
343
344#ifdef SYSVMSG
345static void
346bsd_to_svr4_msqid_ds(bds, sds)
347	const struct msqid_ds *bds;
348	struct svr4_msqid_ds *sds;
349{
350	bzero(sds, sizeof(*sds));
351	bsd_to_svr4_ipc_perm(&bds->msg_perm, &sds->msg_perm);
352	sds->msg_first = (struct svr4_msg *) bds->msg_first;
353	sds->msg_last = (struct svr4_msg *) bds->msg_last;
354	sds->msg_cbytes = bds->msg_cbytes;
355	sds->msg_qnum = bds->msg_qnum;
356	sds->msg_qbytes = bds->msg_qbytes;
357	sds->msg_lspid = bds->msg_lspid;
358	sds->msg_lrpid = bds->msg_lrpid;
359	sds->msg_stime = bds->msg_stime;
360	sds->msg_rtime = bds->msg_rtime;
361	sds->msg_ctime = bds->msg_ctime;
362}
363
364static void
365svr4_to_bsd_msqid_ds(sds, bds)
366	const struct svr4_msqid_ds *sds;
367	struct msqid_ds *bds;
368{
369	svr4_to_bsd_ipc_perm(&sds->msg_perm, &bds->msg_perm);
370	bds->msg_first = (struct msg *) sds->msg_first;
371	bds->msg_last = (struct msg *) sds->msg_last;
372	bds->msg_cbytes = sds->msg_cbytes;
373	bds->msg_qnum = sds->msg_qnum;
374	bds->msg_qbytes = sds->msg_qbytes;
375	bds->msg_lspid = sds->msg_lspid;
376	bds->msg_lrpid = sds->msg_lrpid;
377	bds->msg_stime = sds->msg_stime;
378	bds->msg_rtime = sds->msg_rtime;
379	bds->msg_ctime = sds->msg_ctime;
380}
381
382struct svr4_sys_msgsnd_args {
383	int what;
384	int msqid;
385	void * msgp;
386	size_t msgsz;
387	int msgflg;
388};
389
390static int
391svr4_msgsnd(td, v)
392	struct thread *td;
393	void *v;
394{
395	struct svr4_sys_msgsnd_args *uap = v;
396	struct msgsnd_args ap;
397
398	ap.msqid = uap->msqid;
399	ap.msgp = uap->msgp;
400	ap.msgsz = uap->msgsz;
401	ap.msgflg = uap->msgflg;
402
403	return sys_msgsnd(td, &ap);
404}
405
406struct svr4_sys_msgrcv_args {
407	int what;
408	int msqid;
409	void * msgp;
410	size_t msgsz;
411	long msgtyp;
412	int msgflg;
413};
414
415static int
416svr4_msgrcv(td, v)
417	struct thread *td;
418	void *v;
419{
420	struct svr4_sys_msgrcv_args *uap = v;
421	struct msgrcv_args ap;
422
423	ap.msqid = uap->msqid;
424	ap.msgp = uap->msgp;
425	ap.msgsz = uap->msgsz;
426	ap.msgtyp = uap->msgtyp;
427	ap.msgflg = uap->msgflg;
428
429	return sys_msgrcv(td, &ap);
430}
431
432struct svr4_sys_msgget_args {
433	int what;
434	svr4_key_t key;
435	int msgflg;
436};
437
438static int
439svr4_msgget(td, v)
440	struct thread *td;
441	void *v;
442{
443	struct svr4_sys_msgget_args *uap = v;
444	struct msgget_args ap;
445
446	ap.key = uap->key;
447	ap.msgflg = uap->msgflg;
448
449	return sys_msgget(td, &ap);
450}
451
452struct svr4_sys_msgctl_args {
453	int what;
454	int msqid;
455	int cmd;
456	struct svr4_msqid_ds * buf;
457};
458
459static int
460svr4_msgctl(td, v)
461	struct thread *td;
462	void *v;
463{
464	struct svr4_sys_msgctl_args *uap = v;
465	struct svr4_msqid_ds ss;
466	struct msqid_ds bs;
467	int error;
468
469	switch (uap->cmd) {
470	case SVR4_IPC_STAT:
471		error = kern_msgctl(td, uap->msqid, IPC_STAT, &bs);
472		if (error)
473			return error;
474		bsd_to_svr4_msqid_ds(&bs, &ss);
475		return copyout(&ss, uap->buf, sizeof ss);
476
477	case SVR4_IPC_SET:
478		error = copyin(uap->buf, &ss, sizeof ss);
479		if (error)
480			return error;
481		svr4_to_bsd_msqid_ds(&ss, &bs);
482		return (kern_msgctl(td, uap->msqid, IPC_SET, &bs));
483
484	case SVR4_IPC_RMID:
485		return (kern_msgctl(td, uap->msqid, IPC_RMID, NULL));
486
487	default:
488		return EINVAL;
489	}
490}
491
492int
493svr4_sys_msgsys(td, uap)
494	struct thread *td;
495	struct svr4_sys_msgsys_args *uap;
496{
497
498	DPRINTF(("svr4_msgsys(%d)\n", uap->what));
499
500	switch (uap->what) {
501	case SVR4_msgsnd:
502		return svr4_msgsnd(td, uap);
503	case SVR4_msgrcv:
504		return svr4_msgrcv(td, uap);
505	case SVR4_msgget:
506		return svr4_msgget(td, uap);
507	case SVR4_msgctl:
508		return svr4_msgctl(td, uap);
509	default:
510		return EINVAL;
511	}
512}
513
514MODULE_DEPEND(svr4elf, sysvmsg, 1, 1, 1);
515#endif
516
517#ifdef SYSVSHM
518
519static void
520bsd_to_svr4_shmid_ds(bds, sds)
521	const struct shmid_ds *bds;
522	struct svr4_shmid_ds *sds;
523{
524	bzero(sds, sizeof(*sds));
525	bsd_to_svr4_ipc_perm(&bds->shm_perm, &sds->shm_perm);
526	sds->shm_segsz = bds->shm_segsz;
527	sds->shm_lkcnt = 0;
528	sds->shm_lpid = bds->shm_lpid;
529	sds->shm_cpid = bds->shm_cpid;
530	sds->shm_amp = 0;
531	sds->shm_nattch = bds->shm_nattch;
532	sds->shm_cnattch = 0;
533	sds->shm_atime = bds->shm_atime;
534	sds->shm_dtime = bds->shm_dtime;
535	sds->shm_ctime = bds->shm_ctime;
536}
537
538static void
539svr4_to_bsd_shmid_ds(sds, bds)
540	const struct svr4_shmid_ds *sds;
541	struct shmid_ds *bds;
542{
543	svr4_to_bsd_ipc_perm(&sds->shm_perm, &bds->shm_perm);
544	bds->shm_segsz = sds->shm_segsz;
545	bds->shm_lpid = sds->shm_lpid;
546	bds->shm_cpid = sds->shm_cpid;
547	bds->shm_nattch = sds->shm_nattch;
548	bds->shm_atime = sds->shm_atime;
549	bds->shm_dtime = sds->shm_dtime;
550	bds->shm_ctime = sds->shm_ctime;
551}
552
553struct svr4_sys_shmat_args {
554	int what;
555	int shmid;
556	void * shmaddr;
557	int shmflg;
558};
559
560static int
561svr4_shmat(td, v)
562	struct thread *td;
563	void *v;
564{
565	struct svr4_sys_shmat_args *uap = v;
566	struct shmat_args ap;
567
568	ap.shmid = uap->shmid;
569	ap.shmaddr = uap->shmaddr;
570	ap.shmflg = uap->shmflg;
571
572	return sys_shmat(td, &ap);
573}
574
575struct svr4_sys_shmdt_args {
576	int what;
577	void * shmaddr;
578};
579
580static int
581svr4_shmdt(td, v)
582	struct thread *td;
583	void *v;
584{
585	struct svr4_sys_shmdt_args *uap = v;
586	struct shmdt_args ap;
587
588	ap.shmaddr = uap->shmaddr;
589
590	return sys_shmdt(td, &ap);
591}
592
593struct svr4_sys_shmget_args {
594	int what;
595	key_t key;
596	int size;
597	int shmflg;
598};
599
600static int
601svr4_shmget(td, v)
602	struct thread *td;
603	void *v;
604{
605	struct svr4_sys_shmget_args *uap = v;
606	struct shmget_args ap;
607
608	ap.key = uap->key;
609	ap.size = uap->size;
610	ap.shmflg = uap->shmflg;
611
612	return sys_shmget(td, &ap);
613}
614
615struct svr4_sys_shmctl_args {
616	int what;
617	int shmid;
618	int cmd;
619	struct svr4_shmid_ds * buf;
620};
621
622int
623svr4_shmctl(td, v)
624	struct thread *td;
625	void *v;
626{
627	struct svr4_sys_shmctl_args *uap = v;
628	struct shmid_ds bs;
629	struct svr4_shmid_ds ss;
630	size_t bufsize;
631	int cmd, error;
632
633	if (uap->buf != NULL) {
634		switch (uap->cmd) {
635		case SVR4_IPC_SET:
636		case SVR4_SHM_LOCK:
637		case SVR4_SHM_UNLOCK:
638			error = copyin(uap->buf, &ss, sizeof(ss));
639			if (error)
640				return (error);
641			svr4_to_bsd_shmid_ds(&ss, &bs);
642			break;
643		default:
644			return (EINVAL);
645		}
646	}
647
648	switch (uap->cmd) {
649	case SVR4_IPC_STAT:
650		cmd = IPC_STAT;
651		break;
652	case SVR4_IPC_SET:
653		cmd = IPC_SET;
654		break;
655	case SVR4_IPC_RMID:
656		cmd = IPC_RMID;
657		break;
658	case SVR4_SHM_LOCK:
659		cmd = SHM_LOCK;
660		break;
661	case SVR4_SHM_UNLOCK:
662		cmd = SHM_UNLOCK;
663		break;
664	default:
665		return (EINVAL);
666	}
667
668	error = kern_shmctl(td, uap->shmid, cmd, &bs, &bufsize);
669	if (error)
670		return (error);
671
672	switch (uap->cmd) {
673	case SVR4_IPC_STAT:
674		if (uap->buf != NULL) {
675			bsd_to_svr4_shmid_ds(&bs, &ss);
676			error = copyout(&ss, uap->buf, sizeof(ss));
677		}
678		break;
679	}
680
681	return (error);
682}
683
684int
685svr4_sys_shmsys(td, uap)
686	struct thread *td;
687	struct svr4_sys_shmsys_args *uap;
688{
689
690	DPRINTF(("svr4_shmsys(%d)\n", uap->what));
691
692	switch (uap->what) {
693	case SVR4_shmat:
694		return svr4_shmat(td, uap);
695	case SVR4_shmdt:
696		return svr4_shmdt(td, uap);
697	case SVR4_shmget:
698		return svr4_shmget(td, uap);
699	case SVR4_shmctl:
700		return svr4_shmctl(td, uap);
701	default:
702		return ENOSYS;
703	}
704}
705
706MODULE_DEPEND(svr4elf, sysvshm, 1, 1, 1);
707#endif /* SYSVSHM */
708