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