1 /* $NetBSD: linux_misc.c,v 1.52 1998/12/16 10:21:50 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden and Eric Haszlakiewicz. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Linux compatibility module. Try to deal with various Linux system calls. 41 */ 42 43 /* 44 * These functions have been moved to multiarch to allow 45 * selection of which machines include them to be 46 * determined by the individual files.linux_<arch> files. 47 * 48 * Function in multiarch: 49 * linux_sys_break : linux_break.c 50 * linux_sys_alarm : linux_misc_notalpha.c 51 * linux_sys_nice : linux_misc_notalpha.c 52 * linux_sys_readdir : linux_misc_notalpha.c 53 * linux_sys_time : linux_misc_notalpha.c 54 * linux_sys_utime : linux_misc_notalpha.c 55 * linux_sys_waitpid : linux_misc_notalpha.c 56 * linux_sys_old_mmap : linux_oldmmap.c 57 * linux_sys_oldolduname : linux_oldolduname.c 58 * linux_sys_oldselect : linux_oldselect.c 59 * linux_sys_olduname : linux_olduname.c 60 * linux_sys_pipe : linux_pipe.c 61 */ 62 63 #include <sys/param.h> 64 #include <sys/systm.h> 65 #include <sys/namei.h> 66 #include <sys/proc.h> 67 #include <sys/dirent.h> 68 #include <sys/file.h> 69 #include <sys/stat.h> 70 #include <sys/filedesc.h> 71 #include <sys/ioctl.h> 72 #include <sys/kernel.h> 73 #include <sys/malloc.h> 74 #include <sys/mbuf.h> 75 #include <sys/mman.h> 76 #include <sys/mount.h> 77 #include <sys/ptrace.h> 78 #include <sys/resource.h> 79 #include <sys/resourcevar.h> 80 #include <sys/signal.h> 81 #include <sys/signalvar.h> 82 #include <sys/socket.h> 83 #include <sys/time.h> 84 #include <sys/times.h> 85 #include <sys/vnode.h> 86 #include <sys/uio.h> 87 #include <sys/wait.h> 88 #include <sys/utsname.h> 89 #include <sys/unistd.h> 90 91 #include <sys/syscallargs.h> 92 93 #include <vm/vm.h> 94 #include <vm/vm_param.h> 95 96 #include <compat/linux/common/linux_types.h> 97 #include <compat/linux/common/linux_signal.h> 98 99 #include <compat/linux/linux_syscallargs.h> 100 101 #include <compat/linux/common/linux_fcntl.h> 102 #include <compat/linux/common/linux_mmap.h> 103 #include <compat/linux/common/linux_dirent.h> 104 #include <compat/linux/common/linux_util.h> 105 #include <compat/linux/common/linux_misc.h> 106 107 108 /* Local linux_misc.c functions: */ 109 static void bsd_to_linux_statfs __P((struct statfs *, struct linux_statfs *)); 110 111 /* 112 * The information on a terminated (or stopped) process needs 113 * to be converted in order for Linux binaries to get a valid signal 114 * number out of it. 115 */ 116 void 117 bsd_to_linux_wstat(st) 118 int *st; 119 { 120 121 int sig; 122 123 if (WIFSIGNALED(*st)) { 124 sig = WTERMSIG(*st); 125 if (sig >= 0 && sig < NSIG) 126 *st= (*st& ~0177) | native_to_linux_sig[sig]; 127 } else if (WIFSTOPPED(*st)) { 128 sig = WSTOPSIG(*st); 129 if (sig >= 0 && sig < NSIG) 130 *st = (*st & ~0xff00) | (native_to_linux_sig[sig] << 8); 131 } 132 } 133 134 /* 135 * This is very much the same as waitpid() 136 */ 137 int 138 linux_sys_wait4(p, v, retval) 139 struct proc *p; 140 void *v; 141 register_t *retval; 142 { 143 struct linux_sys_wait4_args /* { 144 syscallarg(int) pid; 145 syscallarg(int *) status; 146 syscallarg(int) options; 147 syscallarg(struct rusage *) rusage; 148 } */ *uap = v; 149 struct sys_wait4_args w4a; 150 int error, *status, tstat; 151 caddr_t sg; 152 153 if (SCARG(uap, status) != NULL) { 154 sg = stackgap_init(p->p_emul); 155 status = (int *) stackgap_alloc(&sg, sizeof *status); 156 } else 157 status = NULL; 158 159 SCARG(&w4a, pid) = SCARG(uap, pid); 160 SCARG(&w4a, status) = status; 161 SCARG(&w4a, options) = SCARG(uap, options); 162 SCARG(&w4a, rusage) = SCARG(uap, rusage); 163 164 if ((error = sys_wait4(p, &w4a, retval))) 165 return error; 166 167 sigdelset(&p->p_siglist, SIGCHLD); 168 169 if (status != NULL) { 170 if ((error = copyin(status, &tstat, sizeof tstat))) 171 return error; 172 173 bsd_to_linux_wstat(&tstat); 174 return copyout(&tstat, SCARG(uap, status), sizeof tstat); 175 } 176 177 return 0; 178 } 179 180 /* 181 * Linux brk(2). The check if the new address is >= the old one is 182 * done in the kernel in Linux. NetBSD does it in the library. 183 */ 184 int 185 linux_sys_brk(p, v, retval) 186 struct proc *p; 187 void *v; 188 register_t *retval; 189 { 190 struct linux_sys_brk_args /* { 191 syscallarg(char *) nsize; 192 } */ *uap = v; 193 char *nbrk = SCARG(uap, nsize); 194 struct sys_obreak_args oba; 195 struct vmspace *vm = p->p_vmspace; 196 caddr_t oldbrk; 197 198 oldbrk = vm->vm_daddr + ctob(vm->vm_dsize); 199 /* 200 * XXX inconsistent.. Linux always returns at least the old 201 * brk value, but it will be page-aligned if this fails, 202 * and possibly not page aligned if it succeeds (the user 203 * supplied pointer is returned). 204 */ 205 SCARG(&oba, nsize) = nbrk; 206 207 if ((caddr_t) nbrk > vm->vm_daddr && sys_obreak(p, &oba, retval) == 0) 208 retval[0] = (register_t)nbrk; 209 else 210 retval[0] = (register_t)oldbrk; 211 212 return 0; 213 } 214 215 /* 216 * Convert BSD statfs structure to Linux statfs structure. 217 * The Linux structure has less fields, and it also wants 218 * the length of a name in a dir entry in a field, which 219 * we fake (probably the wrong way). 220 */ 221 static void 222 bsd_to_linux_statfs(bsp, lsp) 223 struct statfs *bsp; 224 struct linux_statfs *lsp; 225 { 226 227 lsp->l_ftype = bsp->f_type; 228 lsp->l_fbsize = bsp->f_bsize; 229 lsp->l_fblocks = bsp->f_blocks; 230 lsp->l_fbfree = bsp->f_bfree; 231 lsp->l_fbavail = bsp->f_bavail; 232 lsp->l_ffiles = bsp->f_files; 233 lsp->l_fffree = bsp->f_ffree; 234 lsp->l_ffsid.val[0] = bsp->f_fsid.val[0]; 235 lsp->l_ffsid.val[1] = bsp->f_fsid.val[1]; 236 lsp->l_fnamelen = MAXNAMLEN; /* XXX */ 237 } 238 239 /* 240 * Implement the fs stat functions. Straightforward. 241 */ 242 int 243 linux_sys_statfs(p, v, retval) 244 struct proc *p; 245 void *v; 246 register_t *retval; 247 { 248 struct linux_sys_statfs_args /* { 249 syscallarg(char *) path; 250 syscallarg(struct linux_statfs *) sp; 251 } */ *uap = v; 252 struct statfs btmp, *bsp; 253 struct linux_statfs ltmp; 254 struct sys_statfs_args bsa; 255 caddr_t sg; 256 int error; 257 258 sg = stackgap_init(p->p_emul); 259 bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs)); 260 261 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 262 263 SCARG(&bsa, path) = SCARG(uap, path); 264 SCARG(&bsa, buf) = bsp; 265 266 if ((error = sys_statfs(p, &bsa, retval))) 267 return error; 268 269 if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) 270 return error; 271 272 bsd_to_linux_statfs(&btmp, <mp); 273 274 return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); 275 } 276 277 int 278 linux_sys_fstatfs(p, v, retval) 279 struct proc *p; 280 void *v; 281 register_t *retval; 282 { 283 struct linux_sys_fstatfs_args /* { 284 syscallarg(int) fd; 285 syscallarg(struct linux_statfs *) sp; 286 } */ *uap = v; 287 struct statfs btmp, *bsp; 288 struct linux_statfs ltmp; 289 struct sys_fstatfs_args bsa; 290 caddr_t sg; 291 int error; 292 293 sg = stackgap_init(p->p_emul); 294 bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs)); 295 296 SCARG(&bsa, fd) = SCARG(uap, fd); 297 SCARG(&bsa, buf) = bsp; 298 299 if ((error = sys_fstatfs(p, &bsa, retval))) 300 return error; 301 302 if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) 303 return error; 304 305 bsd_to_linux_statfs(&btmp, <mp); 306 307 return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); 308 } 309 310 /* 311 * uname(). Just copy the info from the various strings stored in the 312 * kernel, and put it in the Linux utsname structure. That structure 313 * is almost the same as the NetBSD one, only it has fields 65 characters 314 * long, and an extra domainname field. 315 */ 316 int 317 linux_sys_uname(p, v, retval) 318 struct proc *p; 319 void *v; 320 register_t *retval; 321 { 322 struct linux_sys_uname_args /* { 323 syscallarg(struct linux_utsname *) up; 324 } */ *uap = v; 325 extern char ostype[], hostname[], osrelease[], version[], machine[], 326 domainname[]; 327 struct linux_utsname luts; 328 int len; 329 char *cp; 330 331 strncpy(luts.l_sysname, ostype, sizeof(luts.l_sysname)); 332 strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); 333 strncpy(luts.l_release, osrelease, sizeof(luts.l_release)); 334 strncpy(luts.l_version, version, sizeof(luts.l_version)); 335 strncpy(luts.l_machine, machine, sizeof(luts.l_machine)); 336 strncpy(luts.l_domainname, domainname, sizeof(luts.l_domainname)); 337 338 /* This part taken from the the uname() in libc */ 339 len = sizeof(luts.l_version); 340 for (cp = luts.l_version; len--; ++cp) { 341 if (*cp == '\n' || *cp == '\t') { 342 if (len > 1) 343 *cp = ' '; 344 else 345 *cp = '\0'; 346 } 347 } 348 349 return copyout(&luts, SCARG(uap, up), sizeof(luts)); 350 } 351 352 /* Used directly on: alpha, mips, ppc, sparc, sparc64 */ 353 /* Used indirectly on: arm, i386, m68k */ 354 355 /* 356 * New type Linux mmap call. 357 * Only called directly on machines with >= 6 free regs. 358 */ 359 int 360 linux_sys_mmap(p, v, retval) 361 struct proc *p; 362 void *v; 363 register_t *retval; 364 { 365 struct linux_sys_mmap_args /* { 366 syscallarg(unsigned long) addr; 367 syscallarg(size_t) len; 368 syscallarg(int) prot; 369 syscallarg(int) flags; 370 syscallarg(int) fd; 371 syscallarg(off_t) offset; 372 } */ *uap = v; 373 struct sys_mmap_args cma; 374 int flags; 375 376 flags = 0; 377 flags |= cvtto_bsd_mask(SCARG(uap,flags), LINUX_MAP_SHARED, MAP_SHARED); 378 flags |= cvtto_bsd_mask(SCARG(uap,flags), LINUX_MAP_PRIVATE, MAP_PRIVATE); 379 flags |= cvtto_bsd_mask(SCARG(uap,flags), LINUX_MAP_FIXED, MAP_FIXED); 380 flags |= cvtto_bsd_mask(SCARG(uap,flags), LINUX_MAP_ANON, MAP_ANON); 381 /* XXX XAX ERH: Any other flags here? There are more defined... */ 382 383 SCARG(&cma,addr) = (void *)SCARG(uap, addr); 384 SCARG(&cma,len) = SCARG(uap, len); 385 SCARG(&cma,prot) = SCARG(uap, prot); 386 if (SCARG(&cma,prot) & VM_PROT_WRITE) /* XXX */ 387 SCARG(&cma,prot) |= VM_PROT_READ; 388 SCARG(&cma,flags) = flags; 389 SCARG(&cma,fd) = SCARG(uap, fd); 390 SCARG(&cma,pad) = 0; 391 SCARG(&cma,pos) = SCARG(uap, offset); 392 393 return sys_mmap(p, &cma, retval); 394 } 395 396 int 397 linux_sys_mremap(p, v, retval) 398 struct proc *p; 399 void *v; 400 register_t *retval; 401 { 402 struct linux_sys_mremap_args /* { 403 syscallarg(void *) old_address; 404 syscallarg(size_t) old_size; 405 syscallarg(size_t) new_size; 406 syscallarg(u_long) flags; 407 } */ *uap = v; 408 struct sys_munmap_args mua; 409 size_t old_size, new_size; 410 int error; 411 412 old_size = round_page(SCARG(uap, old_size)); 413 new_size = round_page(SCARG(uap, new_size)); 414 415 /* 416 * Growing mapped region. 417 */ 418 if (new_size > old_size) { 419 /* 420 * XXX Implement me. What we probably want to do is 421 * XXX dig out the guts of the old mapping, mmap that 422 * XXX object again with the new size, then munmap 423 * XXX the old mapping. 424 */ 425 *retval = 0; 426 return (ENOMEM); 427 } 428 429 /* 430 * Shrinking mapped region. 431 */ 432 if (new_size < old_size) { 433 SCARG(&mua, addr) = (caddr_t)SCARG(uap, old_address) + 434 new_size; 435 SCARG(&mua, len) = old_size - new_size; 436 error = sys_munmap(p, &mua, retval); 437 *retval = error ? 0 : (register_t)SCARG(uap, old_address); 438 return (error); 439 } 440 441 /* 442 * No change. 443 */ 444 *retval = (register_t)SCARG(uap, old_address); 445 return (0); 446 } 447 448 int 449 linux_sys_msync(p, v, retval) 450 struct proc *p; 451 void *v; 452 register_t *retval; 453 { 454 struct linux_sys_msync_args /* { 455 syscallarg(caddr_t) addr; 456 syscallarg(int) len; 457 syscallarg(int) fl; 458 } */ *uap = v; 459 460 struct sys___msync13_args bma; 461 462 /* flags are ignored */ 463 SCARG(&bma, addr) = SCARG(uap, addr); 464 SCARG(&bma, len) = SCARG(uap, len); 465 SCARG(&bma, flags) = SCARG(uap, fl); 466 467 return sys___msync13(p, &bma, retval); 468 } 469 470 /* 471 * This code is partly stolen from src/lib/libc/compat-43/times.c 472 * XXX - CLK_TCK isn't declared in /sys, just in <time.h>, done here 473 */ 474 475 #define CLK_TCK 100 476 #define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 477 478 int 479 linux_sys_times(p, v, retval) 480 struct proc *p; 481 void *v; 482 register_t *retval; 483 { 484 struct linux_sys_times_args /* { 485 syscallarg(struct times *) tms; 486 } */ *uap = v; 487 struct timeval t; 488 struct linux_tms ltms; 489 struct rusage ru; 490 int error, s; 491 492 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL); 493 ltms.ltms_utime = CONVTCK(ru.ru_utime); 494 ltms.ltms_stime = CONVTCK(ru.ru_stime); 495 496 ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime); 497 ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime); 498 499 if ((error = copyout(<ms, SCARG(uap, tms), sizeof ltms))) 500 return error; 501 502 s = splclock(); 503 timersub(&time, &boottime, &t); 504 splx(s); 505 506 retval[0] = ((linux_clock_t)(CONVTCK(t))); 507 return 0; 508 } 509 510 /* 511 * Linux 'readdir' call. This code is mostly taken from the 512 * SunOS getdents call (see compat/sunos/sunos_misc.c), though 513 * an attempt has been made to keep it a little cleaner (failing 514 * miserably, because of the cruft needed if count 1 is passed). 515 * 516 * The d_off field should contain the offset of the next valid entry, 517 * but in Linux it has the offset of the entry itself. We emulate 518 * that bug here. 519 * 520 * Read in BSD-style entries, convert them, and copy them out. 521 * 522 * Note that this doesn't handle union-mounted filesystems. 523 */ 524 int 525 linux_sys_getdents(p, v, retval) 526 struct proc *p; 527 void *v; 528 register_t *retval; 529 { 530 struct linux_sys_getdents_args /* { 531 syscallarg(int) fd; 532 syscallarg(struct linux_dirent *) dent; 533 syscallarg(unsigned int) count; 534 } */ *uap = v; 535 register struct dirent *bdp; 536 struct vnode *vp; 537 caddr_t inp, buf; /* BSD-format */ 538 int len, reclen; /* BSD-format */ 539 caddr_t outp; /* Linux-format */ 540 int resid, linux_reclen = 0; /* Linux-format */ 541 struct file *fp; 542 struct uio auio; 543 struct iovec aiov; 544 struct linux_dirent idb; 545 off_t off; /* true file offset */ 546 int buflen, error, eofflag, nbytes, oldcall; 547 struct vattr va; 548 off_t *cookiebuf = NULL, *cookie; 549 int ncookies; 550 551 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 552 return (error); 553 554 if ((fp->f_flag & FREAD) == 0) 555 return (EBADF); 556 557 vp = (struct vnode *)fp->f_data; 558 if (vp->v_type != VDIR) 559 return (EINVAL); 560 561 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) 562 return error; 563 564 nbytes = SCARG(uap, count); 565 if (nbytes == 1) { /* emulating old, broken behaviour */ 566 nbytes = sizeof (struct linux_dirent); 567 buflen = max(va.va_blocksize, nbytes); 568 oldcall = 1; 569 } else { 570 buflen = min(MAXBSIZE, nbytes); 571 if (buflen < va.va_blocksize) 572 buflen = va.va_blocksize; 573 oldcall = 0; 574 } 575 buf = malloc(buflen, M_TEMP, M_WAITOK); 576 577 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 578 off = fp->f_offset; 579 again: 580 aiov.iov_base = buf; 581 aiov.iov_len = buflen; 582 auio.uio_iov = &aiov; 583 auio.uio_iovcnt = 1; 584 auio.uio_rw = UIO_READ; 585 auio.uio_segflg = UIO_SYSSPACE; 586 auio.uio_procp = p; 587 auio.uio_resid = buflen; 588 auio.uio_offset = off; 589 /* 590 * First we read into the malloc'ed buffer, then 591 * we massage it into user space, one record at a time. 592 */ 593 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf, 594 &ncookies); 595 if (error) 596 goto out; 597 598 inp = buf; 599 outp = (caddr_t)SCARG(uap, dent); 600 resid = nbytes; 601 if ((len = buflen - auio.uio_resid) == 0) 602 goto eof; 603 604 for (cookie = cookiebuf; len > 0; len -= reclen) { 605 bdp = (struct dirent *)inp; 606 reclen = bdp->d_reclen; 607 if (reclen & 3) 608 panic("linux_readdir"); 609 if (bdp->d_fileno == 0) { 610 inp += reclen; /* it is a hole; squish it out */ 611 off = *cookie++; 612 continue; 613 } 614 linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen); 615 if (reclen > len || resid < linux_reclen) { 616 /* entry too big for buffer, so just stop */ 617 outp++; 618 break; 619 } 620 /* 621 * Massage in place to make a Linux-shaped dirent (otherwise 622 * we have to worry about touching user memory outside of 623 * the copyout() call). 624 */ 625 idb.d_ino = (linux_ino_t)bdp->d_fileno; 626 /* 627 * The old readdir() call misuses the offset and reclen fields. 628 */ 629 if (oldcall) { 630 idb.d_off = (linux_off_t)linux_reclen; 631 idb.d_reclen = (u_short)bdp->d_namlen; 632 } else { 633 if (sizeof (linux_off_t) < 4 && (off >> 32) != 0) { 634 compat_offseterr(vp, "linux_getdents"); 635 error = EINVAL; 636 goto out; 637 } 638 idb.d_off = (linux_off_t)off; 639 idb.d_reclen = (u_short)linux_reclen; 640 } 641 strcpy(idb.d_name, bdp->d_name); 642 if ((error = copyout((caddr_t)&idb, outp, linux_reclen))) 643 goto out; 644 /* advance past this real entry */ 645 inp += reclen; 646 off = *cookie++; /* each entry points to itself */ 647 /* advance output past Linux-shaped entry */ 648 outp += linux_reclen; 649 resid -= linux_reclen; 650 if (oldcall) 651 break; 652 } 653 654 /* if we squished out the whole block, try again */ 655 if (outp == (caddr_t)SCARG(uap, dent)) 656 goto again; 657 fp->f_offset = off; /* update the vnode offset */ 658 659 if (oldcall) 660 nbytes = resid + linux_reclen; 661 662 eof: 663 *retval = nbytes - resid; 664 out: 665 VOP_UNLOCK(vp, 0); 666 if (cookiebuf) 667 free(cookiebuf, M_TEMP); 668 free(buf, M_TEMP); 669 return error; 670 } 671 672 /* 673 * Even when just using registers to pass arguments to syscalls you can 674 * have 5 of them on the i386. So this newer version of select() does 675 * this. 676 */ 677 int 678 linux_sys_select(p, v, retval) 679 struct proc *p; 680 void *v; 681 register_t *retval; 682 { 683 struct linux_sys_select_args /* { 684 syscallarg(int) nfds; 685 syscallarg(fd_set *) readfds; 686 syscallarg(fd_set *) writefds; 687 syscallarg(fd_set *) exceptfds; 688 syscallarg(struct timeval *) timeout; 689 } */ *uap = v; 690 691 return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds), 692 SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout)); 693 } 694 695 /* 696 * Common code for the old and new versions of select(). A couple of 697 * things are important: 698 * 1) return the amount of time left in the 'timeout' parameter 699 * 2) select never returns ERESTART on Linux, always return EINTR 700 */ 701 int 702 linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout) 703 struct proc *p; 704 register_t *retval; 705 int nfds; 706 fd_set *readfds, *writefds, *exceptfds; 707 struct timeval *timeout; 708 { 709 struct sys_select_args bsa; 710 struct timeval tv0, tv1, utv, *tvp; 711 caddr_t sg; 712 int error; 713 714 SCARG(&bsa, nd) = nfds; 715 SCARG(&bsa, in) = readfds; 716 SCARG(&bsa, ou) = writefds; 717 SCARG(&bsa, ex) = exceptfds; 718 SCARG(&bsa, tv) = timeout; 719 720 /* 721 * Store current time for computation of the amount of 722 * time left. 723 */ 724 if (timeout) { 725 if ((error = copyin(timeout, &utv, sizeof(utv)))) 726 return error; 727 if (itimerfix(&utv)) { 728 /* 729 * The timeval was invalid. Convert it to something 730 * valid that will act as it does under Linux. 731 */ 732 sg = stackgap_init(p->p_emul); 733 tvp = stackgap_alloc(&sg, sizeof(utv)); 734 utv.tv_sec += utv.tv_usec / 1000000; 735 utv.tv_usec %= 1000000; 736 if (utv.tv_usec < 0) { 737 utv.tv_sec -= 1; 738 utv.tv_usec += 1000000; 739 } 740 if (utv.tv_sec < 0) 741 timerclear(&utv); 742 if ((error = copyout(&utv, tvp, sizeof(utv)))) 743 return error; 744 SCARG(&bsa, tv) = tvp; 745 } 746 microtime(&tv0); 747 } 748 749 error = sys_select(p, &bsa, retval); 750 if (error) { 751 /* 752 * See fs/select.c in the Linux kernel. Without this, 753 * Maelstrom doesn't work. 754 */ 755 if (error == ERESTART) 756 error = EINTR; 757 return error; 758 } 759 760 if (timeout) { 761 if (*retval) { 762 /* 763 * Compute how much time was left of the timeout, 764 * by subtracting the current time and the time 765 * before we started the call, and subtracting 766 * that result from the user-supplied value. 767 */ 768 microtime(&tv1); 769 timersub(&tv1, &tv0, &tv1); 770 timersub(&utv, &tv1, &utv); 771 if (utv.tv_sec < 0) 772 timerclear(&utv); 773 } else 774 timerclear(&utv); 775 if ((error = copyout(&utv, timeout, sizeof(utv)))) 776 return error; 777 } 778 779 return 0; 780 } 781 782 /* 783 * Get the process group of a certain process. Look it up 784 * and return the value. 785 */ 786 int 787 linux_sys_getpgid(p, v, retval) 788 struct proc *p; 789 void *v; 790 register_t *retval; 791 { 792 struct linux_sys_getpgid_args /* { 793 syscallarg(int) pid; 794 } */ *uap = v; 795 struct proc *targp; 796 797 if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_pid) { 798 if ((targp = pfind(SCARG(uap, pid))) == 0) 799 return ESRCH; 800 } 801 else 802 targp = p; 803 804 retval[0] = targp->p_pgid; 805 return 0; 806 } 807 808 /* 809 * Set the 'personality' (emulation mode) for the current process. Only 810 * accept the Linux personality here (0). This call is needed because 811 * the Linux ELF crt0 issues it in an ugly kludge to make sure that 812 * ELF binaries run in Linux mode, not SVR4 mode. 813 */ 814 int 815 linux_sys_personality(p, v, retval) 816 struct proc *p; 817 void *v; 818 register_t *retval; 819 { 820 struct linux_sys_personality_args /* { 821 syscallarg(int) per; 822 } */ *uap = v; 823 824 if (SCARG(uap, per) != 0) 825 return EINVAL; 826 retval[0] = 0; 827 return 0; 828 } 829 830 /* 831 * The calls are here because of type conversions. 832 */ 833 int 834 linux_sys_setreuid(p, v, retval) 835 struct proc *p; 836 void *v; 837 register_t *retval; 838 { 839 struct linux_sys_setreuid_args /* { 840 syscallarg(int) ruid; 841 syscallarg(int) euid; 842 } */ *uap = v; 843 struct sys_setreuid_args bsa; 844 845 SCARG(&bsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ? 846 (uid_t)-1 : SCARG(uap, ruid); 847 SCARG(&bsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ? 848 (uid_t)-1 : SCARG(uap, euid); 849 850 return sys_setreuid(p, &bsa, retval); 851 } 852 853 int 854 linux_sys_setregid(p, v, retval) 855 struct proc *p; 856 void *v; 857 register_t *retval; 858 { 859 struct linux_sys_setregid_args /* { 860 syscallarg(int) rgid; 861 syscallarg(int) egid; 862 } */ *uap = v; 863 struct sys_setregid_args bsa; 864 865 SCARG(&bsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ? 866 (uid_t)-1 : SCARG(uap, rgid); 867 SCARG(&bsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ? 868 (uid_t)-1 : SCARG(uap, egid); 869 870 return sys_setregid(p, &bsa, retval); 871 } 872 873 int 874 linux_sys___sysctl(p, v, retval) 875 struct proc *p; 876 void *v; 877 register_t *retval; 878 { 879 struct linux_sys___sysctl_args /* { 880 syscallarg(struct linux___sysctl *) lsp; 881 } */ *uap = v; 882 struct linux___sysctl ls; 883 struct sys___sysctl_args bsa; 884 int error; 885 886 if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls))) 887 return error; 888 SCARG(&bsa, name) = ls.name; 889 SCARG(&bsa, namelen) = ls.namelen; 890 SCARG(&bsa, old) = ls.old; 891 SCARG(&bsa, oldlenp) = ls.oldlenp; 892 SCARG(&bsa, new) = ls.new; 893 SCARG(&bsa, newlen) = ls.newlen; 894 895 return sys___sysctl(p, &bsa, retval); 896 } 897