1 /* $NetBSD: linux32_ipccall.c,v 1.12 2019/02/21 03:37:18 mrg 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.12 2019/02/21 03:37:18 mrg 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 #if defined(SYSVSEM) || defined (SYSVMSG) || defined(SYSVSHM) 163 static void 164 bsd_to_linux32_ipc_perm(struct ipc_perm *bpp, struct linux32_ipc_perm *lpp) 165 { 166 167 memset(lpp, 0, sizeof *lpp); 168 lpp->l_key = bpp->_key; 169 lpp->l_uid = bpp->uid; 170 lpp->l_gid = bpp->gid; 171 lpp->l_cuid = bpp->cuid; 172 lpp->l_cgid = bpp->cgid; 173 lpp->l_mode = bpp->mode; 174 lpp->l_seq = bpp->_seq; 175 } 176 177 static void 178 linux32_to_bsd_ipc_perm(struct linux32_ipc_perm *lpp, struct ipc_perm *bpp) 179 { 180 181 bpp->_key = lpp->l_key; 182 bpp->uid = lpp->l_uid; 183 bpp->gid = lpp->l_gid; 184 bpp->cuid = lpp->l_cuid; 185 bpp->cgid = lpp->l_cgid; 186 bpp->mode = lpp->l_mode; 187 bpp->_seq = lpp->l_seq; 188 } 189 190 static void 191 bsd_to_linux32_ipc64_perm(struct ipc_perm *bpp, struct linux32_ipc64_perm *lpp) 192 { 193 194 memset(lpp, 0, sizeof *lpp); 195 lpp->l_key = bpp->_key; 196 lpp->l_uid = bpp->uid; 197 lpp->l_gid = bpp->gid; 198 lpp->l_cuid = bpp->cuid; 199 lpp->l_cgid = bpp->cgid; 200 lpp->l_mode = bpp->mode; 201 lpp->l_seq = bpp->_seq; 202 } 203 204 static void 205 linux32_to_bsd_ipc64_perm(struct linux32_ipc64_perm *lpp, struct ipc_perm *bpp) 206 { 207 208 bpp->_key = lpp->l_key; 209 bpp->uid = lpp->l_uid; 210 bpp->gid = lpp->l_gid; 211 bpp->cuid = lpp->l_cuid; 212 bpp->cgid = lpp->l_cgid; 213 bpp->mode = lpp->l_mode; 214 bpp->_seq = lpp->l_seq; 215 } 216 #endif /* SYSVSEM, SYSVMSG, or SYSVSHM */ 217 218 #ifdef SYSVSEM 219 static void 220 bsd_to_linux32_semid_ds(struct semid_ds *bsp, struct linux32_semid_ds *lsp) 221 { 222 223 memset(lsp, 0, sizeof *lsp); 224 bsd_to_linux32_ipc_perm(&bsp->sem_perm, &lsp->l_sem_perm); 225 lsp->l_sem_otime = bsp->sem_otime; 226 lsp->l_sem_ctime = bsp->sem_ctime; 227 lsp->l_sem_nsems = bsp->sem_nsems; 228 } 229 230 static void 231 bsd_to_linux32_semid64_ds(struct semid_ds *bsp, struct linux32_semid64_ds *lsp) 232 { 233 234 memset(lsp, 0, sizeof *lsp); 235 bsd_to_linux32_ipc64_perm(&bsp->sem_perm, &lsp->l_sem_perm); 236 lsp->l_sem_otime = bsp->sem_otime; 237 lsp->l_sem_ctime = bsp->sem_ctime; 238 lsp->l_sem_nsems = bsp->sem_nsems; 239 } 240 241 static void 242 linux32_to_bsd_semid_ds(struct linux32_semid_ds *lsp, struct semid_ds *bsp) 243 { 244 linux32_to_bsd_ipc_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 void 251 linux32_to_bsd_semid64_ds(struct linux32_semid64_ds *lsp, struct semid_ds *bsp) 252 { 253 linux32_to_bsd_ipc64_perm(&lsp->l_sem_perm, &bsp->sem_perm); 254 bsp->sem_otime = lsp->l_sem_otime; 255 bsp->sem_ctime = lsp->l_sem_ctime; 256 bsp->sem_nsems = lsp->l_sem_nsems; 257 } 258 259 static int 260 linux32_semop(struct lwp *l, const struct linux32_sys_ipc_args *uap, 261 register_t *retval) 262 { 263 struct sys_semop_args ua; 264 265 SCARG(&ua, semid) = SCARG(uap, a1); 266 SCARG(&ua, sops) = SCARG_P32(uap, ptr); 267 SCARG(&ua, nsops) = SCARG(uap, a2); 268 269 return sys_semop(l, &ua, retval); 270 } 271 272 static int 273 linux32_semget(struct lwp *l, const struct linux32_sys_ipc_args *uap, 274 register_t *retval) 275 { 276 struct sys_semget_args ua; 277 278 SCARG(&ua, key) = SCARG(uap, a1); 279 SCARG(&ua, nsems) = SCARG(uap, a2); 280 SCARG(&ua, semflg) = SCARG(uap, a3); 281 282 return sys_semget(l, &ua, retval); 283 } 284 285 static int 286 linux32_semctl(struct lwp *l, const struct linux32_sys_ipc_args *uap, 287 register_t *retval) 288 { 289 int lcmd, cmd, error; 290 struct semid_ds bs; 291 struct linux32_semid_ds ls; 292 struct linux32_semid64_ds ls64; 293 union linux32_semun lsem; 294 union __semun bsem; 295 void *buf = NULL; 296 297 if ((error = copyin(SCARG_P32(uap, ptr), &lsem, sizeof lsem))) 298 return error; 299 300 lcmd = SCARG(uap, a3); 301 302 switch (lcmd & ~LINUX32_IPC_64) { 303 case LINUX32_IPC_RMID: 304 cmd = IPC_RMID; 305 break; 306 case LINUX32_IPC_STAT: 307 cmd = IPC_STAT; 308 buf = &bs; 309 break; 310 case LINUX32_IPC_SET: 311 if (lcmd & LINUX32_IPC_64) { 312 error = copyin(NETBSD32PTR64(lsem.l_buf), &ls64, 313 sizeof ls64); 314 linux32_to_bsd_semid64_ds(&ls64, &bs); 315 } else { 316 error = copyin(NETBSD32PTR64(lsem.l_buf), &ls, 317 sizeof ls); 318 linux32_to_bsd_semid_ds(&ls, &bs); 319 } 320 if (error) 321 return error; 322 cmd = IPC_SET; 323 buf = &bs; 324 break; 325 case LINUX32_GETVAL: 326 cmd = GETVAL; 327 break; 328 case LINUX32_SETVAL: 329 cmd = SETVAL; 330 bsem.val = lsem.l_val; 331 buf = &bsem; 332 break; 333 case LINUX32_GETPID: 334 cmd = GETPID; 335 break; 336 case LINUX32_GETNCNT: 337 cmd = GETNCNT; 338 break; 339 case LINUX32_GETZCNT: 340 cmd = GETZCNT; 341 break; 342 case LINUX32_GETALL: 343 cmd = GETALL; 344 bsem.array = NETBSD32PTR64(lsem.l_array); 345 buf = &bsem; 346 break; 347 case LINUX32_SETALL: 348 cmd = SETALL; 349 bsem.array = NETBSD32PTR64(lsem.l_array); 350 buf = &bsem; 351 break; 352 default: 353 return EINVAL; 354 } 355 356 error = semctl1(l, SCARG(uap, a1), SCARG(uap, a2), cmd, buf, retval); 357 if (error) 358 return error; 359 360 switch (lcmd) { 361 case LINUX32_IPC_STAT: 362 bsd_to_linux32_semid_ds(&bs, &ls); 363 error = copyout(&ls, NETBSD32PTR64(lsem.l_buf), sizeof ls); 364 break; 365 case LINUX32_IPC_STAT|LINUX32_IPC_64: 366 bsd_to_linux32_semid64_ds(&bs, &ls64); 367 error = copyout(&ls64, NETBSD32PTR64(lsem.l_buf), sizeof ls64); 368 break; 369 default: 370 break; 371 } 372 373 return error; 374 } 375 #endif /* SYSVSEM */ 376 377 #ifdef SYSVMSG 378 379 static int 380 linux32_msgsnd(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) 381 { 382 struct netbsd32_msgsnd_args bma; 383 384 SCARG(&bma, msqid) = SCARG(uap, a1); 385 SCARG(&bma, msgp) = SCARG(uap, ptr); 386 SCARG(&bma, msgsz) = SCARG(uap, a2); 387 SCARG(&bma, msgflg) = SCARG(uap, a3); 388 389 return netbsd32_msgsnd(l, &bma, retval); 390 } 391 392 /* 393 * This kludge is used for the 6th argument to the msgrcv system 394 * call, to get around the maximum of 5 arguments to a syscall in Linux. 395 */ 396 struct linux32_msgrcv_msgarg { 397 netbsd32_pointer_t msg; 398 netbsd32_long type; 399 }; 400 401 static int 402 linux32_msgrcv(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) 403 { 404 struct netbsd32_msgrcv_args bma; 405 struct linux32_msgrcv_msgarg kluge; 406 int error; 407 408 if ((error = copyin(SCARG_P32(uap, ptr), &kluge, sizeof kluge))) 409 return error; 410 411 SCARG(&bma, msqid) = SCARG(uap, a1); 412 SCARG(&bma, msgp) = kluge.msg; 413 SCARG(&bma, msgsz) = SCARG(uap, a2); 414 SCARG(&bma, msgtyp) = kluge.type; 415 SCARG(&bma, msgflg) = SCARG(uap, a3); 416 417 return netbsd32_msgrcv(l, &bma, retval); 418 } 419 420 static int 421 linux32_msgget(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) 422 { 423 struct sys_msgget_args bma; 424 425 SCARG(&bma, key) = (key_t)(linux32_key_t)SCARG(uap, a1); 426 SCARG(&bma, msgflg) = SCARG(uap, a2); 427 428 return sys_msgget(l, &bma, retval); 429 } 430 431 432 static void 433 linux32_to_bsd_msqid_ds(struct linux32_msqid_ds *lmp, struct msqid_ds *bmp) 434 { 435 436 memset(bmp, 0, sizeof(*bmp)); 437 linux32_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm); 438 bmp->_msg_cbytes = lmp->l_msg_cbytes; 439 bmp->msg_qnum = lmp->l_msg_qnum; 440 bmp->msg_qbytes = lmp->l_msg_qbytes; 441 bmp->msg_lspid = lmp->l_msg_lspid; 442 bmp->msg_lrpid = lmp->l_msg_lrpid; 443 bmp->msg_stime = lmp->l_msg_stime; 444 bmp->msg_rtime = lmp->l_msg_rtime; 445 bmp->msg_ctime = lmp->l_msg_ctime; 446 } 447 448 static void 449 linux32_to_bsd_msqid64_ds(struct linux32_msqid64_ds *lmp, struct msqid_ds *bmp) 450 { 451 452 linux32_to_bsd_ipc64_perm(&lmp->l_msg_perm, &bmp->msg_perm); 453 bmp->_msg_cbytes = lmp->l_msg_cbytes; 454 bmp->msg_stime = lmp->l_msg_stime; 455 bmp->msg_rtime = lmp->l_msg_rtime; 456 bmp->msg_ctime = lmp->l_msg_ctime; 457 bmp->msg_qnum = lmp->l_msg_qnum; 458 bmp->msg_qbytes = lmp->l_msg_qbytes; 459 bmp->msg_lspid = lmp->l_msg_lspid; 460 bmp->msg_lrpid = lmp->l_msg_lrpid; 461 } 462 463 static void 464 bsd_to_linux32_msqid_ds(struct msqid_ds *bmp, struct linux32_msqid_ds *lmp) 465 { 466 467 memset(lmp, 0, sizeof(*lmp)); 468 bsd_to_linux32_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm); 469 lmp->l_msg_cbytes = bmp->_msg_cbytes; 470 lmp->l_msg_qnum = bmp->msg_qnum; 471 lmp->l_msg_qbytes = bmp->msg_qbytes; 472 lmp->l_msg_lspid = bmp->msg_lspid; 473 lmp->l_msg_lrpid = bmp->msg_lrpid; 474 lmp->l_msg_stime = bmp->msg_stime; 475 lmp->l_msg_rtime = bmp->msg_rtime; 476 lmp->l_msg_ctime = bmp->msg_ctime; 477 } 478 479 static void 480 bsd_to_linux32_msqid64_ds(struct msqid_ds *bmp, struct linux32_msqid64_ds *lmp) 481 { 482 483 memset(lmp, 0, sizeof(*lmp)); 484 bsd_to_linux32_ipc64_perm(&bmp->msg_perm, &lmp->l_msg_perm); 485 lmp->l_msg_cbytes = bmp->_msg_cbytes; 486 lmp->l_msg_stime = bmp->msg_stime; 487 lmp->l_msg_rtime = bmp->msg_rtime; 488 lmp->l_msg_ctime = bmp->msg_ctime; 489 lmp->l_msg_qnum = bmp->msg_qnum; 490 lmp->l_msg_qbytes = bmp->msg_qbytes; 491 lmp->l_msg_lspid = bmp->msg_lspid; 492 lmp->l_msg_lrpid = bmp->msg_lrpid; 493 } 494 495 static int 496 linux32_msgctl(struct lwp *l, const struct linux32_sys_ipc_args *uap, register_t *retval) 497 { 498 struct msqid_ds bm, *bmp = NULL; 499 struct linux32_msqid_ds lm; 500 struct linux32_msqid64_ds lm64; 501 int cmd, lcmd, error; 502 void *data = SCARG_P32(uap, ptr); 503 504 lcmd = SCARG(uap, a2); 505 506 switch (lcmd & ~LINUX32_IPC_64) { 507 case LINUX32_IPC_STAT: 508 cmd = IPC_STAT; 509 bmp = &bm; 510 break; 511 case LINUX32_IPC_SET: 512 if (lcmd & LINUX32_IPC_64) { 513 error = copyin(data, &lm64, sizeof lm64); 514 linux32_to_bsd_msqid64_ds(&lm64, &bm); 515 } else { 516 error = copyin(data, &lm, sizeof lm); 517 linux32_to_bsd_msqid_ds(&lm, &bm); 518 } 519 if (error) 520 return error; 521 cmd = IPC_SET; 522 bmp = &bm; 523 break; 524 case LINUX32_IPC_RMID: 525 cmd = IPC_RMID; 526 break; 527 default: 528 return EINVAL; 529 } 530 531 if ((error = msgctl1(l, SCARG(uap, a1), cmd, bmp))) 532 return error; 533 534 switch (lcmd) { 535 case LINUX32_IPC_STAT: 536 bsd_to_linux32_msqid_ds(&bm, &lm); 537 error = copyout(&lm, data, sizeof lm); 538 break; 539 case LINUX32_IPC_STAT|LINUX32_IPC_64: 540 bsd_to_linux32_msqid64_ds(&bm, &lm64); 541 error = copyout(&lm64, data, sizeof lm64); 542 break; 543 default: 544 break; 545 } 546 547 return error; 548 } 549 #endif /* SYSVMSG */ 550 551 #ifdef SYSVSHM 552 static void 553 bsd_to_linux32_shmid_ds(struct shmid_ds *bsp, struct linux32_shmid_ds *lsp) 554 { 555 556 memset(lsp, 0, sizeof *lsp); 557 bsd_to_linux32_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm); 558 lsp->l_shm_segsz = bsp->shm_segsz; 559 lsp->l_shm_atime = bsp->shm_atime; 560 lsp->l_shm_dtime = bsp->shm_dtime; 561 lsp->l_shm_ctime = bsp->shm_ctime; 562 lsp->l_shm_cpid = bsp->shm_cpid; 563 lsp->l_shm_lpid = bsp->shm_lpid; 564 lsp->l_shm_nattch = bsp->shm_nattch; 565 } 566 567 static void 568 linux32_to_bsd_shmid_ds(struct linux32_shmid_ds *lsp, struct shmid_ds *bsp) 569 { 570 571 linux32_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm); 572 bsp->shm_segsz = lsp->l_shm_segsz; 573 bsp->shm_atime = lsp->l_shm_atime; 574 bsp->shm_dtime = lsp->l_shm_dtime; 575 bsp->shm_ctime = lsp->l_shm_ctime; 576 bsp->shm_cpid = lsp->l_shm_cpid; 577 bsp->shm_lpid = lsp->l_shm_lpid; 578 bsp->shm_nattch = lsp->l_shm_nattch; 579 } 580 581 static void 582 bsd_to_linux32_shmid64_ds(struct shmid_ds *bsp, struct linux32_shmid64_ds *lsp) 583 { 584 585 memset(lsp, 0, sizeof *lsp); 586 bsd_to_linux32_ipc64_perm(&bsp->shm_perm, &lsp->l_shm_perm); 587 lsp->l_shm_segsz = bsp->shm_segsz; 588 lsp->l_shm_atime = bsp->shm_atime; 589 lsp->l_shm_dtime = bsp->shm_dtime; 590 lsp->l_shm_ctime = bsp->shm_ctime; 591 lsp->l_shm_cpid = bsp->shm_cpid; 592 lsp->l_shm_lpid = bsp->shm_lpid; 593 lsp->l_shm_nattch = bsp->shm_nattch; 594 } 595 596 static void 597 linux32_to_bsd_shmid64_ds(struct linux32_shmid64_ds *lsp, struct shmid_ds *bsp) 598 { 599 600 linux32_to_bsd_ipc64_perm(&lsp->l_shm_perm, &bsp->shm_perm); 601 bsp->shm_segsz = lsp->l_shm_segsz; 602 bsp->shm_atime = lsp->l_shm_atime; 603 bsp->shm_dtime = lsp->l_shm_dtime; 604 bsp->shm_ctime = lsp->l_shm_ctime; 605 bsp->shm_cpid = lsp->l_shm_cpid; 606 bsp->shm_lpid = lsp->l_shm_lpid; 607 bsp->shm_nattch = lsp->l_shm_nattch; 608 } 609 610 static int 611 linux32_shmat(struct lwp *l, const struct linux32_sys_ipc_args *uap, 612 register_t *retval) 613 { 614 struct sys_shmat_args ua; 615 netbsd32_pointer_t addr32; 616 int error; 617 618 SCARG(&ua, shmid) = SCARG(uap, a1); 619 SCARG(&ua, shmaddr) = SCARG_P32(uap, ptr); 620 SCARG(&ua, shmflg) = SCARG(uap, a2); 621 622 if ((error = sys_shmat(l, &ua, retval))) 623 return error; 624 625 NETBSD32PTR32(addr32, (const void *)(uintptr_t)retval[0]); 626 627 error = copyout(&addr32, NETBSD32IPTR64(SCARG(uap, a3)), sizeof addr32); 628 if (error == 0) 629 retval[0] = 0; 630 631 return error; 632 } 633 634 static int 635 linux32_shmdt(struct lwp *l, const struct linux32_sys_ipc_args *uap, 636 register_t *retval) 637 { 638 struct sys_shmdt_args ua; 639 640 SCARG(&ua, shmaddr) = SCARG_P32(uap, ptr); 641 642 return sys_shmdt(l, &ua, retval); 643 } 644 645 static int 646 linux32_shmget(struct lwp *l, const struct linux32_sys_ipc_args *uap, 647 register_t *retval) 648 { 649 struct sys_shmget_args ua; 650 651 SCARG(&ua, key) = SCARG(uap, a1); 652 SCARG(&ua, size) = SCARG(uap, a2); 653 SCARG(&ua, shmflg) = SCARG(uap, a3) | _SHM_RMLINGER; 654 655 return sys_shmget(l, &ua, retval); 656 } 657 658 static int 659 linux32_shmctl(struct lwp *l, const struct linux32_sys_ipc_args *uap, 660 register_t *retval) 661 { 662 int shmid, cmd, error; 663 struct shmid_ds bs; 664 struct linux32_shmid_ds ls; 665 struct linux32_shmid64_ds ls64; 666 667 shmid = SCARG(uap, a1); 668 cmd = SCARG(uap, a2); 669 670 switch (cmd & ~LINUX32_IPC_64) { 671 672 case LINUX32_SHM_STAT: 673 return ENOSYS; 674 675 case LINUX32_IPC_STAT: 676 error = shmctl1(l, shmid, IPC_STAT, &bs); 677 if (error != 0) 678 return error; 679 if (cmd & LINUX32_IPC_64) { 680 bsd_to_linux32_shmid64_ds(&bs, &ls64); 681 error = copyout(&ls64, SCARG_P32(uap, ptr), sizeof ls64); 682 } else { 683 bsd_to_linux32_shmid_ds(&bs, &ls); 684 error = copyout(&ls, SCARG_P32(uap, ptr), sizeof ls); 685 } 686 return error; 687 688 case LINUX32_IPC_SET: 689 if (cmd & LINUX32_IPC_64) { 690 error = copyin(SCARG_P32(uap, ptr), &ls64, sizeof ls64); 691 linux32_to_bsd_shmid64_ds(&ls64, &bs); 692 } else { 693 error = copyin(SCARG_P32(uap, ptr), &ls, sizeof ls); 694 linux32_to_bsd_shmid_ds(&ls, &bs); 695 } 696 if (error != 0) 697 return error; 698 return shmctl1(l, shmid, IPC_SET, &bs); 699 700 case LINUX32_IPC_RMID: 701 return shmctl1(l, shmid, IPC_RMID, NULL); 702 703 case LINUX32_SHM_LOCK: 704 return shmctl1(l, shmid, SHM_LOCK, NULL); 705 706 case LINUX32_SHM_UNLOCK: 707 return shmctl1(l, shmid, SHM_UNLOCK, NULL); 708 709 case LINUX32_IPC_INFO: 710 case LINUX32_SHM_INFO: 711 return ENOSYS; 712 713 default: 714 return EINVAL; 715 } 716 } 717 #endif /* SYSVSHM */ 718