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