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