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