1 /*- 2 * Copyright (c) 2002 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include "opt_compat.h" 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/exec.h> 36 #include <sys/fcntl.h> 37 #include <sys/filedesc.h> 38 #include <sys/imgact.h> 39 #include <sys/kernel.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/file.h> /* Must come after sys/malloc.h */ 43 #include <sys/mman.h> 44 #include <sys/module.h> 45 #include <sys/mount.h> 46 #include <sys/mutex.h> 47 #include <sys/namei.h> 48 #include <sys/param.h> 49 #include <sys/proc.h> 50 #include <sys/reboot.h> 51 #include <sys/resource.h> 52 #include <sys/resourcevar.h> 53 #include <sys/selinfo.h> 54 #include <sys/pipe.h> /* Must come after sys/selinfo.h */ 55 #include <sys/signal.h> 56 #include <sys/signalvar.h> 57 #include <sys/socket.h> 58 #include <sys/socketvar.h> 59 #include <sys/stat.h> 60 #include <sys/syscallsubr.h> 61 #include <sys/sysctl.h> 62 #include <sys/sysent.h> 63 #include <sys/sysproto.h> 64 #include <sys/systm.h> 65 #include <sys/unistd.h> 66 #include <sys/user.h> 67 #include <sys/utsname.h> 68 #include <sys/vnode.h> 69 70 #include <vm/vm.h> 71 #include <vm/vm_kern.h> 72 #include <vm/vm_param.h> 73 #include <vm/pmap.h> 74 #include <vm/vm_map.h> 75 #include <vm/vm_object.h> 76 #include <vm/vm_extern.h> 77 78 #include <compat/freebsd32/freebsd32_util.h> 79 #include <compat/freebsd32/freebsd32.h> 80 #include <compat/freebsd32/freebsd32_proto.h> 81 82 /* 83 * [ taken from the linux emulator ] 84 * Search an alternate path before passing pathname arguments on 85 * to system calls. Useful for keeping a separate 'emulation tree'. 86 * 87 * If cflag is set, we check if an attempt can be made to create 88 * the named file, i.e. we check if the directory it should 89 * be in exists. 90 */ 91 int 92 freebsd32_emul_find(td, sgp, prefix, path, pbuf, cflag) 93 struct thread *td; 94 caddr_t *sgp; /* Pointer to stackgap memory */ 95 const char *prefix; 96 char *path; 97 char **pbuf; 98 int cflag; 99 { 100 int error; 101 size_t len, sz; 102 char *buf, *cp, *ptr; 103 struct ucred *ucred; 104 struct nameidata nd; 105 struct nameidata ndroot; 106 struct vattr vat; 107 struct vattr vatroot; 108 109 buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 110 *pbuf = path; 111 112 for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 113 continue; 114 115 sz = MAXPATHLEN - (ptr - buf); 116 117 /* 118 * If sgp is not given then the path is already in kernel space 119 */ 120 if (sgp == NULL) 121 error = copystr(path, ptr, sz, &len); 122 else 123 error = copyinstr(path, ptr, sz, &len); 124 125 if (error) { 126 free(buf, M_TEMP); 127 return error; 128 } 129 130 if (*ptr != '/') { 131 free(buf, M_TEMP); 132 return EINVAL; 133 } 134 135 /* 136 * We know that there is a / somewhere in this pathname. 137 * Search backwards for it, to find the file's parent dir 138 * to see if it exists in the alternate tree. If it does, 139 * and we want to create a file (cflag is set). We don't 140 * need to worry about the root comparison in this case. 141 */ 142 143 if (cflag) { 144 for (cp = &ptr[len] - 1; *cp != '/'; cp--) 145 ; 146 *cp = '\0'; 147 148 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 149 150 if ((error = namei(&nd)) != 0) { 151 free(buf, M_TEMP); 152 return error; 153 } 154 155 *cp = '/'; 156 } else { 157 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 158 159 if ((error = namei(&nd)) != 0) { 160 free(buf, M_TEMP); 161 return error; 162 } 163 164 /* 165 * We now compare the vnode of the freebsd32_root to the one 166 * vnode asked. If they resolve to be the same, then we 167 * ignore the match so that the real root gets used. 168 * This avoids the problem of traversing "../.." to find the 169 * root directory and never finding it, because "/" resolves 170 * to the emulation root directory. This is expensive :-( 171 */ 172 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, 173 freebsd32_emul_path, td); 174 175 if ((error = namei(&ndroot)) != 0) { 176 /* Cannot happen! */ 177 free(buf, M_TEMP); 178 vrele(nd.ni_vp); 179 return error; 180 } 181 182 ucred = td->td_ucred; 183 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) { 184 goto bad; 185 } 186 187 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred, 188 td)) != 0) { 189 goto bad; 190 } 191 192 if (vat.va_fsid == vatroot.va_fsid && 193 vat.va_fileid == vatroot.va_fileid) { 194 error = ENOENT; 195 goto bad; 196 } 197 198 } 199 if (sgp == NULL) 200 *pbuf = buf; 201 else { 202 sz = &ptr[len] - buf; 203 *pbuf = stackgap_alloc(sgp, sz + 1); 204 error = copyout(buf, *pbuf, sz); 205 free(buf, M_TEMP); 206 } 207 208 vrele(nd.ni_vp); 209 if (!cflag) 210 vrele(ndroot.ni_vp); 211 212 return error; 213 214 bad: 215 vrele(ndroot.ni_vp); 216 vrele(nd.ni_vp); 217 free(buf, M_TEMP); 218 return error; 219 } 220 221 int 222 freebsd32_open(struct thread *td, struct freebsd32_open_args *uap) 223 { 224 caddr_t sg; 225 226 sg = stackgap_init(); 227 CHECKALTEXIST(td, &sg, uap->path); 228 229 return open(td, (struct open_args *) uap); 230 } 231 232 int 233 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 234 { 235 int error; 236 caddr_t sg; 237 struct rusage32 *rusage32, ru32; 238 struct rusage *rusage = NULL, ru; 239 240 rusage32 = uap->rusage; 241 if (rusage32) { 242 sg = stackgap_init(); 243 rusage = stackgap_alloc(&sg, sizeof(struct rusage)); 244 uap->rusage = (struct rusage32 *)rusage; 245 } 246 error = wait4(td, (struct wait_args *)uap); 247 if (error) 248 return (error); 249 if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) { 250 TV_CP(ru, ru32, ru_utime); 251 TV_CP(ru, ru32, ru_stime); 252 CP(ru, ru32, ru_maxrss); 253 CP(ru, ru32, ru_ixrss); 254 CP(ru, ru32, ru_idrss); 255 CP(ru, ru32, ru_isrss); 256 CP(ru, ru32, ru_minflt); 257 CP(ru, ru32, ru_majflt); 258 CP(ru, ru32, ru_nswap); 259 CP(ru, ru32, ru_inblock); 260 CP(ru, ru32, ru_oublock); 261 CP(ru, ru32, ru_msgsnd); 262 CP(ru, ru32, ru_msgrcv); 263 CP(ru, ru32, ru_nsignals); 264 CP(ru, ru32, ru_nvcsw); 265 CP(ru, ru32, ru_nivcsw); 266 error = copyout(&ru32, rusage32, sizeof(ru32)); 267 } 268 return (error); 269 } 270 271 static void 272 copy_statfs(struct statfs *in, struct statfs32 *out) 273 { 274 CP(*in, *out, f_bsize); 275 CP(*in, *out, f_iosize); 276 CP(*in, *out, f_blocks); 277 CP(*in, *out, f_bfree); 278 CP(*in, *out, f_bavail); 279 CP(*in, *out, f_files); 280 CP(*in, *out, f_ffree); 281 CP(*in, *out, f_fsid); 282 CP(*in, *out, f_owner); 283 CP(*in, *out, f_type); 284 CP(*in, *out, f_flags); 285 CP(*in, *out, f_flags); 286 CP(*in, *out, f_syncwrites); 287 CP(*in, *out, f_asyncwrites); 288 bcopy(in->f_fstypename, 289 out->f_fstypename, MFSNAMELEN); 290 bcopy(in->f_mntonname, 291 out->f_mntonname, MNAMELEN); 292 CP(*in, *out, f_syncreads); 293 CP(*in, *out, f_asyncreads); 294 bcopy(in->f_mntfromname, 295 out->f_mntfromname, MNAMELEN); 296 } 297 298 int 299 freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap) 300 { 301 int error; 302 caddr_t sg; 303 struct statfs32 *sp32, stat32; 304 struct statfs *sp = NULL, stat; 305 int maxcount, count, i; 306 307 sp32 = uap->buf; 308 maxcount = uap->bufsize / sizeof(struct statfs32); 309 310 if (sp32) { 311 sg = stackgap_init(); 312 sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); 313 uap->buf = (struct statfs32 *)sp; 314 } 315 error = getfsstat(td, (struct getfsstat_args *) uap); 316 if (sp32 && !error) { 317 count = td->td_retval[0]; 318 for (i = 0; i < count; i++) { 319 error = copyin(&sp[i], &stat, sizeof(stat)); 320 if (error) 321 return (error); 322 copy_statfs(&stat, &stat32); 323 error = copyout(&stat32, &sp32[i], sizeof(stat32)); 324 if (error) 325 return (error); 326 } 327 } 328 return (error); 329 } 330 331 int 332 freebsd32_access(struct thread *td, struct freebsd32_access_args *uap) 333 { 334 caddr_t sg; 335 336 sg = stackgap_init(); 337 CHECKALTEXIST(td, &sg, uap->path); 338 339 return access(td, (struct access_args *)uap); 340 } 341 342 int 343 freebsd32_chflags(struct thread *td, struct freebsd32_chflags_args *uap) 344 { 345 caddr_t sg; 346 347 sg = stackgap_init(); 348 CHECKALTEXIST(td, &sg, uap->path); 349 350 return chflags(td, (struct chflags_args *)uap); 351 } 352 353 struct sigaltstack32 { 354 u_int32_t ss_sp; 355 u_int32_t ss_size; 356 int ss_flags; 357 }; 358 359 int 360 freebsd32_sigaltstack(struct thread *td, 361 struct freebsd32_sigaltstack_args *uap) 362 { 363 struct sigaltstack32 s32; 364 struct sigaltstack ss, oss, *ssp; 365 int error; 366 367 if (uap->ss != NULL) { 368 error = copyin(uap->ss, &s32, sizeof(s32)); 369 if (error) 370 return (error); 371 PTRIN_CP(s32, ss, ss_sp); 372 CP(s32, ss, ss_size); 373 CP(s32, ss, ss_flags); 374 ssp = &ss; 375 } else 376 ssp = NULL; 377 error = kern_sigaltstack(td, ssp, &oss); 378 if (error == 0 && uap->oss != NULL) { 379 PTROUT_CP(oss, s32, ss_sp); 380 CP(oss, s32, ss_size); 381 CP(oss, s32, ss_flags); 382 error = copyout(&s32, uap->oss, sizeof(s32)); 383 } 384 return (error); 385 } 386 387 int 388 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 389 { 390 int error; 391 caddr_t sg; 392 struct execve_args ap; 393 u_int32_t *p32, arg; 394 char **p; 395 int count; 396 397 sg = stackgap_init(); 398 CHECKALTEXIST(td, &sg, uap->fname); 399 ap.fname = uap->fname; 400 401 if (uap->argv) { 402 count = 0; 403 p32 = uap->argv; 404 do { 405 error = copyin(p32++, &arg, sizeof(arg)); 406 if (error) 407 return error; 408 count++; 409 } while (arg != 0); 410 p = stackgap_alloc(&sg, count * sizeof(char *)); 411 ap.argv = p; 412 p32 = uap->argv; 413 do { 414 error = copyin(p32++, &arg, sizeof(arg)); 415 if (error) 416 return error; 417 *p++ = PTRIN(arg); 418 } while (arg != 0); 419 } 420 if (uap->envv) { 421 count = 0; 422 p32 = uap->envv; 423 do { 424 error = copyin(p32++, &arg, sizeof(arg)); 425 if (error) 426 return error; 427 count++; 428 } while (arg != 0); 429 p = stackgap_alloc(&sg, count * sizeof(char *)); 430 ap.envv = p; 431 p32 = uap->envv; 432 do { 433 error = copyin(p32++, &arg, sizeof(arg)); 434 if (error) 435 return error; 436 *p++ = PTRIN(arg); 437 } while (arg != 0); 438 } 439 440 return execve(td, &ap); 441 } 442 443 #ifdef __ia64__ 444 static int 445 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 446 int prot, int fd, off_t pos) 447 { 448 vm_map_t map; 449 vm_map_entry_t entry; 450 int rv; 451 452 map = &td->td_proc->p_vmspace->vm_map; 453 if (fd != -1) 454 prot |= VM_PROT_WRITE; 455 456 if (vm_map_lookup_entry(map, start, &entry)) { 457 if ((entry->protection & prot) != prot) { 458 rv = vm_map_protect(map, 459 trunc_page(start), 460 round_page(end), 461 entry->protection | prot, 462 FALSE); 463 if (rv != KERN_SUCCESS) 464 return (EINVAL); 465 } 466 } else { 467 vm_offset_t addr = trunc_page(start); 468 rv = vm_map_find(map, 0, 0, 469 &addr, PAGE_SIZE, FALSE, prot, 470 VM_PROT_ALL, 0); 471 if (rv != KERN_SUCCESS) 472 return (EINVAL); 473 } 474 475 if (fd != -1) { 476 struct pread_args r; 477 r.fd = fd; 478 r.buf = (void *) start; 479 r.nbyte = end - start; 480 r.offset = pos; 481 return (pread(td, &r)); 482 } else { 483 while (start < end) { 484 subyte((void *) start, 0); 485 start++; 486 } 487 return (0); 488 } 489 } 490 #endif 491 492 int 493 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 494 { 495 struct mmap_args ap; 496 vm_offset_t addr = (vm_offset_t) uap->addr; 497 vm_size_t len = uap->len; 498 int prot = uap->prot; 499 int flags = uap->flags; 500 int fd = uap->fd; 501 off_t pos = (uap->poslo 502 | ((off_t)uap->poshi << 32)); 503 #ifdef __ia64__ 504 vm_size_t pageoff; 505 int error; 506 507 /* 508 * Attempt to handle page size hassles. 509 */ 510 pageoff = (pos & PAGE_MASK); 511 if (flags & MAP_FIXED) { 512 vm_offset_t start, end; 513 start = addr; 514 end = addr + len; 515 516 if (start != trunc_page(start)) { 517 error = freebsd32_mmap_partial(td, start, 518 round_page(start), prot, 519 fd, pos); 520 if (fd != -1) 521 pos += round_page(start) - start; 522 start = round_page(start); 523 } 524 if (end != round_page(end)) { 525 vm_offset_t t = trunc_page(end); 526 error = freebsd32_mmap_partial(td, t, end, 527 prot, fd, 528 pos + t - start); 529 end = trunc_page(end); 530 } 531 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 532 /* 533 * We can't map this region at all. The specified 534 * address doesn't have the same alignment as the file 535 * position. Fake the mapping by simply reading the 536 * entire region into memory. First we need to make 537 * sure the region exists. 538 */ 539 vm_map_t map; 540 struct pread_args r; 541 int rv; 542 543 prot |= VM_PROT_WRITE; 544 map = &td->td_proc->p_vmspace->vm_map; 545 rv = vm_map_remove(map, start, end); 546 if (rv != KERN_SUCCESS) 547 return (EINVAL); 548 rv = vm_map_find(map, 0, 0, 549 &start, end - start, FALSE, 550 prot, VM_PROT_ALL, 0); 551 if (rv != KERN_SUCCESS) 552 return (EINVAL); 553 r.fd = fd; 554 r.buf = (void *) start; 555 r.nbyte = end - start; 556 r.offset = pos; 557 error = pread(td, &r); 558 if (error) 559 return (error); 560 561 td->td_retval[0] = addr; 562 return (0); 563 } 564 if (end == start) { 565 /* 566 * After dealing with the ragged ends, there 567 * might be none left. 568 */ 569 td->td_retval[0] = addr; 570 return (0); 571 } 572 addr = start; 573 len = end - start; 574 } 575 #endif 576 577 ap.addr = (void *) addr; 578 ap.len = len; 579 ap.prot = prot; 580 ap.flags = flags; 581 ap.fd = fd; 582 ap.pos = pos; 583 584 return (mmap(td, &ap)); 585 } 586 587 struct itimerval32 { 588 struct timeval32 it_interval; 589 struct timeval32 it_value; 590 }; 591 592 int 593 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 594 { 595 int error; 596 caddr_t sg; 597 struct itimerval32 *p32, *op32, s32; 598 struct itimerval *p = NULL, *op = NULL, s; 599 600 p32 = uap->itv; 601 if (p32) { 602 sg = stackgap_init(); 603 p = stackgap_alloc(&sg, sizeof(struct itimerval)); 604 uap->itv = (struct itimerval32 *)p; 605 error = copyin(p32, &s32, sizeof(s32)); 606 if (error) 607 return (error); 608 TV_CP(s32, s, it_interval); 609 TV_CP(s32, s, it_value); 610 error = copyout(&s, p, sizeof(s)); 611 if (error) 612 return (error); 613 } 614 op32 = uap->oitv; 615 if (op32) { 616 sg = stackgap_init(); 617 op = stackgap_alloc(&sg, sizeof(struct itimerval)); 618 uap->oitv = (struct itimerval32 *)op; 619 } 620 error = setitimer(td, (struct setitimer_args *) uap); 621 if (error) 622 return (error); 623 if (op32) { 624 error = copyin(op, &s, sizeof(s)); 625 if (error) 626 return (error); 627 TV_CP(s, s32, it_interval); 628 TV_CP(s, s32, it_value); 629 error = copyout(&s32, op32, sizeof(s32)); 630 } 631 return (error); 632 } 633 634 int 635 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 636 { 637 int error; 638 caddr_t sg; 639 struct timeval32 *p32, s32; 640 struct timeval *p = NULL, s; 641 642 p32 = uap->tv; 643 if (p32) { 644 sg = stackgap_init(); 645 p = stackgap_alloc(&sg, sizeof(struct timeval)); 646 uap->tv = (struct timeval32 *)p; 647 error = copyin(p32, &s32, sizeof(s32)); 648 if (error) 649 return (error); 650 CP(s32, s, tv_sec); 651 CP(s32, s, tv_usec); 652 error = copyout(&s, p, sizeof(s)); 653 if (error) 654 return (error); 655 } 656 /* 657 * XXX big-endian needs to convert the fd_sets too. 658 */ 659 return (select(td, (struct select_args *) uap)); 660 } 661 662 struct kevent32 { 663 u_int32_t ident; /* identifier for this event */ 664 short filter; /* filter for event */ 665 u_short flags; 666 u_int fflags; 667 int32_t data; 668 u_int32_t udata; /* opaque user data identifier */ 669 }; 670 671 int 672 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 673 { 674 int error; 675 caddr_t sg; 676 struct timespec32 ts32; 677 struct timespec ts; 678 struct kevent32 ks32; 679 struct kevent *ks; 680 struct kevent_args a; 681 int i; 682 683 sg = stackgap_init(); 684 685 a.fd = uap->fd; 686 a.changelist = uap->changelist; 687 a.nchanges = uap->nchanges; 688 a.eventlist = uap->eventlist; 689 a.nevents = uap->nevents; 690 a.timeout = NULL; 691 692 if (uap->timeout) { 693 a.timeout = stackgap_alloc(&sg, sizeof(struct timespec)); 694 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 695 if (error) 696 return (error); 697 CP(ts32, ts, tv_sec); 698 CP(ts32, ts, tv_nsec); 699 error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts)); 700 if (error) 701 return (error); 702 } 703 if (uap->changelist) { 704 a.changelist = (struct kevent *)stackgap_alloc(&sg, 705 uap->nchanges * sizeof(struct kevent)); 706 for (i = 0; i < uap->nchanges; i++) { 707 error = copyin(&uap->changelist[i], &ks32, 708 sizeof(ks32)); 709 if (error) 710 return (error); 711 ks = (struct kevent *)(uintptr_t)&a.changelist[i]; 712 CP(ks32, *ks, ident); 713 CP(ks32, *ks, filter); 714 CP(ks32, *ks, flags); 715 CP(ks32, *ks, fflags); 716 CP(ks32, *ks, data); 717 PTRIN_CP(ks32, *ks, udata); 718 } 719 } 720 if (uap->eventlist) { 721 a.eventlist = stackgap_alloc(&sg, 722 uap->nevents * sizeof(struct kevent)); 723 } 724 error = kevent(td, &a); 725 if (uap->eventlist && error > 0) { 726 for (i = 0; i < error; i++) { 727 ks = &a.eventlist[i]; 728 CP(*ks, ks32, ident); 729 CP(*ks, ks32, filter); 730 CP(*ks, ks32, flags); 731 CP(*ks, ks32, fflags); 732 CP(*ks, ks32, data); 733 PTROUT_CP(*ks, ks32, udata); 734 error = copyout(&ks32, &uap->eventlist[i], 735 sizeof(ks32)); 736 if (error) 737 return (error); 738 } 739 } 740 return error; 741 } 742 743 int 744 freebsd32_gettimeofday(struct thread *td, 745 struct freebsd32_gettimeofday_args *uap) 746 { 747 int error; 748 caddr_t sg; 749 struct timeval32 *p32, s32; 750 struct timeval *p = NULL, s; 751 752 p32 = uap->tp; 753 if (p32) { 754 sg = stackgap_init(); 755 p = stackgap_alloc(&sg, sizeof(struct timeval)); 756 uap->tp = (struct timeval32 *)p; 757 } 758 error = gettimeofday(td, (struct gettimeofday_args *) uap); 759 if (error) 760 return (error); 761 if (p32) { 762 error = copyin(p, &s, sizeof(s)); 763 if (error) 764 return (error); 765 CP(s, s32, tv_sec); 766 CP(s, s32, tv_usec); 767 error = copyout(&s32, p32, sizeof(s32)); 768 if (error) 769 return (error); 770 } 771 return (error); 772 } 773 774 int 775 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 776 { 777 int error; 778 caddr_t sg; 779 struct rusage32 *p32, s32; 780 struct rusage *p = NULL, s; 781 782 p32 = uap->rusage; 783 if (p32) { 784 sg = stackgap_init(); 785 p = stackgap_alloc(&sg, sizeof(struct rusage)); 786 uap->rusage = (struct rusage32 *)p; 787 } 788 error = getrusage(td, (struct getrusage_args *) uap); 789 if (error) 790 return (error); 791 if (p32) { 792 error = copyin(p, &s, sizeof(s)); 793 if (error) 794 return (error); 795 TV_CP(s, s32, ru_utime); 796 TV_CP(s, s32, ru_stime); 797 CP(s, s32, ru_maxrss); 798 CP(s, s32, ru_ixrss); 799 CP(s, s32, ru_idrss); 800 CP(s, s32, ru_isrss); 801 CP(s, s32, ru_minflt); 802 CP(s, s32, ru_majflt); 803 CP(s, s32, ru_nswap); 804 CP(s, s32, ru_inblock); 805 CP(s, s32, ru_oublock); 806 CP(s, s32, ru_msgsnd); 807 CP(s, s32, ru_msgrcv); 808 CP(s, s32, ru_nsignals); 809 CP(s, s32, ru_nvcsw); 810 CP(s, s32, ru_nivcsw); 811 error = copyout(&s32, p32, sizeof(s32)); 812 } 813 return (error); 814 } 815 816 struct iovec32 { 817 u_int32_t iov_base; 818 int iov_len; 819 }; 820 #define STACKGAPLEN 400 821 822 int 823 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 824 { 825 int error, osize, nsize, i; 826 caddr_t sg; 827 struct readv_args /* { 828 syscallarg(int) fd; 829 syscallarg(struct iovec *) iovp; 830 syscallarg(u_int) iovcnt; 831 } */ a; 832 struct iovec32 *oio; 833 struct iovec *nio; 834 835 sg = stackgap_init(); 836 837 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 838 return (EINVAL); 839 840 osize = uap->iovcnt * sizeof (struct iovec32); 841 nsize = uap->iovcnt * sizeof (struct iovec); 842 843 oio = malloc(osize, M_TEMP, M_WAITOK); 844 nio = malloc(nsize, M_TEMP, M_WAITOK); 845 846 error = 0; 847 if ((error = copyin(uap->iovp, oio, osize))) 848 goto punt; 849 for (i = 0; i < uap->iovcnt; i++) { 850 nio[i].iov_base = PTRIN(oio[i].iov_base); 851 nio[i].iov_len = oio[i].iov_len; 852 } 853 854 a.fd = uap->fd; 855 a.iovp = stackgap_alloc(&sg, nsize); 856 a.iovcnt = uap->iovcnt; 857 858 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 859 goto punt; 860 error = readv(td, &a); 861 862 punt: 863 free(oio, M_TEMP); 864 free(nio, M_TEMP); 865 return (error); 866 } 867 868 int 869 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 870 { 871 int error, i, nsize, osize; 872 caddr_t sg; 873 struct writev_args /* { 874 syscallarg(int) fd; 875 syscallarg(struct iovec *) iovp; 876 syscallarg(u_int) iovcnt; 877 } */ a; 878 struct iovec32 *oio; 879 struct iovec *nio; 880 881 sg = stackgap_init(); 882 883 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 884 return (EINVAL); 885 886 osize = uap->iovcnt * sizeof (struct iovec32); 887 nsize = uap->iovcnt * sizeof (struct iovec); 888 889 oio = malloc(osize, M_TEMP, M_WAITOK); 890 nio = malloc(nsize, M_TEMP, M_WAITOK); 891 892 error = 0; 893 if ((error = copyin(uap->iovp, oio, osize))) 894 goto punt; 895 for (i = 0; i < uap->iovcnt; i++) { 896 nio[i].iov_base = PTRIN(oio[i].iov_base); 897 nio[i].iov_len = oio[i].iov_len; 898 } 899 900 a.fd = uap->fd; 901 a.iovp = stackgap_alloc(&sg, nsize); 902 a.iovcnt = uap->iovcnt; 903 904 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 905 goto punt; 906 error = writev(td, &a); 907 908 punt: 909 free(oio, M_TEMP); 910 free(nio, M_TEMP); 911 return (error); 912 } 913 914 int 915 freebsd32_settimeofday(struct thread *td, 916 struct freebsd32_settimeofday_args *uap) 917 { 918 int error; 919 caddr_t sg; 920 struct timeval32 *p32, s32; 921 struct timeval *p = NULL, s; 922 923 p32 = uap->tv; 924 if (p32) { 925 sg = stackgap_init(); 926 p = stackgap_alloc(&sg, sizeof(struct timeval)); 927 uap->tv = (struct timeval32 *)p; 928 error = copyin(p32, &s32, sizeof(s32)); 929 if (error) 930 return (error); 931 CP(s32, s, tv_sec); 932 CP(s32, s, tv_usec); 933 error = copyout(&s, p, sizeof(s)); 934 if (error) 935 return (error); 936 } 937 return (settimeofday(td, (struct settimeofday_args *) uap)); 938 } 939 940 int 941 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 942 { 943 int error; 944 caddr_t sg; 945 struct timeval32 *p32, s32[2]; 946 struct timeval *p = NULL, s[2]; 947 948 p32 = uap->tptr; 949 if (p32) { 950 sg = stackgap_init(); 951 p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); 952 uap->tptr = (struct timeval32 *)p; 953 error = copyin(p32, s32, sizeof(s32)); 954 if (error) 955 return (error); 956 CP(s32[0], s[0], tv_sec); 957 CP(s32[0], s[0], tv_usec); 958 CP(s32[1], s[1], tv_sec); 959 CP(s32[1], s[1], tv_usec); 960 error = copyout(s, p, sizeof(s)); 961 if (error) 962 return (error); 963 } 964 return (utimes(td, (struct utimes_args *) uap)); 965 } 966 967 int 968 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 969 { 970 int error; 971 caddr_t sg; 972 struct timeval32 *p32, *op32, s32; 973 struct timeval *p = NULL, *op = NULL, s; 974 975 p32 = uap->delta; 976 if (p32) { 977 sg = stackgap_init(); 978 p = stackgap_alloc(&sg, sizeof(struct timeval)); 979 uap->delta = (struct timeval32 *)p; 980 error = copyin(p32, &s32, sizeof(s32)); 981 if (error) 982 return (error); 983 CP(s32, s, tv_sec); 984 CP(s32, s, tv_usec); 985 error = copyout(&s, p, sizeof(s)); 986 if (error) 987 return (error); 988 } 989 op32 = uap->olddelta; 990 if (op32) { 991 sg = stackgap_init(); 992 op = stackgap_alloc(&sg, sizeof(struct timeval)); 993 uap->olddelta = (struct timeval32 *)op; 994 } 995 error = utimes(td, (struct utimes_args *) uap); 996 if (error) 997 return error; 998 if (op32) { 999 error = copyin(op, &s, sizeof(s)); 1000 if (error) 1001 return (error); 1002 CP(s, s32, tv_sec); 1003 CP(s, s32, tv_usec); 1004 error = copyout(&s32, op32, sizeof(s32)); 1005 } 1006 return (error); 1007 } 1008 1009 int 1010 freebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap) 1011 { 1012 int error; 1013 caddr_t sg; 1014 struct statfs32 *p32, s32; 1015 struct statfs *p = NULL, s; 1016 1017 p32 = uap->buf; 1018 if (p32) { 1019 sg = stackgap_init(); 1020 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1021 uap->buf = (struct statfs32 *)p; 1022 } 1023 error = statfs(td, (struct statfs_args *) uap); 1024 if (error) 1025 return (error); 1026 if (p32) { 1027 error = copyin(p, &s, sizeof(s)); 1028 if (error) 1029 return (error); 1030 copy_statfs(&s, &s32); 1031 error = copyout(&s32, p32, sizeof(s32)); 1032 } 1033 return (error); 1034 } 1035 1036 int 1037 freebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap) 1038 { 1039 int error; 1040 caddr_t sg; 1041 struct statfs32 *p32, s32; 1042 struct statfs *p = NULL, s; 1043 1044 p32 = uap->buf; 1045 if (p32) { 1046 sg = stackgap_init(); 1047 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1048 uap->buf = (struct statfs32 *)p; 1049 } 1050 error = fstatfs(td, (struct fstatfs_args *) uap); 1051 if (error) 1052 return (error); 1053 if (p32) { 1054 error = copyin(p, &s, sizeof(s)); 1055 if (error) 1056 return (error); 1057 copy_statfs(&s, &s32); 1058 error = copyout(&s32, p32, sizeof(s32)); 1059 } 1060 return (error); 1061 } 1062 1063 int 1064 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1065 { 1066 /* 1067 * Vector through to semsys if it is loaded. 1068 */ 1069 return sysent[169].sy_call(td, uap); 1070 } 1071 1072 int 1073 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1074 { 1075 /* 1076 * Vector through to msgsys if it is loaded. 1077 */ 1078 return sysent[170].sy_call(td, uap); 1079 } 1080 1081 int 1082 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1083 { 1084 /* 1085 * Vector through to shmsys if it is loaded. 1086 */ 1087 return sysent[171].sy_call(td, uap); 1088 } 1089 1090 int 1091 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1092 { 1093 struct pread_args ap; 1094 1095 ap.fd = uap->fd; 1096 ap.buf = uap->buf; 1097 ap.nbyte = uap->nbyte; 1098 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1099 return (pread(td, &ap)); 1100 } 1101 1102 int 1103 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1104 { 1105 struct pwrite_args ap; 1106 1107 ap.fd = uap->fd; 1108 ap.buf = uap->buf; 1109 ap.nbyte = uap->nbyte; 1110 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1111 return (pwrite(td, &ap)); 1112 } 1113 1114 int 1115 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1116 { 1117 int error; 1118 struct lseek_args ap; 1119 off_t pos; 1120 1121 ap.fd = uap->fd; 1122 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1123 ap.whence = uap->whence; 1124 error = lseek(td, &ap); 1125 /* Expand the quad return into two parts for eax and edx */ 1126 pos = *(off_t *)(td->td_retval); 1127 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1128 td->td_retval[1] = pos >> 32; /* %edx */ 1129 return error; 1130 } 1131 1132 int 1133 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1134 { 1135 struct truncate_args ap; 1136 1137 ap.path = uap->path; 1138 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1139 return (truncate(td, &ap)); 1140 } 1141 1142 int 1143 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1144 { 1145 struct ftruncate_args ap; 1146 1147 ap.fd = uap->fd; 1148 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1149 return (ftruncate(td, &ap)); 1150 } 1151 1152 #ifdef COMPAT_FREEBSD4 1153 int 1154 freebsd4_freebsd32_sendfile(struct thread *td, 1155 struct freebsd4_freebsd32_sendfile_args *uap) 1156 { 1157 struct freebsd4_sendfile_args ap; 1158 1159 ap.fd = uap->fd; 1160 ap.s = uap->s; 1161 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1162 ap.nbytes = uap->nbytes; /* XXX check */ 1163 ap.hdtr = uap->hdtr; /* XXX check */ 1164 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1165 ap.flags = uap->flags; 1166 return (freebsd4_sendfile(td, &ap)); 1167 } 1168 #endif 1169 1170 int 1171 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1172 { 1173 struct sendfile_args ap; 1174 1175 ap.fd = uap->fd; 1176 ap.s = uap->s; 1177 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1178 ap.nbytes = uap->nbytes; /* XXX check */ 1179 ap.hdtr = uap->hdtr; /* XXX check */ 1180 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1181 ap.flags = uap->flags; 1182 return (sendfile(td, &ap)); 1183 } 1184 1185 struct stat32 { 1186 udev_t st_dev; 1187 ino_t st_ino; 1188 mode_t st_mode; 1189 nlink_t st_nlink; 1190 uid_t st_uid; 1191 gid_t st_gid; 1192 udev_t st_rdev; 1193 struct timespec32 st_atimespec; 1194 struct timespec32 st_mtimespec; 1195 struct timespec32 st_ctimespec; 1196 off_t st_size; 1197 int64_t st_blocks; 1198 u_int32_t st_blksize; 1199 u_int32_t st_flags; 1200 u_int32_t st_gen; 1201 }; 1202 1203 static void 1204 copy_stat( struct stat *in, struct stat32 *out) 1205 { 1206 CP(*in, *out, st_dev); 1207 CP(*in, *out, st_ino); 1208 CP(*in, *out, st_mode); 1209 CP(*in, *out, st_nlink); 1210 CP(*in, *out, st_uid); 1211 CP(*in, *out, st_gid); 1212 CP(*in, *out, st_rdev); 1213 TS_CP(*in, *out, st_atimespec); 1214 TS_CP(*in, *out, st_mtimespec); 1215 TS_CP(*in, *out, st_ctimespec); 1216 CP(*in, *out, st_size); 1217 CP(*in, *out, st_blocks); 1218 CP(*in, *out, st_blksize); 1219 CP(*in, *out, st_flags); 1220 CP(*in, *out, st_gen); 1221 } 1222 1223 int 1224 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1225 { 1226 int error; 1227 caddr_t sg; 1228 struct stat32 *p32, s32; 1229 struct stat *p = NULL, s; 1230 1231 p32 = uap->ub; 1232 if (p32) { 1233 sg = stackgap_init(); 1234 p = stackgap_alloc(&sg, sizeof(struct stat)); 1235 uap->ub = (struct stat32 *)p; 1236 } 1237 error = stat(td, (struct stat_args *) uap); 1238 if (error) 1239 return (error); 1240 if (p32) { 1241 error = copyin(p, &s, sizeof(s)); 1242 if (error) 1243 return (error); 1244 copy_stat(&s, &s32); 1245 error = copyout(&s32, p32, sizeof(s32)); 1246 } 1247 return (error); 1248 } 1249 1250 int 1251 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1252 { 1253 int error; 1254 caddr_t sg; 1255 struct stat32 *p32, s32; 1256 struct stat *p = NULL, s; 1257 1258 p32 = uap->ub; 1259 if (p32) { 1260 sg = stackgap_init(); 1261 p = stackgap_alloc(&sg, sizeof(struct stat)); 1262 uap->ub = (struct stat32 *)p; 1263 } 1264 error = fstat(td, (struct fstat_args *) uap); 1265 if (error) 1266 return (error); 1267 if (p32) { 1268 error = copyin(p, &s, sizeof(s)); 1269 if (error) 1270 return (error); 1271 copy_stat(&s, &s32); 1272 error = copyout(&s32, p32, sizeof(s32)); 1273 } 1274 return (error); 1275 } 1276 1277 int 1278 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1279 { 1280 int error; 1281 caddr_t sg; 1282 struct stat32 *p32, s32; 1283 struct stat *p = NULL, s; 1284 1285 p32 = uap->ub; 1286 if (p32) { 1287 sg = stackgap_init(); 1288 p = stackgap_alloc(&sg, sizeof(struct stat)); 1289 uap->ub = (struct stat32 *)p; 1290 } 1291 error = lstat(td, (struct lstat_args *) uap); 1292 if (error) 1293 return (error); 1294 if (p32) { 1295 error = copyin(p, &s, sizeof(s)); 1296 if (error) 1297 return (error); 1298 copy_stat(&s, &s32); 1299 error = copyout(&s32, p32, sizeof(s32)); 1300 } 1301 return (error); 1302 } 1303 1304 /* 1305 * MPSAFE 1306 */ 1307 int 1308 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1309 { 1310 int error, name[CTL_MAXNAME]; 1311 size_t j, oldlen; 1312 1313 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1314 return (EINVAL); 1315 1316 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 1317 if (error) 1318 return (error); 1319 1320 mtx_lock(&Giant); 1321 1322 if (uap->oldlenp) 1323 oldlen = fuword32(uap->oldlenp); 1324 else 1325 oldlen = 0; 1326 error = userland_sysctl(td, name, uap->namelen, 1327 uap->old, &oldlen, 1, 1328 uap->new, uap->newlen, &j); 1329 if (error && error != ENOMEM) 1330 goto done2; 1331 if (uap->oldlenp) { 1332 suword32(uap->oldlenp, j); 1333 } 1334 done2: 1335 mtx_unlock(&Giant); 1336 return (error); 1337 } 1338 1339 struct sigaction32 { 1340 u_int32_t sa_u; 1341 int sa_flags; 1342 sigset_t sa_mask; 1343 }; 1344 1345 int 1346 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1347 { 1348 struct sigaction32 s32; 1349 struct sigaction sa, osa, *sap; 1350 int error; 1351 1352 if (uap->act) { 1353 error = copyin(uap->act, &s32, sizeof(s32)); 1354 if (error) 1355 return (error); 1356 sa.sa_handler = PTRIN(s32.sa_u); 1357 CP(s32, sa, sa_flags); 1358 CP(s32, sa, sa_mask); 1359 sap = &sa; 1360 } else 1361 sap = NULL; 1362 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1363 if (error != 0 && uap->oact != NULL) { 1364 s32.sa_u = PTROUT(osa.sa_handler); 1365 CP(osa, s32, sa_flags); 1366 CP(osa, s32, sa_mask); 1367 error = copyout(&s32, uap->oact, sizeof(s32)); 1368 } 1369 return (error); 1370 } 1371 1372 #ifdef COMPAT_FREEBSD4 1373 int 1374 freebsd4_freebsd32_sigaction(struct thread *td, 1375 struct freebsd4_freebsd32_sigaction_args *uap) 1376 { 1377 struct sigaction32 s32; 1378 struct sigaction sa, osa, *sap; 1379 int error; 1380 1381 if (uap->act) { 1382 error = copyin(uap->act, &s32, sizeof(s32)); 1383 if (error) 1384 return (error); 1385 sa.sa_handler = PTRIN(s32.sa_u); 1386 CP(s32, sa, sa_flags); 1387 CP(s32, sa, sa_mask); 1388 sap = &sa; 1389 } else 1390 sap = NULL; 1391 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1392 if (error != 0 && uap->oact != NULL) { 1393 s32.sa_u = PTROUT(osa.sa_handler); 1394 CP(osa, s32, sa_flags); 1395 CP(osa, s32, sa_mask); 1396 error = copyout(&s32, uap->oact, sizeof(s32)); 1397 } 1398 return (error); 1399 } 1400 #endif 1401 1402 #if 0 1403 1404 int 1405 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 1406 { 1407 int error; 1408 caddr_t sg; 1409 struct yyy32 *p32, s32; 1410 struct yyy *p = NULL, s; 1411 1412 p32 = uap->zzz; 1413 if (p32) { 1414 sg = stackgap_init(); 1415 p = stackgap_alloc(&sg, sizeof(struct yyy)); 1416 uap->zzz = (struct yyy32 *)p; 1417 error = copyin(p32, &s32, sizeof(s32)); 1418 if (error) 1419 return (error); 1420 /* translate in */ 1421 error = copyout(&s, p, sizeof(s)); 1422 if (error) 1423 return (error); 1424 } 1425 error = xxx(td, (struct xxx_args *) uap); 1426 if (error) 1427 return (error); 1428 if (p32) { 1429 error = copyin(p, &s, sizeof(s)); 1430 if (error) 1431 return (error); 1432 /* translate out */ 1433 error = copyout(&s32, p32, sizeof(s32)); 1434 } 1435 return (error); 1436 } 1437 1438 #endif 1439