1 /* $NetBSD: netbsd32_ipc.c,v 1.15 2008/05/29 14:51:26 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_ipc.c,v 1.15 2008/05/29 14:51:26 mrg Exp $"); 31 32 #if defined(_KERNEL_OPT) 33 #include "opt_sysv.h" 34 #endif 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/ipc.h> 39 #include <sys/msg.h> 40 #include <sys/sem.h> 41 #include <sys/shm.h> 42 #include <sys/mount.h> 43 #include <sys/dirent.h> 44 45 #include <sys/syscallargs.h> 46 #include <sys/proc.h> 47 48 #include <compat/netbsd32/netbsd32.h> 49 #include <compat/netbsd32/netbsd32_syscallargs.h> 50 #include <compat/netbsd32/netbsd32_conv.h> 51 52 #if defined(SYSVSEM) 53 54 int 55 netbsd32___semctl14(struct lwp *l, const struct netbsd32___semctl14_args *uap, register_t *retval) 56 { 57 return do_netbsd32___semctl14(l, uap, retval, NULL); 58 } 59 60 int 61 do_netbsd32___semctl14(struct lwp *l, const struct netbsd32___semctl14_args *uap, register_t *retval, void *vkarg) 62 { 63 /* { 64 syscallarg(int) semid; 65 syscallarg(int) semnum; 66 syscallarg(int) cmd; 67 syscallarg(netbsd32_semunp_t) arg; 68 } */ 69 struct semid_ds sembuf; 70 struct netbsd32_semid_ds sembuf32; 71 int cmd, error; 72 void *pass_arg; 73 union __semun karg; 74 union netbsd32_semun karg32; 75 76 cmd = SCARG(uap, cmd); 77 78 switch (cmd) { 79 case IPC_SET: 80 case IPC_STAT: 81 pass_arg = &sembuf; 82 break; 83 84 case GETALL: 85 case SETVAL: 86 case SETALL: 87 pass_arg = &karg; 88 break; 89 default: 90 pass_arg = NULL; 91 break; 92 } 93 94 if (pass_arg) { 95 if (vkarg != NULL) 96 karg32 = *(union netbsd32_semun *)vkarg; 97 else { 98 error = copyin(SCARG_P32(uap, arg), &karg32, 99 sizeof(karg32)); 100 if (error) 101 return error; 102 } 103 if (pass_arg == &karg) { 104 switch (cmd) { 105 case GETALL: 106 case SETALL: 107 karg.array = NETBSD32PTR64(karg32.array); 108 break; 109 case SETVAL: 110 karg.val = karg32.val; 111 break; 112 } 113 } 114 if (cmd == IPC_SET) { 115 error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32, 116 sizeof(sembuf32)); 117 if (error) 118 return (error); 119 netbsd32_to_semid_ds(&sembuf32, &sembuf); 120 } 121 } 122 123 error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd, 124 pass_arg, retval); 125 126 if (error == 0 && cmd == IPC_STAT) { 127 netbsd32_from_semid_ds(&sembuf, &sembuf32); 128 error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf), 129 sizeof(sembuf32)); 130 } 131 132 return (error); 133 } 134 135 int 136 netbsd32_semget(struct lwp *l, const struct netbsd32_semget_args *uap, register_t *retval) 137 { 138 /* { 139 syscallarg(netbsd32_key_t) key; 140 syscallarg(int) nsems; 141 syscallarg(int) semflg; 142 } */ 143 struct sys_semget_args ua; 144 145 NETBSD32TOX_UAP(key, key_t); 146 NETBSD32TO64_UAP(nsems); 147 NETBSD32TO64_UAP(semflg); 148 return (sys_semget(l, &ua, retval)); 149 } 150 151 int 152 netbsd32_semop(struct lwp *l, const struct netbsd32_semop_args *uap, register_t *retval) 153 { 154 /* { 155 syscallarg(int) semid; 156 syscallarg(netbsd32_sembufp_t) sops; 157 syscallarg(netbsd32_size_t) nsops; 158 } */ 159 struct sys_semop_args ua; 160 161 NETBSD32TO64_UAP(semid); 162 NETBSD32TOP_UAP(sops, struct sembuf); 163 NETBSD32TOX_UAP(nsops, size_t); 164 return (sys_semop(l, &ua, retval)); 165 } 166 167 int 168 netbsd32_semconfig(struct lwp *l, const struct netbsd32_semconfig_args *uap, register_t *retval) 169 { 170 /* { 171 syscallarg(int) flag; 172 } */ 173 struct sys_semconfig_args ua; 174 175 NETBSD32TO64_UAP(flag); 176 return (sys_semconfig(l, &ua, retval)); 177 } 178 #endif /* SYSVSEM */ 179 180 #if defined(SYSVMSG) 181 182 int 183 netbsd32___msgctl13(struct lwp *l, const struct netbsd32___msgctl13_args *uap, register_t *retval) 184 { 185 /* { 186 syscallarg(int) msqid; 187 syscallarg(int) cmd; 188 syscallarg(netbsd32_msqid_dsp_t) buf; 189 } */ 190 struct msqid_ds ds; 191 struct netbsd32_msqid_ds ds32; 192 int error, cmd; 193 194 cmd = SCARG(uap, cmd); 195 if (cmd == IPC_SET) { 196 error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); 197 if (error) 198 return error; 199 netbsd32_to_msqid_ds(&ds32, &ds); 200 } 201 202 error = msgctl1(l, SCARG(uap, msqid), cmd, 203 (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); 204 205 if (error == 0 && cmd == IPC_STAT) { 206 netbsd32_from_msqid_ds(&ds, &ds32); 207 error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); 208 } 209 210 return error; 211 } 212 213 int 214 netbsd32_msgget(struct lwp *l, const struct netbsd32_msgget_args *uap, register_t *retval) 215 { 216 /* { 217 syscallarg(netbsd32_key_t) key; 218 syscallarg(int) msgflg; 219 } */ 220 struct sys_msgget_args ua; 221 222 NETBSD32TOX_UAP(key, key_t); 223 NETBSD32TO64_UAP(msgflg); 224 return sys_msgget(l, &ua, retval); 225 } 226 227 static int 228 netbsd32_msgsnd_fetch_type(const void *src, void *dst, size_t size) 229 { 230 netbsd32_long l32; 231 long *l = dst; 232 int error; 233 234 KASSERT(size == sizeof(netbsd32_long)); 235 236 error = copyin(src, &l32, sizeof(l32)); 237 if (!error) 238 *l = l32; 239 return error; 240 } 241 242 int 243 netbsd32_msgsnd(struct lwp *l, const struct netbsd32_msgsnd_args *uap, register_t *retval) 244 { 245 /* { 246 syscallarg(int) msqid; 247 syscallarg(const netbsd32_voidp) msgp; 248 syscallarg(netbsd32_size_t) msgsz; 249 syscallarg(int) msgflg; 250 } */ 251 252 return msgsnd1(l, SCARG(uap, msqid), 253 SCARG_P32(uap, msgp), SCARG(uap, msgsz), 254 SCARG(uap, msgflg), sizeof(netbsd32_long), 255 netbsd32_msgsnd_fetch_type); 256 } 257 258 static int 259 netbsd32_msgrcv_put_type(const void *src, void *dst, size_t size) 260 { 261 netbsd32_long l32; 262 const long *l = src; 263 264 KASSERT(size == sizeof(netbsd32_long)); 265 266 l32 = (netbsd32_long)(*l); 267 return copyout(&l32, dst, sizeof(l32)); 268 } 269 270 int 271 netbsd32_msgrcv(struct lwp *l, const struct netbsd32_msgrcv_args *uap, register_t *retval) 272 { 273 /* { 274 syscallarg(int) msqid; 275 syscallarg(netbsd32_voidp) msgp; 276 syscallarg(netbsd32_size_t) msgsz; 277 syscallarg(netbsd32_long) msgtyp; 278 syscallarg(int) msgflg; 279 } */ 280 281 return msgrcv1(l, SCARG(uap, msqid), 282 SCARG_P32(uap, msgp), SCARG(uap, msgsz), 283 SCARG(uap, msgtyp), SCARG(uap, msgflg), sizeof(netbsd32_long), 284 netbsd32_msgrcv_put_type, retval); 285 } 286 #endif /* SYSVMSG */ 287 288 #if defined(SYSVSHM) 289 290 int 291 netbsd32_shmat(struct lwp *l, const struct netbsd32_shmat_args *uap, register_t *retval) 292 { 293 /* { 294 syscallarg(int) shmid; 295 syscallarg(const netbsd32_voidp) shmaddr; 296 syscallarg(int) shmflg; 297 } */ 298 struct sys_shmat_args ua; 299 300 NETBSD32TO64_UAP(shmid); 301 NETBSD32TOP_UAP(shmaddr, void); 302 NETBSD32TO64_UAP(shmflg); 303 return sys_shmat(l, &ua, retval); 304 } 305 306 int 307 netbsd32___shmctl13(struct lwp *l, const struct netbsd32___shmctl13_args *uap, register_t *retval) 308 { 309 /* { 310 syscallarg(int) shmid; 311 syscallarg(int) cmd; 312 syscallarg(netbsd32_shmid_dsp_t) buf; 313 } */ 314 struct shmid_ds ds; 315 struct netbsd32_shmid_ds ds32; 316 int error, cmd; 317 318 cmd = SCARG(uap, cmd); 319 if (cmd == IPC_SET) { 320 error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); 321 if (error) 322 return error; 323 netbsd32_to_shmid_ds(&ds32, &ds); 324 } 325 326 error = shmctl1(l, SCARG(uap, shmid), cmd, 327 (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); 328 329 if (error == 0 && cmd == IPC_STAT) { 330 netbsd32_from_shmid_ds(&ds, &ds32); 331 error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); 332 } 333 334 return error; 335 } 336 337 int 338 netbsd32_shmdt(struct lwp *l, const struct netbsd32_shmdt_args *uap, register_t *retval) 339 { 340 /* { 341 syscallarg(const netbsd32_voidp) shmaddr; 342 } */ 343 struct sys_shmdt_args ua; 344 345 NETBSD32TOP_UAP(shmaddr, const char); 346 return (sys_shmdt(l, &ua, retval)); 347 } 348 349 int 350 netbsd32_shmget(struct lwp *l, const struct netbsd32_shmget_args *uap, register_t *retval) 351 { 352 /* { 353 syscallarg(netbsd32_key_t) key; 354 syscallarg(netbsd32_size_t) size; 355 syscallarg(int) shmflg; 356 } */ 357 struct sys_shmget_args ua; 358 359 NETBSD32TOX_UAP(key, key_t) 360 NETBSD32TOX_UAP(size, size_t) 361 NETBSD32TO64_UAP(shmflg); 362 return (sys_shmget(l, &ua, retval)); 363 } 364 #endif /* SYSVSHM */ 365