1 /* $NetBSD: netbsd32_ipc.c,v 1.18 2015/12/03 10:38:21 pgoyette 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.18 2015/12/03 10:38:21 pgoyette 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/module.h> 44 #include <sys/dirent.h> 45 #include <sys/syscallvar.h> 46 47 #include <sys/syscallargs.h> 48 #include <sys/proc.h> 49 50 #include <compat/netbsd32/netbsd32.h> 51 #include <compat/netbsd32/netbsd32_syscall.h> 52 #include <compat/netbsd32/netbsd32_syscallargs.h> 53 #include <compat/netbsd32/netbsd32_conv.h> 54 55 extern struct emul emul_netbsd32; 56 57 #define _PKG_ENTRY(name) \ 58 { NETBSD32_SYS_ ## name, 0, (sy_call_t *)name } 59 60 #define _PKG_ENTRY2(code, name) \ 61 { NETBSD32_SYS_ ## code, 0, (sy_call_t *)name } 62 63 static const struct syscall_package compat_sysvipc_syscalls[] = { 64 #if defined(SYSVSEM) 65 _PKG_ENTRY(netbsd32_____semctl50), 66 _PKG_ENTRY(netbsd32_semget), 67 _PKG_ENTRY(netbsd32_semop), 68 _PKG_ENTRY(netbsd32_semconfig), 69 #if defined(COMPAT_10) 70 _PKG_ENTRY2(compat_10_osemsys, compat_10_netbsd32_semsys), 71 #endif 72 #if defined(COMPAT_14) 73 _PKG_ENTRY(compat_14_netbsd32___semctl), 74 #endif 75 #if defined(COMPAT_50) 76 _PKG_ENTRY(compat_50_netbsd32___semctl14), 77 #endif 78 #endif /* SYSVSEM */ 79 80 #if defined(SYSVSHM) 81 _PKG_ENTRY(netbsd32_shmat), 82 _PKG_ENTRY(netbsd32___shmctl50), 83 _PKG_ENTRY(netbsd32_shmdt), 84 _PKG_ENTRY(netbsd32_shmget), 85 #if defined(COMPAT_10) 86 _PKG_ENTRY2(compat_10_oshmsys, compat_10_netbsd32_shmsys), 87 #endif 88 #if defined(COMPAT_14) 89 _PKG_ENTRY(compat_14_netbsd32_shmctl), 90 #endif 91 #if defined(COMPAT_50) 92 _PKG_ENTRY(compat_50_netbsd32___shmctl13), 93 #endif 94 #endif /* SYSVSHM */ 95 96 #if defined(SYSVMSG) 97 _PKG_ENTRY(netbsd32___msgctl50), 98 _PKG_ENTRY(netbsd32_msgget), 99 _PKG_ENTRY(netbsd32_msgsnd), 100 _PKG_ENTRY(netbsd32_msgrcv), 101 #if defined(COMPAT_10) 102 _PKG_ENTRY2(compat_10_omsgsys, compat_10_netbsd32_msgsys), 103 #endif 104 #if defined(COMPAT_14) 105 _PKG_ENTRY(compat_14_netbsd32_msgctl), 106 #endif 107 #if defined(COMPAT_50) 108 _PKG_ENTRY(compat_50_netbsd32___msgctl13), 109 #endif 110 #endif /* SYSVMSG */ 111 { 0, 0, NULL } 112 }; 113 114 MODULE(MODULE_CLASS_EXEC, compat_netbsd32_sysvipc, "sysv_ipc,compat_netbsd32"); 115 116 static int 117 compat_netbsd32_sysvipc_modcmd(modcmd_t cmd, void *arg) 118 { 119 int error; 120 121 switch (cmd) { 122 case MODULE_CMD_INIT: 123 error = syscall_establish(&emul_netbsd32, 124 compat_sysvipc_syscalls); 125 break; 126 case MODULE_CMD_FINI: 127 error = syscall_disestablish(&emul_netbsd32, 128 compat_sysvipc_syscalls); 129 break; 130 default: 131 error = ENOTTY; 132 break; 133 } 134 return error; 135 } 136 137 138 #if defined(SYSVSEM) 139 140 int 141 netbsd32_____semctl50(struct lwp *l, const struct netbsd32_____semctl50_args *uap, register_t *retval) 142 { 143 /* { 144 syscallarg(int) semid; 145 syscallarg(int) semnum; 146 syscallarg(int) cmd; 147 syscallarg(netbsd32_semunp_t) arg; 148 } */ 149 struct semid_ds sembuf; 150 struct netbsd32_semid_ds sembuf32; 151 int cmd, error; 152 void *pass_arg; 153 union __semun karg; 154 union netbsd32_semun karg32; 155 156 cmd = SCARG(uap, cmd); 157 158 switch (cmd) { 159 case IPC_SET: 160 case IPC_STAT: 161 pass_arg = &sembuf; 162 break; 163 164 case GETALL: 165 case SETVAL: 166 case SETALL: 167 pass_arg = &karg; 168 break; 169 default: 170 pass_arg = NULL; 171 break; 172 } 173 174 if (pass_arg) { 175 error = copyin(SCARG_P32(uap, arg), &karg32, sizeof(karg32)); 176 if (error) 177 return error; 178 if (pass_arg == &karg) { 179 switch (cmd) { 180 case GETALL: 181 case SETALL: 182 karg.array = NETBSD32PTR64(karg32.array); 183 break; 184 case SETVAL: 185 karg.val = karg32.val; 186 break; 187 } 188 } 189 if (cmd == IPC_SET) { 190 error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32, 191 sizeof(sembuf32)); 192 if (error) 193 return (error); 194 netbsd32_to_semid_ds(&sembuf32, &sembuf); 195 } 196 } 197 198 error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd, 199 pass_arg, retval); 200 201 if (error == 0 && cmd == IPC_STAT) { 202 netbsd32_from_semid_ds(&sembuf, &sembuf32); 203 error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf), 204 sizeof(sembuf32)); 205 } 206 207 return (error); 208 } 209 210 int 211 netbsd32_semget(struct lwp *l, const struct netbsd32_semget_args *uap, register_t *retval) 212 { 213 /* { 214 syscallarg(netbsd32_key_t) key; 215 syscallarg(int) nsems; 216 syscallarg(int) semflg; 217 } */ 218 struct sys_semget_args ua; 219 220 NETBSD32TOX_UAP(key, key_t); 221 NETBSD32TO64_UAP(nsems); 222 NETBSD32TO64_UAP(semflg); 223 return (sys_semget(l, &ua, retval)); 224 } 225 226 int 227 netbsd32_semop(struct lwp *l, const struct netbsd32_semop_args *uap, register_t *retval) 228 { 229 /* { 230 syscallarg(int) semid; 231 syscallarg(netbsd32_sembufp_t) sops; 232 syscallarg(netbsd32_size_t) nsops; 233 } */ 234 struct sys_semop_args ua; 235 236 NETBSD32TO64_UAP(semid); 237 NETBSD32TOP_UAP(sops, struct sembuf); 238 NETBSD32TOX_UAP(nsops, size_t); 239 return (sys_semop(l, &ua, retval)); 240 } 241 242 int 243 netbsd32_semconfig(struct lwp *l, const struct netbsd32_semconfig_args *uap, register_t *retval) 244 { 245 /* { 246 syscallarg(int) flag; 247 } */ 248 struct sys_semconfig_args ua; 249 250 NETBSD32TO64_UAP(flag); 251 return (sys_semconfig(l, &ua, retval)); 252 } 253 #endif /* SYSVSEM */ 254 255 #if defined(SYSVMSG) 256 257 int 258 netbsd32___msgctl50(struct lwp *l, const struct netbsd32___msgctl50_args *uap, 259 register_t *retval) 260 { 261 /* { 262 syscallarg(int) msqid; 263 syscallarg(int) cmd; 264 syscallarg(netbsd32_msqid_dsp_t) buf; 265 } */ 266 struct msqid_ds ds; 267 struct netbsd32_msqid_ds ds32; 268 int error, cmd; 269 270 cmd = SCARG(uap, cmd); 271 if (cmd == IPC_SET) { 272 error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); 273 if (error) 274 return error; 275 netbsd32_to_msqid_ds(&ds32, &ds); 276 } 277 278 error = msgctl1(l, SCARG(uap, msqid), cmd, 279 (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); 280 281 if (error == 0 && cmd == IPC_STAT) { 282 netbsd32_from_msqid_ds(&ds, &ds32); 283 error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); 284 } 285 286 return error; 287 } 288 289 int 290 netbsd32_msgget(struct lwp *l, const struct netbsd32_msgget_args *uap, register_t *retval) 291 { 292 /* { 293 syscallarg(netbsd32_key_t) key; 294 syscallarg(int) msgflg; 295 } */ 296 struct sys_msgget_args ua; 297 298 NETBSD32TOX_UAP(key, key_t); 299 NETBSD32TO64_UAP(msgflg); 300 return sys_msgget(l, &ua, retval); 301 } 302 303 static int 304 netbsd32_msgsnd_fetch_type(const void *src, void *dst, size_t size) 305 { 306 netbsd32_long l32; 307 long *l = dst; 308 int error; 309 310 KASSERT(size == sizeof(netbsd32_long)); 311 312 error = copyin(src, &l32, sizeof(l32)); 313 if (!error) 314 *l = l32; 315 return error; 316 } 317 318 int 319 netbsd32_msgsnd(struct lwp *l, const struct netbsd32_msgsnd_args *uap, register_t *retval) 320 { 321 /* { 322 syscallarg(int) msqid; 323 syscallarg(const netbsd32_voidp) msgp; 324 syscallarg(netbsd32_size_t) msgsz; 325 syscallarg(int) msgflg; 326 } */ 327 328 return msgsnd1(l, SCARG(uap, msqid), 329 SCARG_P32(uap, msgp), SCARG(uap, msgsz), 330 SCARG(uap, msgflg), sizeof(netbsd32_long), 331 netbsd32_msgsnd_fetch_type); 332 } 333 334 static int 335 netbsd32_msgrcv_put_type(const void *src, void *dst, size_t size) 336 { 337 netbsd32_long l32; 338 const long *l = src; 339 340 KASSERT(size == sizeof(netbsd32_long)); 341 342 l32 = (netbsd32_long)(*l); 343 return copyout(&l32, dst, sizeof(l32)); 344 } 345 346 int 347 netbsd32_msgrcv(struct lwp *l, const struct netbsd32_msgrcv_args *uap, register_t *retval) 348 { 349 /* { 350 syscallarg(int) msqid; 351 syscallarg(netbsd32_voidp) msgp; 352 syscallarg(netbsd32_size_t) msgsz; 353 syscallarg(netbsd32_long) msgtyp; 354 syscallarg(int) msgflg; 355 } */ 356 357 return msgrcv1(l, SCARG(uap, msqid), 358 SCARG_P32(uap, msgp), SCARG(uap, msgsz), 359 SCARG(uap, msgtyp), SCARG(uap, msgflg), sizeof(netbsd32_long), 360 netbsd32_msgrcv_put_type, retval); 361 } 362 #endif /* SYSVMSG */ 363 364 #if defined(SYSVSHM) 365 366 int 367 netbsd32_shmat(struct lwp *l, const struct netbsd32_shmat_args *uap, register_t *retval) 368 { 369 /* { 370 syscallarg(int) shmid; 371 syscallarg(const netbsd32_voidp) shmaddr; 372 syscallarg(int) shmflg; 373 } */ 374 struct sys_shmat_args ua; 375 376 NETBSD32TO64_UAP(shmid); 377 NETBSD32TOP_UAP(shmaddr, void); 378 NETBSD32TO64_UAP(shmflg); 379 return sys_shmat(l, &ua, retval); 380 } 381 382 int 383 netbsd32___shmctl50(struct lwp *l, const struct netbsd32___shmctl50_args *uap, 384 register_t *retval) 385 { 386 /* { 387 syscallarg(int) shmid; 388 syscallarg(int) cmd; 389 syscallarg(netbsd32_shmid_dsp_t) buf; 390 } */ 391 struct shmid_ds ds; 392 struct netbsd32_shmid_ds ds32; 393 int error, cmd; 394 395 cmd = SCARG(uap, cmd); 396 if (cmd == IPC_SET) { 397 error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32)); 398 if (error) 399 return error; 400 netbsd32_to_shmid_ds(&ds32, &ds); 401 } 402 403 error = shmctl1(l, SCARG(uap, shmid), cmd, 404 (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL); 405 406 if (error == 0 && cmd == IPC_STAT) { 407 netbsd32_from_shmid_ds(&ds, &ds32); 408 error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32)); 409 } 410 411 return error; 412 } 413 414 int 415 netbsd32_shmdt(struct lwp *l, const struct netbsd32_shmdt_args *uap, register_t *retval) 416 { 417 /* { 418 syscallarg(const netbsd32_voidp) shmaddr; 419 } */ 420 struct sys_shmdt_args ua; 421 422 NETBSD32TOP_UAP(shmaddr, const char); 423 return (sys_shmdt(l, &ua, retval)); 424 } 425 426 int 427 netbsd32_shmget(struct lwp *l, const struct netbsd32_shmget_args *uap, register_t *retval) 428 { 429 /* { 430 syscallarg(netbsd32_key_t) key; 431 syscallarg(netbsd32_size_t) size; 432 syscallarg(int) shmflg; 433 } */ 434 struct sys_shmget_args ua; 435 436 NETBSD32TOX_UAP(key, key_t); 437 NETBSD32TOX_UAP(size, size_t); 438 NETBSD32TO64_UAP(shmflg); 439 return (sys_shmget(l, &ua, retval)); 440 } 441 #endif /* SYSVSHM */ 442