1 /**	$MirOS: src/sys/compat/common/kern_ipc_23.c,v 1.2 2005/03/06 21:27:29 tg Exp $ */
2 /*	$OpenBSD: kern_ipc_23.c,v 1.5 2004/07/15 11:25:59 millert Exp $	*/
3 
4 /*
5  * Copyright (c) 2004 Todd C. Miller <Todd.Miller@courtesan.com>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/kernel.h>
23 #include <sys/proc.h>
24 #include <sys/msg.h>
25 #include <sys/sem.h>
26 #include <sys/shm.h>
27 
28 #include <sys/mount.h>
29 #include <sys/syscallargs.h>
30 
31 #if defined(COMPAT_OPENBSD)
32 
33 /*
34  * Convert between new and old struct {msq,sem,shm}id_ds (both ways)
35  */
36 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
37 #define cvt_ds(to, from, type, base) do {				\
38 	(to)->type##_perm.cuid = (from)->type##_perm.cuid;		\
39 	(to)->type##_perm.cgid = (from)->type##_perm.cgid;		\
40 	(to)->type##_perm.uid = (from)->type##_perm.uid;		\
41 	(to)->type##_perm.gid = (from)->type##_perm.gid;		\
42 	(to)->type##_perm.mode = (from)->type##_perm.mode & 0xffffU;	\
43 	(to)->type##_perm.seq = (from)->type##_perm.seq;		\
44 	(to)->type##_perm.key = (from)->type##_perm.key;		\
45 	memmove((caddr_t)&(to)->base, (caddr_t)&(from)->base,		\
46 	    sizeof(*(to)) - ((caddr_t)&(to)->base - (caddr_t)to));	\
47 } while (0)
48 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
49 
50 #ifdef SYSVMSG
51 /*
52  * Copy a struct msqid_ds23 from userland and convert to struct msqid_ds
53  */
54 static int
msqid_copyin(const void * uaddr,void * kaddr,size_t len)55 msqid_copyin(const void *uaddr, void *kaddr, size_t len)
56 {
57 	struct msqid_ds *msqbuf = kaddr;
58 	struct msqid_ds23 omsqbuf;
59 	int error;
60 
61 	if (len != sizeof(struct msqid_ds))
62 		return (EFAULT);
63 	if ((error = copyin(uaddr, &omsqbuf, sizeof(omsqbuf))) == 0)
64 		cvt_ds(msqbuf, &omsqbuf, msg, msg_first);
65 	return (error);
66 }
67 
68 /*
69  * Convert a struct msqid_ds to struct msqid_ds23 and copy to userland
70  */
71 static int
msqid_copyout(const void * kaddr,void * uaddr,size_t len)72 msqid_copyout(const void *kaddr, void *uaddr, size_t len)
73 {
74 	const struct msqid_ds *msqbuf = kaddr;
75 	struct msqid_ds23 omsqbuf;
76 
77 	if (len != sizeof(struct msqid_ds))
78 		return (EFAULT);
79 	cvt_ds(&omsqbuf, msqbuf, msg, msg_first);
80 	return (copyout(&omsqbuf, uaddr, sizeof(omsqbuf)));
81 }
82 
83 /*
84  * OpenBSD 2.3 msgctl(2) with 16bit values in struct ipcperm.
85  */
86 int
compat_23_sys_msgctl(struct proc * p,void * v,register_t * retval)87 compat_23_sys_msgctl(struct proc *p, void *v, register_t *retval)
88 {
89 	struct compat_23_sys_msgctl_args /* {
90 		syscallarg(int) msqid;
91 		syscallarg(int) cmd;
92 		syscallarg(struct msqid_ds23 *) buf;
93 	} */ *uap = v;
94 
95 	return (msgctl1(p, SCARG(uap, msqid), SCARG(uap, cmd),
96 	    (caddr_t)SCARG(uap, buf), msqid_copyin, msqid_copyout));
97 }
98 #endif /* SYSVMSG */
99 
100 #ifdef SYSVSEM
101 /*
102  * Copy a struct semid_ds23 from userland and convert to struct semid_ds
103  */
104 static int
semid_copyin(const void * uaddr,void * kaddr,size_t len)105 semid_copyin(const void *uaddr, void *kaddr, size_t len)
106 {
107 	struct semid_ds *sembuf = kaddr;
108 	struct semid_ds23 osembuf;
109 	int error;
110 
111 	if (len != sizeof(struct semid_ds))
112 		return (EFAULT);
113 	if ((error = copyin(uaddr, &osembuf, sizeof(osembuf))) == 0)
114 		cvt_ds(sembuf, &osembuf, sem, sem_base);
115 	return (error);
116 }
117 
118 /*
119  * Convert a struct semid_ds to struct semid_ds23 and copy to userland
120  */
121 static int
semid_copyout(const void * kaddr,void * uaddr,size_t len)122 semid_copyout(const void *kaddr, void *uaddr, size_t len)
123 {
124 	const struct semid_ds *sembuf = kaddr;
125 	struct semid_ds23 osembuf;
126 
127 	if (len != sizeof(struct semid_ds))
128 		return (EFAULT);
129 	cvt_ds(&osembuf, sembuf, sem, sem_base);
130 	return (copyout(&osembuf, uaddr, sizeof(osembuf)));
131 }
132 
133 /*
134  * OpenBSD 2.3 semctl(2) with 16bit values in struct ipcperm.
135  */
136 int
compat_23_sys___semctl(struct proc * p,void * v,register_t * retval)137 compat_23_sys___semctl(struct proc *p, void *v, register_t *retval)
138 {
139 	struct compat_23_sys___semctl_args /* {
140 		syscallarg(int) semid;
141 		syscallarg(int) semnum;
142 		syscallarg(int) cmd;
143 		syscallarg(union semun *) arg;
144 	} */ *uap = v;
145 	union semun arg;
146 	int error = 0, cmd = SCARG(uap, cmd);
147 
148 	switch (cmd) {
149 	case IPC_SET:
150 	case IPC_STAT:
151 	case GETALL:
152 	case SETVAL:
153 	case SETALL:
154 		error = copyin(SCARG(uap, arg), &arg, sizeof(arg));
155 		break;
156 	}
157 	if (error == 0) {
158 		error = semctl1(p, SCARG(uap, semid), SCARG(uap, semnum),
159 		    cmd, &arg, retval, semid_copyin, semid_copyout);
160 	}
161 	return (error);
162 }
163 #endif /* SYSVSEM */
164 
165 #ifdef SYSVSHM
166 /*
167  * Copy a struct shmid_ds23 from userland and convert to struct shmid_ds
168  */
169 static int
shmid_copyin(const void * uaddr,void * kaddr,size_t len)170 shmid_copyin(const void *uaddr, void *kaddr, size_t len)
171 {
172 	struct shmid_ds *shmbuf = kaddr;
173 	struct shmid_ds23 oshmbuf;
174 	int error;
175 
176 	if (len != sizeof(struct shmid_ds))
177 		return (EFAULT);
178 	if ((error = copyin(uaddr, &oshmbuf, sizeof(oshmbuf))) == 0)
179 		cvt_ds(shmbuf, &oshmbuf, shm, shm_segsz);
180 	return (error);
181 }
182 
183 /*
184  * Convert a struct shmid_ds to struct shmid_ds23 and copy to userland
185  */
186 static int
shmid_copyout(const void * kaddr,void * uaddr,size_t len)187 shmid_copyout(const void *kaddr, void *uaddr, size_t len)
188 {
189 	const struct shmid_ds *shmbuf = kaddr;
190 	struct shmid_ds23 oshmbuf;
191 
192 	if (len != sizeof(struct shmid_ds))
193 		return (EFAULT);
194 	cvt_ds(&oshmbuf, shmbuf, shm, shm_segsz);
195 	return (copyout(&oshmbuf, uaddr, sizeof(oshmbuf)));
196 }
197 
198 /*
199  * OpenBSD 2.3 shmctl(2) with 16bit values in struct ipcperm.
200  */
201 int
compat_23_sys_shmctl(struct proc * p,void * v,register_t * retval)202 compat_23_sys_shmctl(struct proc *p, void *v, register_t *retval)
203 {
204 	struct compat_23_sys_shmctl_args /* {
205 		syscallarg(int) shmid;
206 		syscallarg(int) cmd;
207 		syscallarg(struct shmid_ds23 *) buf;
208 	} */ *uap = v;
209 
210 	return (shmctl1(p, SCARG(uap, shmid), SCARG(uap, cmd),
211 	    (caddr_t)SCARG(uap, buf), shmid_copyin, shmid_copyout));
212 }
213 #endif /* SYSVSHM */
214 #endif /* def COMPAT_OPENBSD */
215