1 /**	$MirOS: src/sys/compat/common/kern_ipc_35.c,v 1.3 2005/08/02 11:16:29 tg Exp $ */
2 /*	$OpenBSD: kern_ipc_35.c,v 1.3 2004/07/15 11:00:12 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 #ifdef COMPAT_OPENBSD
32 
33 #ifdef SYSVMSG
34 /*
35  * Old-style shmget(2) used int for the size parameter, we now use size_t.
36  */
37 int
compat_35_sys_shmget(struct proc * p,void * v,register_t * retval)38 compat_35_sys_shmget(struct proc *p, void *v, register_t *retval)
39 {
40 	struct compat_35_sys_shmget_args /* {
41 		syscallarg(key_t) key;
42 		syscallarg(int) size;
43 		syscallarg(int) shmflg;
44 	} */ *uap = v;
45 	struct sys_shmget_args /* {
46 		syscallarg(key_t) key;
47 		syscallarg(size_t) size;
48 		syscallarg(int) shmflg;
49 	} */ shmget_args;
50 
51 	SCARG(&shmget_args, key) = SCARG(uap, key);
52 	SCARG(&shmget_args, size) = (size_t)SCARG(uap, size);
53 	SCARG(&shmget_args, shmflg) = SCARG(uap, shmflg);
54 
55 	return (sys_shmget(p, &shmget_args, retval));
56 }
57 #endif
58 
59 #ifdef SYSVSEM
60 /*
61  * Old-style shmget(2) used u_int for the nsops parameter, we now use size_t.
62  */
63 int
compat_35_sys_semop(struct proc * p,void * v,register_t * retval)64 compat_35_sys_semop(struct proc *p, void *v, register_t *retval)
65 {
66 	struct compat_35_sys_semop_args /* {
67 		syscallarg(int) semid;
68 		syscallarg(struct sembuf *) sops;
69 		syscallarg(u_int) nsops;
70 	} */ *uap = v;
71 	struct sys_semop_args /* {
72 		syscallarg(int) semid;
73 		syscallarg(struct sembuf *) sops;
74 		syscallarg(size_t) nsops;
75 	} */ semop_args;
76 
77 	SCARG(&semop_args, semid) = SCARG(uap, semid);
78 	SCARG(&semop_args, sops) = SCARG(uap, sops);
79 	SCARG(&semop_args, nsops) = (size_t)SCARG(uap, nsops);
80 
81 	return (sys_semop(p, &semop_args, retval));
82 }
83 #endif
84 
85 /*
86  * Convert between new and old struct {msq,sem,shm}id_ds (both ways)
87  */
88 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
89 #define cvt_ds(to, from, type, base) do {				\
90 	(to)->type##_perm.cuid = (from)->type##_perm.cuid;		\
91 	(to)->type##_perm.cgid = (from)->type##_perm.cgid;		\
92 	(to)->type##_perm.uid = (from)->type##_perm.uid;		\
93 	(to)->type##_perm.gid = (from)->type##_perm.gid;		\
94 	(to)->type##_perm.mode = (from)->type##_perm.mode & 0xffffU;	\
95 	(to)->type##_perm.seq = (from)->type##_perm.seq;		\
96 	(to)->type##_perm.key = (from)->type##_perm.key;		\
97 	memmove((caddr_t)&(to)->base, (caddr_t)&(from)->base,		\
98 	    sizeof(*(to)) - ((caddr_t)&(to)->base - (caddr_t)to));	\
99 } while (0)
100 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
101 
102 #ifdef SYSVMSG
103 /*
104  * Copy a struct msqid_ds35 from userland and convert to struct msqid_ds
105  */
106 static int
msqid_copyin(const void * uaddr,void * kaddr,size_t len)107 msqid_copyin(const void *uaddr, void *kaddr, size_t len)
108 {
109 	struct msqid_ds *msqbuf = kaddr;
110 	struct msqid_ds35 omsqbuf;
111 	int error;
112 
113 	if (len != sizeof(struct msqid_ds))
114 		return (EFAULT);
115 	if ((error = copyin(uaddr, &omsqbuf, sizeof(omsqbuf))) == 0)
116 		cvt_ds(msqbuf, &omsqbuf, msg, msg_first);
117 	return (error);
118 }
119 
120 /*
121  * Convert a struct msqid_ds to struct msqid_ds35 and copy to userland
122  */
123 static int
msqid_copyout(const void * kaddr,void * uaddr,size_t len)124 msqid_copyout(const void *kaddr, void *uaddr, size_t len)
125 {
126 	const struct msqid_ds *msqbuf = kaddr;
127 	struct msqid_ds35 omsqbuf;
128 
129 	if (len != sizeof(struct msqid_ds))
130 		return (EFAULT);
131 	cvt_ds(&omsqbuf, msqbuf, msg, msg_first);
132 	return (copyout(&omsqbuf, uaddr, sizeof(omsqbuf)));
133 }
134 
135 /*
136  * OpenBSD 3.5 msgctl(2) with 16bit mode_t in struct ipcperm.
137  */
138 int
compat_35_sys_msgctl(struct proc * p,void * v,register_t * retval)139 compat_35_sys_msgctl(struct proc *p, void *v, register_t *retval)
140 {
141 	struct compat_35_sys_msgctl_args /* {
142 		syscallarg(int) msqid;
143 		syscallarg(int) cmd;
144 		syscallarg(struct msqid_ds35 *) buf;
145 	} */ *uap = v;
146 
147 	return (msgctl1(p, SCARG(uap, msqid), SCARG(uap, cmd),
148 	    (caddr_t)SCARG(uap, buf), msqid_copyin, msqid_copyout));
149 }
150 #endif /* SYSVMSG */
151 
152 #ifdef SYSVSEM
153 /*
154  * Copy a struct semid_ds35 from userland and convert to struct semid_ds
155  */
156 static int
semid_copyin(const void * uaddr,void * kaddr,size_t len)157 semid_copyin(const void *uaddr, void *kaddr, size_t len)
158 {
159 	struct semid_ds *sembuf = kaddr;
160 	struct semid_ds35 osembuf;
161 	int error;
162 
163 	if (len != sizeof(struct semid_ds))
164 		return (EFAULT);
165 	if ((error = copyin(uaddr, &osembuf, sizeof(osembuf))) == 0)
166 		cvt_ds(sembuf, &osembuf, sem, sem_base);
167 	return (error);
168 }
169 
170 /*
171  * Convert a struct semid_ds to struct semid_ds35 and copy to userland
172  */
173 static int
semid_copyout(const void * kaddr,void * uaddr,size_t len)174 semid_copyout(const void *kaddr, void *uaddr, size_t len)
175 {
176 	const struct semid_ds *sembuf = kaddr;
177 	struct semid_ds35 osembuf;
178 
179 	if (len != sizeof(struct semid_ds))
180 		return (EFAULT);
181 	cvt_ds(&osembuf, sembuf, sem, sem_base);
182 	return (copyout(&osembuf, uaddr, sizeof(osembuf)));
183 }
184 
185 /*
186  * OpenBSD 3.5 semctl(2) with 16bit mode_t in struct ipcperm.
187  */
188 int
compat_35_sys___semctl(struct proc * p,void * v,register_t * retval)189 compat_35_sys___semctl(struct proc *p, void *v, register_t *retval)
190 {
191 	struct compat_35_sys___semctl_args /* {
192 		syscallarg(int) semid;
193 		syscallarg(int) semnum;
194 		syscallarg(int) cmd;
195 		syscallarg(union semun *) arg;
196 	} */ *uap = v;
197 	union semun arg;
198 	int error = 0, cmd = SCARG(uap, cmd);
199 
200 	switch (cmd) {
201 	case IPC_SET:
202 	case IPC_STAT:
203 	case GETALL:
204 	case SETVAL:
205 	case SETALL:
206 		error = copyin(SCARG(uap, arg), &arg, sizeof(arg));
207 		break;
208 	}
209 	if (error == 0) {
210 		error = semctl1(p, SCARG(uap, semid), SCARG(uap, semnum),
211 		    cmd, &arg, retval, semid_copyin, semid_copyout);
212 	}
213 	return (error);
214 }
215 #endif /* SYSVSEM */
216 
217 #ifdef SYSVSHM
218 /*
219  * Copy a struct shmid_ds35 from userland and convert to struct shmid_ds
220  */
221 static int
shmid_copyin(const void * uaddr,void * kaddr,size_t len)222 shmid_copyin(const void *uaddr, void *kaddr, size_t len)
223 {
224 	struct shmid_ds *shmbuf = kaddr;
225 	struct shmid_ds35 oshmbuf;
226 	int error;
227 
228 	if (len != sizeof(struct shmid_ds))
229 		return (EFAULT);
230 	if ((error = copyin(uaddr, &oshmbuf, sizeof(oshmbuf))) == 0)
231 		cvt_ds(shmbuf, &oshmbuf, shm, shm_segsz);
232 	return (error);
233 }
234 
235 /*
236  * Convert a struct shmid_ds to struct shmid_ds35 and copy to userland
237  */
238 static int
shmid_copyout(const void * kaddr,void * uaddr,size_t len)239 shmid_copyout(const void *kaddr, void *uaddr, size_t len)
240 {
241 	const struct shmid_ds *shmbuf = kaddr;
242 	struct shmid_ds35 oshmbuf;
243 
244 	if (len != sizeof(struct shmid_ds))
245 		return (EFAULT);
246 	cvt_ds(&oshmbuf, shmbuf, shm, shm_segsz);
247 	return (copyout(&oshmbuf, uaddr, sizeof(oshmbuf)));
248 }
249 
250 /*
251  * OpenBSD 3.5 shmctl(2) with 16bit mode_t in struct ipcperm.
252  */
253 int
compat_35_sys_shmctl(struct proc * p,void * v,register_t * retval)254 compat_35_sys_shmctl(struct proc *p, void *v, register_t *retval)
255 {
256 	struct compat_35_sys_shmctl_args /* {
257 		syscallarg(int) shmid;
258 		syscallarg(int) cmd;
259 		syscallarg(struct shmid_ds35 *) buf;
260 	} */ *uap = v;
261 
262 	return (shmctl1(p, SCARG(uap, shmid), SCARG(uap, cmd),
263 	    (caddr_t)SCARG(uap, buf), shmid_copyin, shmid_copyout));
264 }
265 #endif /* SYSVSHM */
266 
267 #endif /* def COMPAT_OPENBSD */
268