1 /* $NetBSD: linux32_ipccall.c,v 1.10 2010/01/05 13:22:41 mbalmer Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Nicolas Joly 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 AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: linux32_ipccall.c,v 1.10 2010/01/05 13:22:41 mbalmer Exp $"); 31 32 #if defined(_KERNEL_OPT) 33 #include "opt_sysv.h" 34 #endif 35 36 #include <sys/param.h> 37 #include <sys/vnode.h> 38 #include <sys/msg.h> 39 #include <sys/sem.h> 40 #include <sys/shm.h> 41 42 #include <sys/syscallargs.h> 43 44 #include <compat/netbsd32/netbsd32.h> 45 #include <compat/netbsd32/netbsd32_syscallargs.h> 46 47 #include <compat/linux/common/linux_types.h> 48 #include <compat/linux32/common/linux32_types.h> 49 #include <compat/linux32/common/linux32_signal.h> 50 #include <compat/linux32/linux32_syscallargs.h> 51 #include <compat/linux32/common/linux32_ipc.h> 52 #include <compat/linux32/common/linux32_sem.h> 53 #include <compat/linux32/common/linux32_shm.h> 54 55 #define LINUX32_IPC_semop 1 56 #define LINUX32_IPC_semget 2 57 #define LINUX32_IPC_semctl 3 58 #define LINUX32_IPC_msgsnd 11 59 #define LINUX32_IPC_msgrcv 12 60 #define LINUX32_IPC_msgget 13 61 #define LINUX32_IPC_msgctl 14 62 #define LINUX32_IPC_shmat 21 63 #define LINUX32_IPC_shmdt 22 64 #define LINUX32_IPC_shmget 23 65 #define LINUX32_IPC_shmctl 24 66 67 #ifdef SYSVSEM 68 static void 69 bsd_to_linux32_semid_ds(struct semid_ds *, struct linux32_semid_ds *); 70 static void 71 bsd_to_linux32_semid64_ds(struct semid_ds *, struct linux32_semid64_ds *); 72 static void 73 linux32_to_bsd_semid_ds(struct linux32_semid_ds *, struct semid_ds *); 74 static void 75 linux32_to_bsd_semid64_ds(struct linux32_semid64_ds *, struct semid_ds *); 76 77 static int 78 linux32_semop(struct lwp *, const struct linux32_sys_ipc_args *, register_t *); 79 static int 80 linux32_semget(struct lwp *, const struct linux32_sys_ipc_args *, register_t *); 81 static int 82 linux32_semctl(struct lwp *, const struct linux32_sys_ipc_args *, register_t *); 83 #endif /* SYSVSEM */ 84 85 #ifdef SYSVSHM 86 static void 87 bsd_to_linux32_shmid_ds(struct shmid_ds *, struct linux32_shmid_ds *); 88 static void 89 linux32_to_bsd_shmid_ds(struct linux32_shmid_ds *, struct shmid_ds *); 90 static void 91 bsd_to_linux32_shmid64_ds(struct shmid_ds *, struct linux32_shmid64_ds *); 92 static void 93 linux32_to_bsd_shmid64_ds(struct linux32_shmid64_ds *, struct shmid_ds *); 94 95 static int 96 linux32_shmat(struct lwp *, const struct linux32_sys_ipc_args *, register_t *); 97 static int 98 linux32_shmdt(struct lwp *, const struct linux32_sys_ipc_args *, register_t *); 99 static int 100 linux32_shmget(struct lwp *, const struct linux32_sys_ipc_args *, register_t *); 101 static int 102 linux32_shmctl(struct lwp *, const struct linux32_sys_ipc_args *, register_t *); 103 #endif /* SYSVSHM */ 104 105 #ifdef SYSVMSG 106 static int linux32_msgsnd(struct lwp *, const struct linux32_sys_ipc_args *, 107 register_t *); 108 static int linux32_msgrcv(struct lwp *, const struct linux32_sys_ipc_args *, 109 register_t *); 110 static int linux32_msgget(struct lwp *, const struct linux32_sys_ipc_args *, 111 register_t *); 112 static int linux32_msgctl(struct lwp *, const struct linux32_sys_ipc_args *, 113 register_t *); 114 #endif 115 116 int 117 linux32_sys_ipc(struct lwp *l, const struct linux32_sys_ipc_args *uap, 118 register_t *retval) 119 { 120 /* { 121 syscallarg(int) what; 122 syscallarg(int) a1; 123 syscallarg(int) a2; 124 syscallarg(int) a3; 125 syscallarg(netbsd32_voidp) ptr; 126 } */ 127 128 switch (SCARG(uap, what)) { 129 #ifdef SYSVSEM 130 case LINUX32_IPC_semop: 131 return linux32_semop(l, uap, retval); 132 case LINUX32_IPC_semget: 133 return linux32_semget(l, uap, retval); 134 case LINUX32_IPC_semctl: 135 return linux32_semctl(l, uap, retval); 136 #endif /* SYSVSEM */ 137 #ifdef SYSVMSG 138 case LINUX32_IPC_msgsnd: 139 return linux32_msgsnd(l, uap, retval); 140 case LINUX32_IPC_msgrcv: 141 return linux32_msgrcv(l, uap, retval); 142 case LINUX32_IPC_msgget: 143 return linux32_msgget(l, uap, retval); 144 case LINUX32_IPC_msgctl: 145 return linux32_msgctl(l, uap, retval); 146 #endif 147 #ifdef SYSVSHM 148 case LINUX32_IPC_shmat: 149 return linux32_shmat(l, uap, retval); 150 case LINUX32_IPC_shmdt: 151 return linux32_shmdt(l, uap, retval); 152 case LINUX32_IPC_shmget: 153 return linux32_shmget(l, uap, retval); 154 case LINUX32_IPC_shmctl: 155 return linux32_shmctl(l, uap, retval); 156 #endif /* SYSVSHM */ 157 default: 158 return ENOSYS; 159 } 160 161 } 162 163 static void 164 bsd_to_linux32_ipc_perm(struct ipc_perm *bpp, struct linux32_ipc_perm *lpp) 165 { 166 lpp->l_key = bpp->_key; 167 lpp->l_uid = bpp->uid; 168 lpp->l_gid = bpp->gid; 169 lpp->l_cuid = bpp->cuid; 170 lpp->l_cgid = bpp->cgid; 171 lpp->l_mode = bpp->mode; 172 lpp->l_seq = bpp->_seq; 173 } 174 175 static void 176 linux32_to_bsd_ipc_perm(struct linux32_ipc_perm *lpp, struct ipc_perm *bpp) 177 { 178 bpp->_key = lpp->l_key; 179 bpp->uid = lpp->l_uid; 180 bpp->gid = lpp->l_gid; 181 bpp->cuid = lpp->l_cuid; 182 bpp->cgid = lpp->l_cgid; 183 bpp->mode = lpp->l_mode; 184 bpp->_seq = lpp->l_seq; 185 } 186 187 static void 188 bsd_to_linux32_ipc64_perm(struct ipc_perm *bpp, struct linux32_ipc64_perm *lpp) 189 { 190 lpp->l_key = bpp->_key; 191 lpp->l_uid = bpp->uid; 192 lpp->l_gid = bpp->gid; 193 lpp->l_cuid = bpp->cuid; 194 lpp->l_cgid = bpp->cgid; 195 lpp->l_mode = bpp->mode; 196 lpp->l_seq = bpp->_seq; 197 } 198 199 static void 200 linux32_to_bsd_ipc64_perm(struct linux32_ipc64_perm *lpp, struct ipc_perm *bpp) 201 { 202 bpp->_key = lpp->l_key; 203 bpp->uid = lpp->l_uid; 204 bpp->gid = lpp->l_gid; 205 bpp->cuid = lpp->l_cuid; 206 bpp->cgid = lpp->l_cgid; 207 bpp->mode = lpp->l_mode; 208 bpp->_seq = lpp->l_seq; 209 } 210 211 #ifdef SYSVSEM 212 static void 213 bsd_to_linux32_semid_ds(struct semid_ds *bsp, struct linux32_semid_ds *lsp) 214 { 215 bsd_to_linux32_ipc_perm(&bsp->sem_perm, &lsp->l_sem_perm); 216 lsp->l_sem_otime = bsp->sem_otime; 217 lsp->l_sem_ctime = bsp->sem_ctime; 218 lsp->l_sem_nsems = bsp->sem_nsems; 219 NETBSD32PTR32(lsp->l_sem_base, bsp->_sem_base); 220 } 221 222 static void 223 bsd_to_linux32_semid64_ds(struct semid_ds *bsp, struct linux32_semid64_ds *lsp) 224 { 225 bsd_to_linux32_ipc64_perm(&bsp->sem_perm, &lsp->l_sem_perm); 226 lsp->l_sem_otime = bsp->sem_otime; 227 lsp->l_sem_ctime = bsp->sem_ctime; 228 lsp->l_sem_nsems = bsp->sem_nsems; 229 } 230 231 static void 232 linux32_to_bsd_semid_ds(struct linux32_semid_ds *lsp, struct semid_ds *bsp) 233 { 234 linux32_to_bsd_ipc_perm(&lsp->l_sem_perm, &bsp->sem_perm); 235 bsp->sem_otime = lsp->l_sem_otime; 236 bsp->sem_ctime = lsp->l_sem_ctime; 237 bsp->sem_nsems = lsp->l_sem_nsems; 238 bsp->_sem_base = NETBSD32PTR64(lsp->l_sem_base); 239 } 240 241 static void 242 linux32_to_bsd_semid64_ds(struct linux32_semid64_ds *lsp, struct semid_ds *bsp) 243 { 244 linux32_to_bsd_ipc64_perm(&lsp->l_sem_perm, &bsp->sem_perm); 245 bsp->sem_otime = lsp->l_sem_otime; 246 bsp->sem_ctime = lsp->l_sem_ctime; 247 bsp->sem_nsems = lsp->l_sem_nsems; 248 } 249 250 static int 251 linux32_semop(struct lwp *l, const struct linux32_sys_ipc_args *uap, 252 register_t *retval) 253 { 254 struct sys_semop_args ua; 255 256 SCARG(&ua, semid) = SCARG(uap, a1); 257 SCARG(&ua, sops) = SCARG_P32(uap, ptr); 258 SCARG(&ua, nsops) = SCARG(uap, a2); 259 260 return sys_semop(l, &ua, retval); 261 } 262 263 static int 264 linux32_semget(struct lwp *l, const struct linux32_sys_ipc_args *uap, 265 register_t *retval) 266 { 267 struct sys_semget_args ua; 268 269 SCARG(&ua, key) = SCARG(uap, a1); 270 SCARG(&ua, nsems) = SCARG(uap, a2); 271 SCARG(&ua, semflg) = SCARG(uap, a3); 272 273 return sys_semget(l, &ua, retval); 274 } 275 276 static int 277 linux32_semctl(struct lwp *l, const struct linux32_sys_ipc_args *uap, 278 register_t *retval) 279 { 280 int lcmd, cmd, error; 281 struct semid_ds bs; 282 struct linux32_semid_ds ls; 283 struct linux32_semid64_ds ls64; 284 union linux32_semun lsem; 285 union __semun bsem; 286 void *buf = NULL; 287 288 if ((error = copyin(SCARG_P32(uap, ptr), &lsem, sizeof lsem))) 289 return error; 290 291 lcmd = SCARG(uap, a3); 292 293 switch (lcmd & ~LINUX32_IPC_64) { 294 case LINUX32_IPC_RMID: 295 cmd = IPC_RMID; 296 break; 297 case LINUX32_IPC_STAT: 298 cmd = IPC_STAT; 299 buf = &bs; 300 break; 301 case LINUX32_IPC_SET: 302 if (lcmd & LINUX32_IPC_64) { 303 error = copyin(NETBSD32PTR64(lsem.l_buf), &ls64, 304 sizeof ls64); 305 linux32_to_bsd_semid64_ds(&ls64, &bs); 306 } else { 307 error = copyin(NETBSD32PTR64(lsem.l_buf), &ls, 308 sizeof ls); 309 linux32_to_bsd_semid_ds(&ls, &bs); 310 } 311 if (error) 312 return error; 313 cmd = IPC_SET; 314 buf = &bs; 315 break; 316 case LINUX32_GETVAL: 317 cmd = GETVAL; 318 break; 319 case LINUX32_SETVAL: 320 cmd = SETVAL; 321 bsem.val = lsem.l_val; 322 buf = &bsem; 323 break; 324 case LINUX32_GETPID: 325 cmd = GETPID; 326 break; 327 case LINUX32_GETNCNT: 328 cmd = GETNCNT; 329 break; 330 case LINUX32_GETZCNT: 331 cmd = GETZCNT; 332 break; 333 case LINUX32_GETALL: 334 cmd = GETALL; 335 bsem.array = NETBSD32PTR64(lsem.l_array); 336 buf = &bsem; 337 break; 338 case LINUX32_SETALL: 339 cmd = SETALL; 340 bsem.array = NETBSD32PTR64(lsem.l_array); 341 buf = &bsem; 342 break; 343 default: 344 return EINVAL; 345 } 346 347 error = semctl1(l, SCARG(uap, a1), SCARG(uap, a2), cmd, buf, retval); 348 if (error) 349 return error; 350 351 switch (lcmd) { 352 case LINUX32_IPC_STAT: 353 bsd_to_linux32_semid_ds(&bs, &ls); 354 error = copyout(&ls, NETBSD32PTR64(lsem.l_buf), sizeof ls); 355 break; 356 case LINUX32_IPC_STAT|LINUX32_IPC_64: 357 bsd_to_linux32_semid64_ds(&bs, &ls64); 358 error = copyout(&ls64, NETBSD32PTR64(lsem.l_buf), sizeof ls64); 359 break; 360 default: 361 break; 362 } 363 364 return error; 365 } 366 #endif /* SYSVSEM */ 367 368 #ifdef SYSVMSG 369 370 static int 371 linux32_msgsnd(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) 372 { 373 struct netbsd32_msgsnd_args bma; 374 375 SCARG(&bma, msqid) = SCARG(uap, a1); 376 SCARG(&bma, msgp) = SCARG(uap, ptr); 377 SCARG(&bma, msgsz) = SCARG(uap, a2); 378 SCARG(&bma, msgflg) = SCARG(uap, a3); 379 380 return netbsd32_msgsnd(l, &bma, retval); 381 } 382 383 /* 384 * This kludge is used for the 6th argument to the msgrcv system 385 * call, to get around the maximum of 5 arguments to a syscall in Linux. 386 */ 387 struct linux32_msgrcv_msgarg { 388 netbsd32_pointer_t msg; 389 netbsd32_long type; 390 }; 391 392 static int 393 linux32_msgrcv(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) 394 { 395 struct netbsd32_msgrcv_args bma; 396 struct linux32_msgrcv_msgarg kluge; 397 int error; 398 399 if ((error = copyin(SCARG_P32(uap, ptr), &kluge, sizeof kluge))) 400 return error; 401 402 SCARG(&bma, msqid) = SCARG(uap, a1); 403 SCARG(&bma, msgp) = kluge.msg; 404 SCARG(&bma, msgsz) = SCARG(uap, a2); 405 SCARG(&bma, msgtyp) = kluge.type; 406 SCARG(&bma, msgflg) = SCARG(uap, a3); 407 408 return netbsd32_msgrcv(l, &bma, retval); 409 } 410 411 static int 412 linux32_msgget(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) 413 { 414 struct sys_msgget_args bma; 415 416 SCARG(&bma, key) = (key_t)(linux32_key_t)SCARG(uap, a1); 417 SCARG(&bma, msgflg) = SCARG(uap, a2); 418 419 return sys_msgget(l, &bma, retval); 420 } 421 422 423 static void 424 linux32_to_bsd_msqid_ds(struct linux32_msqid_ds *lmp, struct msqid_ds *bmp) 425 { 426 427 memset(bmp, 0, sizeof(*bmp)); 428 linux32_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm); 429 bmp->_msg_first = NETBSD32PTR64(lmp->l_msg_first); 430 bmp->_msg_last = NETBSD32PTR64(lmp->l_msg_last); 431 bmp->_msg_cbytes = lmp->l_msg_cbytes; 432 bmp->msg_qnum = lmp->l_msg_qnum; 433 bmp->msg_qbytes = lmp->l_msg_qbytes; 434 bmp->msg_lspid = lmp->l_msg_lspid; 435 bmp->msg_lrpid = lmp->l_msg_lrpid; 436 bmp->msg_stime = lmp->l_msg_stime; 437 bmp->msg_rtime = lmp->l_msg_rtime; 438 bmp->msg_ctime = lmp->l_msg_ctime; 439 } 440 441 static void 442 linux32_to_bsd_msqid64_ds(struct linux32_msqid64_ds *lmp, struct msqid_ds *bmp) 443 { 444 445 memset(bmp, 0, sizeof(*bmp)); 446 linux32_to_bsd_ipc64_perm(&lmp->l_msg_perm, &bmp->msg_perm); 447 bmp->msg_stime = lmp->l_msg_stime; 448 bmp->msg_rtime = lmp->l_msg_rtime; 449 bmp->msg_ctime = lmp->l_msg_ctime; 450 bmp->_msg_cbytes = lmp->l_msg_cbytes; 451 bmp->msg_qnum = lmp->l_msg_qnum; 452 bmp->msg_qbytes = lmp->l_msg_qbytes; 453 bmp->msg_lspid = lmp->l_msg_lspid; 454 bmp->msg_lrpid = lmp->l_msg_lrpid; 455 } 456 457 static void 458 bsd_to_linux32_msqid_ds(struct msqid_ds *bmp, struct linux32_msqid_ds *lmp) 459 { 460 461 memset(lmp, 0, sizeof(*lmp)); 462 bsd_to_linux32_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm); 463 NETBSD32PTR32(lmp->l_msg_first, bmp->_msg_first); 464 NETBSD32PTR32(lmp->l_msg_last, bmp->_msg_last); 465 lmp->l_msg_cbytes = bmp->_msg_cbytes; 466 lmp->l_msg_qnum = bmp->msg_qnum; 467 lmp->l_msg_qbytes = bmp->msg_qbytes; 468 lmp->l_msg_lspid = bmp->msg_lspid; 469 lmp->l_msg_lrpid = bmp->msg_lrpid; 470 lmp->l_msg_stime = bmp->msg_stime; 471 lmp->l_msg_rtime = bmp->msg_rtime; 472 lmp->l_msg_ctime = bmp->msg_ctime; 473 } 474 475 static void 476 bsd_to_linux32_msqid64_ds(struct msqid_ds *bmp, struct linux32_msqid64_ds *lmp) 477 { 478 479 memset(lmp, 0, sizeof(*lmp)); 480 bsd_to_linux32_ipc64_perm(&bmp->msg_perm, &lmp->l_msg_perm); 481 lmp->l_msg_stime = bmp->msg_stime; 482 lmp->l_msg_rtime = bmp->msg_rtime; 483 lmp->l_msg_ctime = bmp->msg_ctime; 484 lmp->l_msg_cbytes = bmp->_msg_cbytes; 485 lmp->l_msg_qnum = bmp->msg_qnum; 486 lmp->l_msg_qbytes = bmp->msg_qbytes; 487 lmp->l_msg_lspid = bmp->msg_lspid; 488 lmp->l_msg_lrpid = bmp->msg_lrpid; 489 } 490 491 static int 492 linux32_msgctl(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) 493 { 494 struct msqid_ds bm, *bmp = NULL; 495 struct linux32_msqid_ds lm; 496 struct linux32_msqid64_ds lm64; 497 int cmd, lcmd, error; 498 void *data = SCARG_P32(uap, ptr); 499 500 lcmd = SCARG(uap, a2); 501 502 switch (lcmd & ~LINUX32_IPC_64) { 503 case LINUX32_IPC_STAT: 504 cmd = IPC_STAT; 505 bmp = &bm; 506 break; 507 case LINUX32_IPC_SET: 508 if (lcmd & LINUX32_IPC_64) { 509 error = copyin(data, &lm64, sizeof lm64); 510 linux32_to_bsd_msqid64_ds(&lm64, &bm); 511 } else { 512 error = copyin(data, &lm, sizeof lm); 513 linux32_to_bsd_msqid_ds(&lm, &bm); 514 } 515 if (error) 516 return error; 517 cmd = IPC_SET; 518 bmp = &bm; 519 break; 520 case LINUX32_IPC_RMID: 521 cmd = IPC_RMID; 522 break; 523 default: 524 return EINVAL; 525 } 526 527 if ((error = msgctl1(l, SCARG(uap, a1), cmd, bmp))) 528 return error; 529 530 switch (lcmd) { 531 case LINUX32_IPC_STAT: 532 bsd_to_linux32_msqid_ds(&bm, &lm); 533 error = copyout(&lm, data, sizeof lm); 534 break; 535 case LINUX32_IPC_STAT|LINUX32_IPC_64: 536 bsd_to_linux32_msqid64_ds(&bm, &lm64); 537 error = copyout(&lm64, data, sizeof lm64); 538 break; 539 default: 540 break; 541 } 542 543 return error; 544 } 545 #endif /* SYSVMSG */ 546 547 #ifdef SYSVSHM 548 static void 549 bsd_to_linux32_shmid_ds(struct shmid_ds *bsp, struct linux32_shmid_ds *lsp) 550 { 551 bsd_to_linux32_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm); 552 lsp->l_shm_segsz = bsp->shm_segsz; 553 lsp->l_shm_atime = bsp->shm_atime; 554 lsp->l_shm_dtime = bsp->shm_dtime; 555 lsp->l_shm_ctime = bsp->shm_ctime; 556 lsp->l_shm_cpid = bsp->shm_cpid; 557 lsp->l_shm_lpid = bsp->shm_lpid; 558 lsp->l_shm_nattch = bsp->shm_nattch; 559 NETBSD32PTR32(lsp->l_private2, bsp->_shm_internal); 560 } 561 562 static void 563 linux32_to_bsd_shmid_ds(struct linux32_shmid_ds *lsp, struct shmid_ds *bsp) 564 { 565 linux32_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm); 566 bsp->shm_segsz = lsp->l_shm_segsz; 567 bsp->shm_atime = lsp->l_shm_atime; 568 bsp->shm_dtime = lsp->l_shm_dtime; 569 bsp->shm_ctime = lsp->l_shm_ctime; 570 bsp->shm_cpid = lsp->l_shm_cpid; 571 bsp->shm_lpid = lsp->l_shm_lpid; 572 bsp->shm_nattch = lsp->l_shm_nattch; 573 bsp->_shm_internal = NETBSD32PTR64(lsp->l_private2); 574 } 575 576 static void 577 bsd_to_linux32_shmid64_ds(struct shmid_ds *bsp, struct linux32_shmid64_ds *lsp) 578 { 579 bsd_to_linux32_ipc64_perm(&bsp->shm_perm, &lsp->l_shm_perm); 580 lsp->l_shm_segsz = bsp->shm_segsz; 581 lsp->l_shm_atime = bsp->shm_atime; 582 lsp->l_shm_dtime = bsp->shm_dtime; 583 lsp->l_shm_ctime = bsp->shm_ctime; 584 lsp->l_shm_cpid = bsp->shm_cpid; 585 lsp->l_shm_lpid = bsp->shm_lpid; 586 lsp->l_shm_nattch = bsp->shm_nattch; 587 lsp->l___unused5 = NETBSD32PTR32I(bsp->_shm_internal); 588 } 589 590 static void 591 linux32_to_bsd_shmid64_ds(struct linux32_shmid64_ds *lsp, struct shmid_ds *bsp) 592 { 593 linux32_to_bsd_ipc64_perm(&lsp->l_shm_perm, &bsp->shm_perm); 594 bsp->shm_segsz = lsp->l_shm_segsz; 595 bsp->shm_atime = lsp->l_shm_atime; 596 bsp->shm_dtime = lsp->l_shm_dtime; 597 bsp->shm_ctime = lsp->l_shm_ctime; 598 bsp->shm_cpid = lsp->l_shm_cpid; 599 bsp->shm_lpid = lsp->l_shm_lpid; 600 bsp->shm_nattch = lsp->l_shm_nattch; 601 bsp->_shm_internal = NETBSD32IPTR64(lsp->l___unused5); 602 } 603 604 static int 605 linux32_shmat(struct lwp *l, const struct linux32_sys_ipc_args *uap, 606 register_t *retval) 607 { 608 struct sys_shmat_args ua; 609 netbsd32_pointer_t addr32; 610 int error; 611 612 SCARG(&ua, shmid) = SCARG(uap, a1); 613 SCARG(&ua, shmaddr) = SCARG_P32(uap, ptr); 614 SCARG(&ua, shmflg) = SCARG(uap, a2); 615 616 if ((error = sys_shmat(l, &ua, retval))) 617 return error; 618 619 NETBSD32PTR32(addr32, (const void *)(uintptr_t)retval[0]); 620 621 error = copyout(&addr32, NETBSD32IPTR64(SCARG(uap, a3)), sizeof addr32); 622 if (error == 0) 623 retval[0] = 0; 624 625 return error; 626 } 627 628 static int 629 linux32_shmdt(struct lwp *l, const struct linux32_sys_ipc_args *uap, 630 register_t *retval) 631 { 632 struct sys_shmdt_args ua; 633 634 SCARG(&ua, shmaddr) = SCARG_P32(uap, ptr); 635 636 return sys_shmdt(l, &ua, retval); 637 } 638 639 static int 640 linux32_shmget(struct lwp *l, const struct linux32_sys_ipc_args *uap, 641 register_t *retval) 642 { 643 struct sys_shmget_args ua; 644 645 SCARG(&ua, key) = SCARG(uap, a1); 646 SCARG(&ua, size) = SCARG(uap, a2); 647 SCARG(&ua, shmflg) = SCARG(uap, a3) | _SHM_RMLINGER; 648 649 return sys_shmget(l, &ua, retval); 650 } 651 652 static int 653 linux32_shmctl(struct lwp *l, const struct linux32_sys_ipc_args *uap, 654 register_t *retval) 655 { 656 int shmid, cmd, error; 657 struct shmid_ds bs; 658 struct linux32_shmid_ds ls; 659 struct linux32_shmid64_ds ls64; 660 661 shmid = SCARG(uap, a1); 662 cmd = SCARG(uap, a2); 663 664 switch (cmd & ~LINUX32_IPC_64) { 665 666 case LINUX32_SHM_STAT: 667 return ENOSYS; 668 669 case LINUX32_IPC_STAT: 670 error = shmctl1(l, shmid, IPC_STAT, &bs); 671 if (error != 0) 672 return error; 673 if (cmd & LINUX32_IPC_64) { 674 bsd_to_linux32_shmid64_ds(&bs, &ls64); 675 error = copyout(&ls64, SCARG_P32(uap, ptr), sizeof ls64); 676 } else { 677 bsd_to_linux32_shmid_ds(&bs, &ls); 678 error = copyout(&ls, SCARG_P32(uap, ptr), sizeof ls); 679 } 680 return error; 681 682 case LINUX32_IPC_SET: 683 if (cmd & LINUX32_IPC_64) { 684 error = copyin(SCARG_P32(uap, ptr), &ls64, sizeof ls64); 685 linux32_to_bsd_shmid64_ds(&ls64, &bs); 686 } else { 687 error = copyin(SCARG_P32(uap, ptr), &ls, sizeof ls); 688 linux32_to_bsd_shmid_ds(&ls, &bs); 689 } 690 if (error != 0) 691 return error; 692 return shmctl1(l, shmid, IPC_SET, &bs); 693 694 case LINUX32_IPC_RMID: 695 return shmctl1(l, shmid, IPC_RMID, NULL); 696 697 case LINUX32_SHM_LOCK: 698 return shmctl1(l, shmid, SHM_LOCK, NULL); 699 700 case LINUX32_SHM_UNLOCK: 701 return shmctl1(l, shmid, SHM_UNLOCK, NULL); 702 703 case LINUX32_IPC_INFO: 704 case LINUX32_SHM_INFO: 705 return ENOSYS; 706 707 default: 708 return EINVAL; 709 } 710 } 711 #endif /* SYSVSHM */ 712