1 /*- 2 * Copyright (c) 2004 Tim J. Robbins 3 * Copyright (c) 2002 Doug Rabson 4 * Copyright (c) 2000 Marcel Moolenaar 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 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/kernel.h> 36 #include <sys/systm.h> 37 #include <sys/imgact.h> 38 #include <sys/lock.h> 39 #include <sys/malloc.h> 40 #include <sys/mman.h> 41 #include <sys/mutex.h> 42 #include <sys/proc.h> 43 #include <sys/resource.h> 44 #include <sys/resourcevar.h> 45 #include <sys/syscallsubr.h> 46 #include <sys/sysproto.h> 47 #include <sys/unistd.h> 48 49 #include <machine/frame.h> 50 51 #include <vm/vm.h> 52 #include <vm/pmap.h> 53 #include <vm/vm_extern.h> 54 #include <vm/vm_kern.h> 55 #include <vm/vm_map.h> 56 57 #include <amd64/linux32/linux.h> 58 #include <amd64/linux32/linux32_proto.h> 59 #include <compat/linux/linux_ipc.h> 60 #include <compat/linux/linux_signal.h> 61 #include <compat/linux/linux_util.h> 62 63 struct l_old_select_argv { 64 l_int nfds; 65 l_uintptr_t readfds; 66 l_uintptr_t writefds; 67 l_uintptr_t exceptfds; 68 l_uintptr_t timeout; 69 } __packed; 70 71 int 72 linux_to_bsd_sigaltstack(int lsa) 73 { 74 int bsa = 0; 75 76 if (lsa & LINUX_SS_DISABLE) 77 bsa |= SS_DISABLE; 78 if (lsa & LINUX_SS_ONSTACK) 79 bsa |= SS_ONSTACK; 80 return (bsa); 81 } 82 83 int 84 bsd_to_linux_sigaltstack(int bsa) 85 { 86 int lsa = 0; 87 88 if (bsa & SS_DISABLE) 89 lsa |= LINUX_SS_DISABLE; 90 if (bsa & SS_ONSTACK) 91 lsa |= LINUX_SS_ONSTACK; 92 return (lsa); 93 } 94 95 /* 96 * Custom version of exec_copyin_args() so that we can translate 97 * the pointers. 98 */ 99 static int 100 linux_exec_copyin_args(struct image_args *args, char *fname, 101 enum uio_seg segflg, char **argv, char **envv) 102 { 103 char *argp, *envp; 104 u_int32_t *p32, arg; 105 size_t length; 106 int error; 107 108 bzero(args, sizeof(*args)); 109 if (argv == NULL) 110 return (EFAULT); 111 112 /* 113 * Allocate temporary demand zeroed space for argument and 114 * environment strings 115 */ 116 args->buf = (char *) kmem_alloc_wait(exec_map, 117 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 118 if (args->buf == NULL) 119 return (ENOMEM); 120 args->begin_argv = args->buf; 121 args->endp = args->begin_argv; 122 args->stringspace = ARG_MAX; 123 124 args->fname = args->buf + ARG_MAX; 125 126 /* 127 * Copy the file name. 128 */ 129 error = (segflg == UIO_SYSSPACE) ? 130 copystr(fname, args->fname, PATH_MAX, &length) : 131 copyinstr(fname, args->fname, PATH_MAX, &length); 132 if (error != 0) 133 goto err_exit; 134 135 /* 136 * extract arguments first 137 */ 138 p32 = (u_int32_t *)argv; 139 for (;;) { 140 error = copyin(p32++, &arg, sizeof(arg)); 141 if (error) 142 goto err_exit; 143 if (arg == 0) 144 break; 145 argp = PTRIN(arg); 146 error = copyinstr(argp, args->endp, args->stringspace, &length); 147 if (error) { 148 if (error == ENAMETOOLONG) 149 error = E2BIG; 150 151 goto err_exit; 152 } 153 args->stringspace -= length; 154 args->endp += length; 155 args->argc++; 156 } 157 158 args->begin_envv = args->endp; 159 160 /* 161 * extract environment strings 162 */ 163 if (envv) { 164 p32 = (u_int32_t *)envv; 165 for (;;) { 166 error = copyin(p32++, &arg, sizeof(arg)); 167 if (error) 168 goto err_exit; 169 if (arg == 0) 170 break; 171 envp = PTRIN(arg); 172 error = copyinstr(envp, args->endp, args->stringspace, 173 &length); 174 if (error) { 175 if (error == ENAMETOOLONG) 176 error = E2BIG; 177 goto err_exit; 178 } 179 args->stringspace -= length; 180 args->endp += length; 181 args->envc++; 182 } 183 } 184 185 return (0); 186 187 err_exit: 188 kmem_free_wakeup(exec_map, (vm_offset_t)args->buf, 189 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 190 args->buf = NULL; 191 return (error); 192 } 193 194 int 195 linux_execve(struct thread *td, struct linux_execve_args *args) 196 { 197 struct image_args eargs; 198 char *path; 199 int error; 200 201 LCONVPATHEXIST(td, args->path, &path); 202 203 #ifdef DEBUG 204 if (ldebug(execve)) 205 printf(ARGS(execve, "%s"), path); 206 #endif 207 208 error = linux_exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp, 209 args->envp); 210 free(path, M_TEMP); 211 if (error == 0) 212 error = kern_execve(td, &eargs, NULL); 213 return (error); 214 } 215 216 struct iovec32 { 217 u_int32_t iov_base; 218 int iov_len; 219 }; 220 221 CTASSERT(sizeof(struct iovec32) == 8); 222 223 static int 224 linux32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 225 { 226 struct iovec32 iov32; 227 struct iovec *iov; 228 struct uio *uio; 229 u_int iovlen; 230 int error, i; 231 232 *uiop = NULL; 233 if (iovcnt > UIO_MAXIOV) 234 return (EINVAL); 235 iovlen = iovcnt * sizeof(struct iovec); 236 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 237 iov = (struct iovec *)(uio + 1); 238 for (i = 0; i < iovcnt; i++) { 239 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 240 if (error) { 241 free(uio, M_IOV); 242 return (error); 243 } 244 iov[i].iov_base = PTRIN(iov32.iov_base); 245 iov[i].iov_len = iov32.iov_len; 246 } 247 uio->uio_iov = iov; 248 uio->uio_iovcnt = iovcnt; 249 uio->uio_segflg = UIO_USERSPACE; 250 uio->uio_offset = -1; 251 uio->uio_resid = 0; 252 for (i = 0; i < iovcnt; i++) { 253 if (iov->iov_len > INT_MAX - uio->uio_resid) { 254 free(uio, M_IOV); 255 return (EINVAL); 256 } 257 uio->uio_resid += iov->iov_len; 258 iov++; 259 } 260 *uiop = uio; 261 return (0); 262 } 263 264 int 265 linux_readv(struct thread *td, struct linux_readv_args *uap) 266 { 267 struct uio *auio; 268 int error; 269 270 error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); 271 if (error) 272 return (error); 273 error = kern_readv(td, uap->fd, auio); 274 free(auio, M_IOV); 275 return (error); 276 } 277 278 int 279 linux_writev(struct thread *td, struct linux_writev_args *uap) 280 { 281 struct uio *auio; 282 int error; 283 284 error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); 285 if (error) 286 return (error); 287 error = kern_writev(td, uap->fd, auio); 288 free(auio, M_IOV); 289 return (error); 290 } 291 292 struct l_ipc_kludge { 293 l_uintptr_t msgp; 294 l_long msgtyp; 295 } __packed; 296 297 int 298 linux_ipc(struct thread *td, struct linux_ipc_args *args) 299 { 300 301 switch (args->what & 0xFFFF) { 302 case LINUX_SEMOP: { 303 struct linux_semop_args a; 304 305 a.semid = args->arg1; 306 a.tsops = args->ptr; 307 a.nsops = args->arg2; 308 return (linux_semop(td, &a)); 309 } 310 case LINUX_SEMGET: { 311 struct linux_semget_args a; 312 313 a.key = args->arg1; 314 a.nsems = args->arg2; 315 a.semflg = args->arg3; 316 return (linux_semget(td, &a)); 317 } 318 case LINUX_SEMCTL: { 319 struct linux_semctl_args a; 320 int error; 321 322 a.semid = args->arg1; 323 a.semnum = args->arg2; 324 a.cmd = args->arg3; 325 error = copyin(args->ptr, &a.arg, sizeof(a.arg)); 326 if (error) 327 return (error); 328 return (linux_semctl(td, &a)); 329 } 330 case LINUX_MSGSND: { 331 struct linux_msgsnd_args a; 332 333 a.msqid = args->arg1; 334 a.msgp = args->ptr; 335 a.msgsz = args->arg2; 336 a.msgflg = args->arg3; 337 return (linux_msgsnd(td, &a)); 338 } 339 case LINUX_MSGRCV: { 340 struct linux_msgrcv_args a; 341 342 a.msqid = args->arg1; 343 a.msgsz = args->arg2; 344 a.msgflg = args->arg3; 345 if ((args->what >> 16) == 0) { 346 struct l_ipc_kludge tmp; 347 int error; 348 349 if (args->ptr == 0) 350 return (EINVAL); 351 error = copyin(args->ptr, &tmp, sizeof(tmp)); 352 if (error) 353 return (error); 354 a.msgp = PTRIN(tmp.msgp); 355 a.msgtyp = tmp.msgtyp; 356 } else { 357 a.msgp = args->ptr; 358 a.msgtyp = args->arg5; 359 } 360 return (linux_msgrcv(td, &a)); 361 } 362 case LINUX_MSGGET: { 363 struct linux_msgget_args a; 364 365 a.key = args->arg1; 366 a.msgflg = args->arg2; 367 return (linux_msgget(td, &a)); 368 } 369 case LINUX_MSGCTL: { 370 struct linux_msgctl_args a; 371 372 a.msqid = args->arg1; 373 a.cmd = args->arg2; 374 a.buf = args->ptr; 375 return (linux_msgctl(td, &a)); 376 } 377 case LINUX_SHMAT: { 378 struct linux_shmat_args a; 379 380 a.shmid = args->arg1; 381 a.shmaddr = args->ptr; 382 a.shmflg = args->arg2; 383 a.raddr = PTRIN((l_uint)args->arg3); 384 return (linux_shmat(td, &a)); 385 } 386 case LINUX_SHMDT: { 387 struct linux_shmdt_args a; 388 389 a.shmaddr = args->ptr; 390 return (linux_shmdt(td, &a)); 391 } 392 case LINUX_SHMGET: { 393 struct linux_shmget_args a; 394 395 a.key = args->arg1; 396 a.size = args->arg2; 397 a.shmflg = args->arg3; 398 return (linux_shmget(td, &a)); 399 } 400 case LINUX_SHMCTL: { 401 struct linux_shmctl_args a; 402 403 a.shmid = args->arg1; 404 a.cmd = args->arg2; 405 a.buf = args->ptr; 406 return (linux_shmctl(td, &a)); 407 } 408 default: 409 break; 410 } 411 412 return (EINVAL); 413 } 414 415 int 416 linux_old_select(struct thread *td, struct linux_old_select_args *args) 417 { 418 struct l_old_select_argv linux_args; 419 struct linux_select_args newsel; 420 int error; 421 422 #ifdef DEBUG 423 if (ldebug(old_select)) 424 printf(ARGS(old_select, "%p"), args->ptr); 425 #endif 426 427 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 428 if (error) 429 return (error); 430 431 newsel.nfds = linux_args.nfds; 432 newsel.readfds = PTRIN(linux_args.readfds); 433 newsel.writefds = PTRIN(linux_args.writefds); 434 newsel.exceptfds = PTRIN(linux_args.exceptfds); 435 newsel.timeout = PTRIN(linux_args.timeout); 436 return (linux_select(td, &newsel)); 437 } 438 439 int 440 linux_fork(struct thread *td, struct linux_fork_args *args) 441 { 442 int error; 443 444 #ifdef DEBUG 445 if (ldebug(fork)) 446 printf(ARGS(fork, "")); 447 #endif 448 449 if ((error = fork(td, (struct fork_args *)args)) != 0) 450 return (error); 451 452 if (td->td_retval[1] == 1) 453 td->td_retval[0] = 0; 454 return (0); 455 } 456 457 int 458 linux_vfork(struct thread *td, struct linux_vfork_args *args) 459 { 460 int error; 461 462 #ifdef DEBUG 463 if (ldebug(vfork)) 464 printf(ARGS(vfork, "")); 465 #endif 466 467 if ((error = vfork(td, (struct vfork_args *)args)) != 0) 468 return (error); 469 /* Are we the child? */ 470 if (td->td_retval[1] == 1) 471 td->td_retval[0] = 0; 472 return (0); 473 } 474 475 #define CLONE_VM 0x100 476 #define CLONE_FS 0x200 477 #define CLONE_FILES 0x400 478 #define CLONE_SIGHAND 0x800 479 #define CLONE_PID 0x1000 480 481 int 482 linux_clone(struct thread *td, struct linux_clone_args *args) 483 { 484 int error, ff = RFPROC | RFSTOPPED; 485 struct proc *p2; 486 struct thread *td2; 487 int exit_signal; 488 489 #ifdef DEBUG 490 if (ldebug(clone)) { 491 printf(ARGS(clone, "flags %x, stack %x"), 492 (unsigned int)(uintptr_t)args->flags, 493 (unsigned int)(uintptr_t)args->stack); 494 if (args->flags & CLONE_PID) 495 printf(LMSG("CLONE_PID not yet supported")); 496 } 497 #endif 498 499 if (!args->stack) 500 return (EINVAL); 501 502 exit_signal = args->flags & 0x000000ff; 503 if (exit_signal >= LINUX_NSIG) 504 return (EINVAL); 505 506 if (exit_signal <= LINUX_SIGTBLSZ) 507 exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)]; 508 509 if (args->flags & CLONE_VM) 510 ff |= RFMEM; 511 if (args->flags & CLONE_SIGHAND) 512 ff |= RFSIGSHARE; 513 if (!(args->flags & CLONE_FILES)) 514 ff |= RFFDG; 515 516 error = fork1(td, ff, 0, &p2); 517 if (error) 518 return (error); 519 520 521 PROC_LOCK(p2); 522 p2->p_sigparent = exit_signal; 523 PROC_UNLOCK(p2); 524 td2 = FIRST_THREAD_IN_PROC(p2); 525 td2->td_frame->tf_rsp = PTROUT(args->stack); 526 527 #ifdef DEBUG 528 if (ldebug(clone)) 529 printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"), 530 (long)p2->p_pid, args->stack, exit_signal); 531 #endif 532 533 /* 534 * Make this runnable after we are finished with it. 535 */ 536 mtx_lock_spin(&sched_lock); 537 TD_SET_CAN_RUN(td2); 538 setrunqueue(td2, SRQ_BORING); 539 mtx_unlock_spin(&sched_lock); 540 541 td->td_retval[0] = p2->p_pid; 542 td->td_retval[1] = 0; 543 return (0); 544 } 545 546 /* XXX move */ 547 struct l_mmap_argv { 548 l_ulong addr; 549 l_ulong len; 550 l_ulong prot; 551 l_ulong flags; 552 l_ulong fd; 553 l_ulong pgoff; 554 }; 555 556 #define STACK_SIZE (2 * 1024 * 1024) 557 #define GUARD_SIZE (4 * PAGE_SIZE) 558 559 static int linux_mmap_common(struct thread *, struct l_mmap_argv *); 560 561 int 562 linux_mmap2(struct thread *td, struct linux_mmap2_args *args) 563 { 564 struct l_mmap_argv linux_args; 565 566 #ifdef DEBUG 567 if (ldebug(mmap2)) 568 printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"), 569 (void *)(intptr_t)args->addr, args->len, args->prot, 570 args->flags, args->fd, args->pgoff); 571 #endif 572 573 linux_args.addr = PTROUT(args->addr); 574 linux_args.len = args->len; 575 linux_args.prot = args->prot; 576 linux_args.flags = args->flags; 577 linux_args.fd = args->fd; 578 linux_args.pgoff = args->pgoff; 579 580 return (linux_mmap_common(td, &linux_args)); 581 } 582 583 int 584 linux_mmap(struct thread *td, struct linux_mmap_args *args) 585 { 586 int error; 587 struct l_mmap_argv linux_args; 588 589 error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 590 if (error) 591 return (error); 592 593 #ifdef DEBUG 594 if (ldebug(mmap)) 595 printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"), 596 (void *)(intptr_t)linux_args.addr, linux_args.len, 597 linux_args.prot, linux_args.flags, linux_args.fd, 598 linux_args.pgoff); 599 #endif 600 if ((linux_args.pgoff % PAGE_SIZE) != 0) 601 return (EINVAL); 602 linux_args.pgoff /= PAGE_SIZE; 603 604 return (linux_mmap_common(td, &linux_args)); 605 } 606 607 static int 608 linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args) 609 { 610 struct proc *p = td->td_proc; 611 struct mmap_args /* { 612 caddr_t addr; 613 size_t len; 614 int prot; 615 int flags; 616 int fd; 617 long pad; 618 off_t pos; 619 } */ bsd_args; 620 int error; 621 622 error = 0; 623 bsd_args.flags = 0; 624 if (linux_args->flags & LINUX_MAP_SHARED) 625 bsd_args.flags |= MAP_SHARED; 626 if (linux_args->flags & LINUX_MAP_PRIVATE) 627 bsd_args.flags |= MAP_PRIVATE; 628 if (linux_args->flags & LINUX_MAP_FIXED) 629 bsd_args.flags |= MAP_FIXED; 630 if (linux_args->flags & LINUX_MAP_ANON) 631 bsd_args.flags |= MAP_ANON; 632 else 633 bsd_args.flags |= MAP_NOSYNC; 634 if (linux_args->flags & LINUX_MAP_GROWSDOWN) { 635 bsd_args.flags |= MAP_STACK; 636 637 /* The linux MAP_GROWSDOWN option does not limit auto 638 * growth of the region. Linux mmap with this option 639 * takes as addr the inital BOS, and as len, the initial 640 * region size. It can then grow down from addr without 641 * limit. However, linux threads has an implicit internal 642 * limit to stack size of STACK_SIZE. Its just not 643 * enforced explicitly in linux. But, here we impose 644 * a limit of (STACK_SIZE - GUARD_SIZE) on the stack 645 * region, since we can do this with our mmap. 646 * 647 * Our mmap with MAP_STACK takes addr as the maximum 648 * downsize limit on BOS, and as len the max size of 649 * the region. It them maps the top SGROWSIZ bytes, 650 * and autgrows the region down, up to the limit 651 * in addr. 652 * 653 * If we don't use the MAP_STACK option, the effect 654 * of this code is to allocate a stack region of a 655 * fixed size of (STACK_SIZE - GUARD_SIZE). 656 */ 657 658 /* This gives us TOS */ 659 bsd_args.addr = (caddr_t)PTRIN(linux_args->addr) + 660 linux_args->len; 661 662 if ((caddr_t)PTRIN(bsd_args.addr) > 663 p->p_vmspace->vm_maxsaddr) { 664 /* Some linux apps will attempt to mmap 665 * thread stacks near the top of their 666 * address space. If their TOS is greater 667 * than vm_maxsaddr, vm_map_growstack() 668 * will confuse the thread stack with the 669 * process stack and deliver a SEGV if they 670 * attempt to grow the thread stack past their 671 * current stacksize rlimit. To avoid this, 672 * adjust vm_maxsaddr upwards to reflect 673 * the current stacksize rlimit rather 674 * than the maximum possible stacksize. 675 * It would be better to adjust the 676 * mmap'ed region, but some apps do not check 677 * mmap's return value. 678 */ 679 PROC_LOCK(p); 680 p->p_vmspace->vm_maxsaddr = 681 (char *)LINUX32_USRSTACK - 682 lim_cur(p, RLIMIT_STACK); 683 PROC_UNLOCK(p); 684 } 685 686 /* This gives us our maximum stack size */ 687 if (linux_args->len > STACK_SIZE - GUARD_SIZE) 688 bsd_args.len = linux_args->len; 689 else 690 bsd_args.len = STACK_SIZE - GUARD_SIZE; 691 692 /* This gives us a new BOS. If we're using VM_STACK, then 693 * mmap will just map the top SGROWSIZ bytes, and let 694 * the stack grow down to the limit at BOS. If we're 695 * not using VM_STACK we map the full stack, since we 696 * don't have a way to autogrow it. 697 */ 698 bsd_args.addr -= bsd_args.len; 699 } else { 700 bsd_args.addr = (caddr_t)PTRIN(linux_args->addr); 701 bsd_args.len = linux_args->len; 702 } 703 /* 704 * XXX i386 Linux always emulator forces PROT_READ on (why?) 705 * so we do the same. We add PROT_EXEC to work around buggy 706 * applications (e.g. Java) that take advantage of the fact 707 * that execute permissions are not enforced by x86 CPUs. 708 */ 709 bsd_args.prot = linux_args->prot | PROT_EXEC | PROT_READ; 710 if (linux_args->flags & LINUX_MAP_ANON) 711 bsd_args.fd = -1; 712 else 713 bsd_args.fd = linux_args->fd; 714 bsd_args.pos = (off_t)linux_args->pgoff * PAGE_SIZE; 715 bsd_args.pad = 0; 716 717 #ifdef DEBUG 718 if (ldebug(mmap)) 719 printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n", 720 __func__, 721 (void *)bsd_args.addr, (int)bsd_args.len, bsd_args.prot, 722 bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); 723 #endif 724 error = mmap(td, &bsd_args); 725 #ifdef DEBUG 726 if (ldebug(mmap)) 727 printf("-> %s() return: 0x%x (0x%08x)\n", 728 __func__, error, (u_int)td->td_retval[0]); 729 #endif 730 return (error); 731 } 732 733 int 734 linux_pipe(struct thread *td, struct linux_pipe_args *args) 735 { 736 int pip[2]; 737 int error; 738 register_t reg_rdx; 739 740 #ifdef DEBUG 741 if (ldebug(pipe)) 742 printf(ARGS(pipe, "*")); 743 #endif 744 745 reg_rdx = td->td_retval[1]; 746 error = pipe(td, 0); 747 if (error) { 748 td->td_retval[1] = reg_rdx; 749 return (error); 750 } 751 752 pip[0] = td->td_retval[0]; 753 pip[1] = td->td_retval[1]; 754 error = copyout(pip, args->pipefds, 2 * sizeof(int)); 755 if (error) { 756 td->td_retval[1] = reg_rdx; 757 return (error); 758 } 759 760 td->td_retval[1] = reg_rdx; 761 td->td_retval[0] = 0; 762 return (0); 763 } 764 765 int 766 linux_sigaction(struct thread *td, struct linux_sigaction_args *args) 767 { 768 l_osigaction_t osa; 769 l_sigaction_t act, oact; 770 int error; 771 772 #ifdef DEBUG 773 if (ldebug(sigaction)) 774 printf(ARGS(sigaction, "%d, %p, %p"), 775 args->sig, (void *)args->nsa, (void *)args->osa); 776 #endif 777 778 if (args->nsa != NULL) { 779 error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); 780 if (error) 781 return (error); 782 act.lsa_handler = osa.lsa_handler; 783 act.lsa_flags = osa.lsa_flags; 784 act.lsa_restorer = osa.lsa_restorer; 785 LINUX_SIGEMPTYSET(act.lsa_mask); 786 act.lsa_mask.__bits[0] = osa.lsa_mask; 787 } 788 789 error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, 790 args->osa ? &oact : NULL); 791 792 if (args->osa != NULL && !error) { 793 osa.lsa_handler = oact.lsa_handler; 794 osa.lsa_flags = oact.lsa_flags; 795 osa.lsa_restorer = oact.lsa_restorer; 796 osa.lsa_mask = oact.lsa_mask.__bits[0]; 797 error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); 798 } 799 800 return (error); 801 } 802 803 /* 804 * Linux has two extra args, restart and oldmask. We dont use these, 805 * but it seems that "restart" is actually a context pointer that 806 * enables the signal to happen with a different register set. 807 */ 808 int 809 linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) 810 { 811 sigset_t sigmask; 812 l_sigset_t mask; 813 814 #ifdef DEBUG 815 if (ldebug(sigsuspend)) 816 printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); 817 #endif 818 819 LINUX_SIGEMPTYSET(mask); 820 mask.__bits[0] = args->mask; 821 linux_to_bsd_sigset(&mask, &sigmask); 822 return (kern_sigsuspend(td, sigmask)); 823 } 824 825 int 826 linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) 827 { 828 l_sigset_t lmask; 829 sigset_t sigmask; 830 int error; 831 832 #ifdef DEBUG 833 if (ldebug(rt_sigsuspend)) 834 printf(ARGS(rt_sigsuspend, "%p, %d"), 835 (void *)uap->newset, uap->sigsetsize); 836 #endif 837 838 if (uap->sigsetsize != sizeof(l_sigset_t)) 839 return (EINVAL); 840 841 error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); 842 if (error) 843 return (error); 844 845 linux_to_bsd_sigset(&lmask, &sigmask); 846 return (kern_sigsuspend(td, sigmask)); 847 } 848 849 int 850 linux_pause(struct thread *td, struct linux_pause_args *args) 851 { 852 struct proc *p = td->td_proc; 853 sigset_t sigmask; 854 855 #ifdef DEBUG 856 if (ldebug(pause)) 857 printf(ARGS(pause, "")); 858 #endif 859 860 PROC_LOCK(p); 861 sigmask = td->td_sigmask; 862 PROC_UNLOCK(p); 863 return (kern_sigsuspend(td, sigmask)); 864 } 865 866 int 867 linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) 868 { 869 stack_t ss, oss; 870 l_stack_t lss; 871 int error; 872 873 #ifdef DEBUG 874 if (ldebug(sigaltstack)) 875 printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); 876 #endif 877 878 if (uap->uss != NULL) { 879 error = copyin(uap->uss, &lss, sizeof(l_stack_t)); 880 if (error) 881 return (error); 882 883 ss.ss_sp = PTRIN(lss.ss_sp); 884 ss.ss_size = lss.ss_size; 885 ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); 886 } 887 error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, 888 (uap->uoss != NULL) ? &oss : NULL); 889 if (!error && uap->uoss != NULL) { 890 lss.ss_sp = PTROUT(oss.ss_sp); 891 lss.ss_size = oss.ss_size; 892 lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); 893 error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); 894 } 895 896 return (error); 897 } 898 899 int 900 linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) 901 { 902 struct ftruncate_args sa; 903 904 #ifdef DEBUG 905 if (ldebug(ftruncate64)) 906 printf(ARGS(ftruncate64, "%u, %jd"), args->fd, 907 (intmax_t)args->length); 908 #endif 909 910 sa.fd = args->fd; 911 sa.pad = 0; 912 sa.length = args->length; 913 return ftruncate(td, &sa); 914 } 915 916 int 917 linux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap) 918 { 919 struct timeval atv; 920 l_timeval atv32; 921 struct timezone rtz; 922 int error = 0; 923 924 if (uap->tp) { 925 microtime(&atv); 926 atv32.tv_sec = atv.tv_sec; 927 atv32.tv_usec = atv.tv_usec; 928 error = copyout(&atv32, uap->tp, sizeof (atv32)); 929 } 930 if (error == 0 && uap->tzp != NULL) { 931 rtz.tz_minuteswest = tz_minuteswest; 932 rtz.tz_dsttime = tz_dsttime; 933 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 934 } 935 return (error); 936 } 937 938 int 939 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *uap) 940 { 941 struct timespec rqt, rmt; 942 struct l_timespec ats32; 943 int error; 944 945 error = copyin(uap->rqtp, &ats32, sizeof(ats32)); 946 if (error != 0) 947 return (error); 948 rqt.tv_sec = ats32.tv_sec; 949 rqt.tv_nsec = ats32.tv_nsec; 950 error = kern_nanosleep(td, &rqt, &rmt); 951 if (uap->rmtp != NULL) { 952 ats32.tv_sec = rmt.tv_sec; 953 ats32.tv_nsec = rmt.tv_nsec; 954 error = copyout(&ats32, uap->rmtp, sizeof(ats32)); 955 } 956 return (error); 957 } 958 959 int 960 linux_getrusage(struct thread *td, struct linux_getrusage_args *uap) 961 { 962 struct l_rusage s32; 963 struct rusage s; 964 int error; 965 966 error = kern_getrusage(td, uap->who, &s); 967 if (error != 0) 968 return (error); 969 if (uap->rusage != NULL) { 970 s32.ru_utime.tv_sec = s.ru_utime.tv_sec; 971 s32.ru_utime.tv_usec = s.ru_utime.tv_usec; 972 s32.ru_stime.tv_sec = s.ru_stime.tv_sec; 973 s32.ru_stime.tv_usec = s.ru_stime.tv_usec; 974 s32.ru_maxrss = s.ru_maxrss; 975 s32.ru_ixrss = s.ru_ixrss; 976 s32.ru_idrss = s.ru_idrss; 977 s32.ru_isrss = s.ru_isrss; 978 s32.ru_minflt = s.ru_minflt; 979 s32.ru_majflt = s.ru_majflt; 980 s32.ru_nswap = s.ru_nswap; 981 s32.ru_inblock = s.ru_inblock; 982 s32.ru_oublock = s.ru_oublock; 983 s32.ru_msgsnd = s.ru_msgsnd; 984 s32.ru_msgrcv = s.ru_msgrcv; 985 s32.ru_nsignals = s.ru_nsignals; 986 s32.ru_nvcsw = s.ru_nvcsw; 987 s32.ru_nivcsw = s.ru_nivcsw; 988 error = copyout(&s32, uap->rusage, sizeof(s32)); 989 } 990 return (error); 991 } 992 993 int 994 linux_sched_rr_get_interval(struct thread *td, 995 struct linux_sched_rr_get_interval_args *uap) 996 { 997 struct timespec ts; 998 struct l_timespec ts32; 999 int error; 1000 1001 error = kern_sched_rr_get_interval(td, uap->pid, &ts); 1002 if (error != 0) 1003 return (error); 1004 ts32.tv_sec = ts.tv_sec; 1005 ts32.tv_nsec = ts.tv_nsec; 1006 return (copyout(&ts32, uap->interval, sizeof(ts32))); 1007 } 1008 1009 int 1010 linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) 1011 { 1012 struct mprotect_args bsd_args; 1013 1014 bsd_args.addr = uap->addr; 1015 bsd_args.len = uap->len; 1016 bsd_args.prot = uap->prot; 1017 /* XXX PROT_READ implies PROT_EXEC; see linux_mmap_common(). */ 1018 if ((bsd_args.prot & PROT_READ) != 0) 1019 bsd_args.prot |= PROT_EXEC; 1020 return (mprotect(td, &bsd_args)); 1021 } 1022