freebsd32_misc.c revision 114987
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 * $FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 114987 2003-05-14 04:10:49Z peter $ 27 */ 28 29#include "opt_compat.h" 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/bus.h> 34#include <sys/exec.h> 35#include <sys/fcntl.h> 36#include <sys/filedesc.h> 37#include <sys/imgact.h> 38#include <sys/kernel.h> 39#include <sys/lock.h> 40#include <sys/malloc.h> 41#include <sys/file.h> /* Must come after sys/malloc.h */ 42#include <sys/mman.h> 43#include <sys/module.h> 44#include <sys/mount.h> 45#include <sys/mutex.h> 46#include <sys/namei.h> 47#include <sys/param.h> 48#include <sys/proc.h> 49#include <sys/reboot.h> 50#include <sys/resource.h> 51#include <sys/resourcevar.h> 52#include <sys/selinfo.h> 53#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 54#include <sys/signal.h> 55#include <sys/signalvar.h> 56#include <sys/socket.h> 57#include <sys/socketvar.h> 58#include <sys/stat.h> 59#include <sys/syscallsubr.h> 60#include <sys/sysctl.h> 61#include <sys/sysent.h> 62#include <sys/sysproto.h> 63#include <sys/systm.h> 64#include <sys/unistd.h> 65#include <sys/user.h> 66#include <sys/utsname.h> 67#include <sys/vnode.h> 68 69#include <vm/vm.h> 70#include <vm/vm_kern.h> 71#include <vm/vm_param.h> 72#include <vm/pmap.h> 73#include <vm/vm_map.h> 74#include <vm/vm_object.h> 75#include <vm/vm_extern.h> 76 77#include <amd64/ia32/ia32_util.h> 78#include <amd64/ia32/ia32.h> 79#include <amd64/ia32/ia32_proto.h> 80 81static const char ia32_emul_path[] = "/compat/ia32"; 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 */ 91int 92ia32_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 ia32_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, ia32_emul_path, 173 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 214bad: 215 vrele(ndroot.ni_vp); 216 vrele(nd.ni_vp); 217 free(buf, M_TEMP); 218 return error; 219} 220 221int 222ia32_open(struct thread *td, struct ia32_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 232int 233ia32_wait4(struct thread *td, struct ia32_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 271static void 272copy_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 298int 299ia32_getfsstat(struct thread *td, struct ia32_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 331int 332ia32_access(struct thread *td, struct ia32_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 342int 343ia32_chflags(struct thread *td, struct ia32_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 353struct sigaltstack32 { 354 u_int32_t ss_sp; 355 u_int32_t ss_size; 356 int ss_flags; 357}; 358 359int 360ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap) 361{ 362 struct sigaltstack32 s32; 363 struct sigaltstack ss, oss, *ssp; 364 int error; 365 366 if (uap->ss != NULL) { 367 error = copyin(uap->ss, &s32, sizeof(s32)); 368 if (error) 369 return (error); 370 PTRIN_CP(s32, ss, ss_sp); 371 CP(s32, ss, ss_size); 372 CP(s32, ss, ss_flags); 373 ssp = &ss; 374 } else 375 ssp = NULL; 376 error = kern_sigaltstack(td, ssp, &oss); 377 if (error == 0 && uap->oss != NULL) { 378 PTROUT_CP(oss, s32, ss_sp); 379 CP(oss, s32, ss_size); 380 CP(oss, s32, ss_flags); 381 error = copyout(&s32, uap->oss, sizeof(s32)); 382 } 383 return (error); 384} 385 386int 387ia32_execve(struct thread *td, struct ia32_execve_args *uap) 388{ 389 int error; 390 caddr_t sg; 391 struct execve_args ap; 392 u_int32_t *p32, arg; 393 char **p; 394 int count; 395 396 sg = stackgap_init(); 397 CHECKALTEXIST(td, &sg, uap->fname); 398 ap.fname = uap->fname; 399 400 if (uap->argv) { 401 count = 0; 402 p32 = uap->argv; 403 do { 404 error = copyin(p32++, &arg, sizeof(arg)); 405 if (error) 406 return error; 407 count++; 408 } while (arg != 0); 409 p = stackgap_alloc(&sg, count * sizeof(char *)); 410 ap.argv = p; 411 p32 = uap->argv; 412 do { 413 error = copyin(p32++, &arg, sizeof(arg)); 414 if (error) 415 return error; 416 *p++ = PTRIN(arg); 417 } while (arg != 0); 418 } 419 if (uap->envv) { 420 count = 0; 421 p32 = uap->envv; 422 do { 423 error = copyin(p32++, &arg, sizeof(arg)); 424 if (error) 425 return error; 426 count++; 427 } while (arg != 0); 428 p = stackgap_alloc(&sg, count * sizeof(char *)); 429 ap.envv = p; 430 p32 = uap->envv; 431 do { 432 error = copyin(p32++, &arg, sizeof(arg)); 433 if (error) 434 return error; 435 *p++ = PTRIN(arg); 436 } while (arg != 0); 437 } 438 439 return execve(td, &ap); 440} 441 442#ifdef __ia64__ 443static int 444ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 445 int prot, int fd, off_t pos) 446{ 447 vm_map_t map; 448 vm_map_entry_t entry; 449 int rv; 450 451 map = &td->td_proc->p_vmspace->vm_map; 452 if (fd != -1) 453 prot |= VM_PROT_WRITE; 454 455 if (vm_map_lookup_entry(map, start, &entry)) { 456 if ((entry->protection & prot) != prot) { 457 rv = vm_map_protect(map, 458 trunc_page(start), 459 round_page(end), 460 entry->protection | prot, 461 FALSE); 462 if (rv != KERN_SUCCESS) 463 return (EINVAL); 464 } 465 } else { 466 vm_offset_t addr = trunc_page(start); 467 rv = vm_map_find(map, 0, 0, 468 &addr, PAGE_SIZE, FALSE, prot, 469 VM_PROT_ALL, 0); 470 if (rv != KERN_SUCCESS) 471 return (EINVAL); 472 } 473 474 if (fd != -1) { 475 struct pread_args r; 476 r.fd = fd; 477 r.buf = (void *) start; 478 r.nbyte = end - start; 479 r.offset = pos; 480 return (pread(td, &r)); 481 } else { 482 while (start < end) { 483 subyte((void *) start, 0); 484 start++; 485 } 486 return (0); 487 } 488} 489#endif 490 491int 492ia32_mmap(struct thread *td, struct ia32_mmap_args *uap) 493{ 494 struct mmap_args ap; 495 vm_offset_t addr = (vm_offset_t) uap->addr; 496 vm_size_t len = uap->len; 497 int prot = uap->prot; 498 int flags = uap->flags; 499 int fd = uap->fd; 500 off_t pos = (uap->poslo 501 | ((off_t)uap->poshi << 32)); 502#ifdef __ia64__ 503 vm_size_t pageoff; 504 int error; 505 506 /* 507 * Attempt to handle page size hassles. 508 */ 509 pageoff = (pos & PAGE_MASK); 510 if (flags & MAP_FIXED) { 511 vm_offset_t start, end; 512 start = addr; 513 end = addr + len; 514 515 if (start != trunc_page(start)) { 516 error = ia32_mmap_partial(td, start, round_page(start), 517 prot, fd, pos); 518 if (fd != -1) 519 pos += round_page(start) - start; 520 start = round_page(start); 521 } 522 if (end != round_page(end)) { 523 vm_offset_t t = trunc_page(end); 524 error = ia32_mmap_partial(td, t, end, 525 prot, fd, 526 pos + t - start); 527 end = trunc_page(end); 528 } 529 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 530 /* 531 * We can't map this region at all. The specified 532 * address doesn't have the same alignment as the file 533 * position. Fake the mapping by simply reading the 534 * entire region into memory. First we need to make 535 * sure the region exists. 536 */ 537 vm_map_t map; 538 struct pread_args r; 539 int rv; 540 541 prot |= VM_PROT_WRITE; 542 map = &td->td_proc->p_vmspace->vm_map; 543 rv = vm_map_remove(map, start, end); 544 if (rv != KERN_SUCCESS) 545 return (EINVAL); 546 rv = vm_map_find(map, 0, 0, 547 &start, end - start, FALSE, 548 prot, VM_PROT_ALL, 0); 549 if (rv != KERN_SUCCESS) 550 return (EINVAL); 551 r.fd = fd; 552 r.buf = (void *) start; 553 r.nbyte = end - start; 554 r.offset = pos; 555 error = pread(td, &r); 556 if (error) 557 return (error); 558 559 td->td_retval[0] = addr; 560 return (0); 561 } 562 if (end == start) { 563 /* 564 * After dealing with the ragged ends, there 565 * might be none left. 566 */ 567 td->td_retval[0] = addr; 568 return (0); 569 } 570 addr = start; 571 len = end - start; 572 } 573#endif 574 575 ap.addr = (void *) addr; 576 ap.len = len; 577 ap.prot = prot; 578 ap.flags = flags; 579 ap.fd = fd; 580 ap.pos = pos; 581 582 return (mmap(td, &ap)); 583} 584 585struct itimerval32 { 586 struct timeval32 it_interval; 587 struct timeval32 it_value; 588}; 589 590int 591ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap) 592{ 593 int error; 594 caddr_t sg; 595 struct itimerval32 *p32, *op32, s32; 596 struct itimerval *p = NULL, *op = NULL, s; 597 598 p32 = uap->itv; 599 if (p32) { 600 sg = stackgap_init(); 601 p = stackgap_alloc(&sg, sizeof(struct itimerval)); 602 uap->itv = (struct itimerval32 *)p; 603 error = copyin(p32, &s32, sizeof(s32)); 604 if (error) 605 return (error); 606 TV_CP(s32, s, it_interval); 607 TV_CP(s32, s, it_value); 608 error = copyout(&s, p, sizeof(s)); 609 if (error) 610 return (error); 611 } 612 op32 = uap->oitv; 613 if (op32) { 614 sg = stackgap_init(); 615 op = stackgap_alloc(&sg, sizeof(struct itimerval)); 616 uap->oitv = (struct itimerval32 *)op; 617 } 618 error = setitimer(td, (struct setitimer_args *) uap); 619 if (error) 620 return (error); 621 if (op32) { 622 error = copyin(op, &s, sizeof(s)); 623 if (error) 624 return (error); 625 TV_CP(s, s32, it_interval); 626 TV_CP(s, s32, it_value); 627 error = copyout(&s32, op32, sizeof(s32)); 628 } 629 return (error); 630} 631 632int 633ia32_select(struct thread *td, struct ia32_select_args *uap) 634{ 635 int error; 636 caddr_t sg; 637 struct timeval32 *p32, s32; 638 struct timeval *p = NULL, s; 639 640 p32 = uap->tv; 641 if (p32) { 642 sg = stackgap_init(); 643 p = stackgap_alloc(&sg, sizeof(struct timeval)); 644 uap->tv = (struct timeval32 *)p; 645 error = copyin(p32, &s32, sizeof(s32)); 646 if (error) 647 return (error); 648 CP(s32, s, tv_sec); 649 CP(s32, s, tv_usec); 650 error = copyout(&s, p, sizeof(s)); 651 if (error) 652 return (error); 653 } 654 /* 655 * XXX big-endian needs to convert the fd_sets too. 656 */ 657 return (select(td, (struct select_args *) uap)); 658} 659 660struct kevent32 { 661 u_int32_t ident; /* identifier for this event */ 662 short filter; /* filter for event */ 663 u_short flags; 664 u_int fflags; 665 int32_t data; 666 u_int32_t udata; /* opaque user data identifier */ 667}; 668 669int 670ia32_kevent(struct thread *td, struct ia32_kevent_args *uap) 671{ 672 int error; 673 caddr_t sg; 674 struct timespec32 ts32; 675 struct timespec ts; 676 struct kevent32 ks32; 677 struct kevent *ks; 678 struct kevent_args a; 679 int i; 680 681 sg = stackgap_init(); 682 683 a.fd = uap->fd; 684 a.changelist = uap->changelist; 685 a.nchanges = uap->nchanges; 686 a.eventlist = uap->eventlist; 687 a.nevents = uap->nevents; 688 a.timeout = NULL; 689 690 if (uap->timeout) { 691 a.timeout = stackgap_alloc(&sg, sizeof(struct timespec)); 692 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 693 if (error) 694 return (error); 695 CP(ts32, ts, tv_sec); 696 CP(ts32, ts, tv_nsec); 697 error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts)); 698 if (error) 699 return (error); 700 } 701 if (uap->changelist) { 702 a.changelist = (struct kevent *)stackgap_alloc(&sg, uap->nchanges * sizeof(struct kevent)); 703 for (i = 0; i < uap->nchanges; i++) { 704 error = copyin(&uap->changelist[i], &ks32, sizeof(ks32)); 705 if (error) 706 return (error); 707 ks = (struct kevent *)(uintptr_t)&a.changelist[i]; 708 CP(ks32, *ks, ident); 709 CP(ks32, *ks, filter); 710 CP(ks32, *ks, flags); 711 CP(ks32, *ks, fflags); 712 CP(ks32, *ks, data); 713 PTRIN_CP(ks32, *ks, udata); 714 } 715 } 716 if (uap->eventlist) { 717 a.eventlist = stackgap_alloc(&sg, uap->nevents * sizeof(struct kevent)); 718 } 719 error = kevent(td, &a); 720 if (uap->eventlist && error > 0) { 721 for (i = 0; i < error; i++) { 722 ks = &a.eventlist[i]; 723 CP(*ks, ks32, ident); 724 CP(*ks, ks32, filter); 725 CP(*ks, ks32, flags); 726 CP(*ks, ks32, fflags); 727 CP(*ks, ks32, data); 728 PTROUT_CP(*ks, ks32, udata); 729 error = copyout(&ks32, &uap->eventlist[i], sizeof(ks32)); 730 if (error) 731 return (error); 732 } 733 } 734 return error; 735} 736 737int 738ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap) 739{ 740 int error; 741 caddr_t sg; 742 struct timeval32 *p32, s32; 743 struct timeval *p = NULL, s; 744 745 p32 = uap->tp; 746 if (p32) { 747 sg = stackgap_init(); 748 p = stackgap_alloc(&sg, sizeof(struct timeval)); 749 uap->tp = (struct timeval32 *)p; 750 } 751 error = gettimeofday(td, (struct gettimeofday_args *) uap); 752 if (error) 753 return (error); 754 if (p32) { 755 error = copyin(p, &s, sizeof(s)); 756 if (error) 757 return (error); 758 CP(s, s32, tv_sec); 759 CP(s, s32, tv_usec); 760 error = copyout(&s32, p32, sizeof(s32)); 761 if (error) 762 return (error); 763 } 764 return (error); 765} 766 767int 768ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap) 769{ 770 int error; 771 caddr_t sg; 772 struct rusage32 *p32, s32; 773 struct rusage *p = NULL, s; 774 775 p32 = uap->rusage; 776 if (p32) { 777 sg = stackgap_init(); 778 p = stackgap_alloc(&sg, sizeof(struct rusage)); 779 uap->rusage = (struct rusage32 *)p; 780 } 781 error = getrusage(td, (struct getrusage_args *) uap); 782 if (error) 783 return (error); 784 if (p32) { 785 error = copyin(p, &s, sizeof(s)); 786 if (error) 787 return (error); 788 TV_CP(s, s32, ru_utime); 789 TV_CP(s, s32, ru_stime); 790 CP(s, s32, ru_maxrss); 791 CP(s, s32, ru_ixrss); 792 CP(s, s32, ru_idrss); 793 CP(s, s32, ru_isrss); 794 CP(s, s32, ru_minflt); 795 CP(s, s32, ru_majflt); 796 CP(s, s32, ru_nswap); 797 CP(s, s32, ru_inblock); 798 CP(s, s32, ru_oublock); 799 CP(s, s32, ru_msgsnd); 800 CP(s, s32, ru_msgrcv); 801 CP(s, s32, ru_nsignals); 802 CP(s, s32, ru_nvcsw); 803 CP(s, s32, ru_nivcsw); 804 error = copyout(&s32, p32, sizeof(s32)); 805 } 806 return (error); 807} 808 809struct iovec32 { 810 u_int32_t iov_base; 811 int iov_len; 812}; 813#define STACKGAPLEN 400 814 815int 816ia32_readv(struct thread *td, struct ia32_readv_args *uap) 817{ 818 int error, osize, nsize, i; 819 caddr_t sg; 820 struct readv_args /* { 821 syscallarg(int) fd; 822 syscallarg(struct iovec *) iovp; 823 syscallarg(u_int) iovcnt; 824 } */ a; 825 struct iovec32 *oio; 826 struct iovec *nio; 827 828 sg = stackgap_init(); 829 830 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 831 return (EINVAL); 832 833 osize = uap->iovcnt * sizeof (struct iovec32); 834 nsize = uap->iovcnt * sizeof (struct iovec); 835 836 oio = malloc(osize, M_TEMP, M_WAITOK); 837 nio = malloc(nsize, M_TEMP, M_WAITOK); 838 839 error = 0; 840 if ((error = copyin(uap->iovp, oio, osize))) 841 goto punt; 842 for (i = 0; i < uap->iovcnt; i++) { 843 nio[i].iov_base = PTRIN(oio[i].iov_base); 844 nio[i].iov_len = oio[i].iov_len; 845 } 846 847 a.fd = uap->fd; 848 a.iovp = stackgap_alloc(&sg, nsize); 849 a.iovcnt = uap->iovcnt; 850 851 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 852 goto punt; 853 error = readv(td, &a); 854 855punt: 856 free(oio, M_TEMP); 857 free(nio, M_TEMP); 858 return (error); 859} 860 861int 862ia32_writev(struct thread *td, struct ia32_writev_args *uap) 863{ 864 int error, i, nsize, osize; 865 caddr_t sg; 866 struct writev_args /* { 867 syscallarg(int) fd; 868 syscallarg(struct iovec *) iovp; 869 syscallarg(u_int) iovcnt; 870 } */ a; 871 struct iovec32 *oio; 872 struct iovec *nio; 873 874 sg = stackgap_init(); 875 876 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 877 return (EINVAL); 878 879 osize = uap->iovcnt * sizeof (struct iovec32); 880 nsize = uap->iovcnt * sizeof (struct iovec); 881 882 oio = malloc(osize, M_TEMP, M_WAITOK); 883 nio = malloc(nsize, M_TEMP, M_WAITOK); 884 885 error = 0; 886 if ((error = copyin(uap->iovp, oio, osize))) 887 goto punt; 888 for (i = 0; i < uap->iovcnt; i++) { 889 nio[i].iov_base = PTRIN(oio[i].iov_base); 890 nio[i].iov_len = oio[i].iov_len; 891 } 892 893 a.fd = uap->fd; 894 a.iovp = stackgap_alloc(&sg, nsize); 895 a.iovcnt = uap->iovcnt; 896 897 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 898 goto punt; 899 error = writev(td, &a); 900 901punt: 902 free(oio, M_TEMP); 903 free(nio, M_TEMP); 904 return (error); 905} 906 907int 908ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap) 909{ 910 int error; 911 caddr_t sg; 912 struct timeval32 *p32, s32; 913 struct timeval *p = NULL, s; 914 915 p32 = uap->tv; 916 if (p32) { 917 sg = stackgap_init(); 918 p = stackgap_alloc(&sg, sizeof(struct timeval)); 919 uap->tv = (struct timeval32 *)p; 920 error = copyin(p32, &s32, sizeof(s32)); 921 if (error) 922 return (error); 923 CP(s32, s, tv_sec); 924 CP(s32, s, tv_usec); 925 error = copyout(&s, p, sizeof(s)); 926 if (error) 927 return (error); 928 } 929 return (settimeofday(td, (struct settimeofday_args *) uap)); 930} 931 932int 933ia32_utimes(struct thread *td, struct ia32_utimes_args *uap) 934{ 935 int error; 936 caddr_t sg; 937 struct timeval32 *p32, s32[2]; 938 struct timeval *p = NULL, s[2]; 939 940 p32 = uap->tptr; 941 if (p32) { 942 sg = stackgap_init(); 943 p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); 944 uap->tptr = (struct timeval32 *)p; 945 error = copyin(p32, s32, sizeof(s32)); 946 if (error) 947 return (error); 948 CP(s32[0], s[0], tv_sec); 949 CP(s32[0], s[0], tv_usec); 950 CP(s32[1], s[1], tv_sec); 951 CP(s32[1], s[1], tv_usec); 952 error = copyout(s, p, sizeof(s)); 953 if (error) 954 return (error); 955 } 956 return (utimes(td, (struct utimes_args *) uap)); 957} 958 959int 960ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap) 961{ 962 int error; 963 caddr_t sg; 964 struct timeval32 *p32, *op32, s32; 965 struct timeval *p = NULL, *op = NULL, s; 966 967 p32 = uap->delta; 968 if (p32) { 969 sg = stackgap_init(); 970 p = stackgap_alloc(&sg, sizeof(struct timeval)); 971 uap->delta = (struct timeval32 *)p; 972 error = copyin(p32, &s32, sizeof(s32)); 973 if (error) 974 return (error); 975 CP(s32, s, tv_sec); 976 CP(s32, s, tv_usec); 977 error = copyout(&s, p, sizeof(s)); 978 if (error) 979 return (error); 980 } 981 op32 = uap->olddelta; 982 if (op32) { 983 sg = stackgap_init(); 984 op = stackgap_alloc(&sg, sizeof(struct timeval)); 985 uap->olddelta = (struct timeval32 *)op; 986 } 987 error = utimes(td, (struct utimes_args *) uap); 988 if (error) 989 return error; 990 if (op32) { 991 error = copyin(op, &s, sizeof(s)); 992 if (error) 993 return (error); 994 CP(s, s32, tv_sec); 995 CP(s, s32, tv_usec); 996 error = copyout(&s32, op32, sizeof(s32)); 997 } 998 return (error); 999} 1000 1001int 1002ia32_statfs(struct thread *td, struct ia32_statfs_args *uap) 1003{ 1004 int error; 1005 caddr_t sg; 1006 struct statfs32 *p32, s32; 1007 struct statfs *p = NULL, s; 1008 1009 p32 = uap->buf; 1010 if (p32) { 1011 sg = stackgap_init(); 1012 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1013 uap->buf = (struct statfs32 *)p; 1014 } 1015 error = statfs(td, (struct statfs_args *) uap); 1016 if (error) 1017 return (error); 1018 if (p32) { 1019 error = copyin(p, &s, sizeof(s)); 1020 if (error) 1021 return (error); 1022 copy_statfs(&s, &s32); 1023 error = copyout(&s32, p32, sizeof(s32)); 1024 } 1025 return (error); 1026} 1027 1028int 1029ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap) 1030{ 1031 int error; 1032 caddr_t sg; 1033 struct statfs32 *p32, s32; 1034 struct statfs *p = NULL, s; 1035 1036 p32 = uap->buf; 1037 if (p32) { 1038 sg = stackgap_init(); 1039 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1040 uap->buf = (struct statfs32 *)p; 1041 } 1042 error = fstatfs(td, (struct fstatfs_args *) uap); 1043 if (error) 1044 return (error); 1045 if (p32) { 1046 error = copyin(p, &s, sizeof(s)); 1047 if (error) 1048 return (error); 1049 copy_statfs(&s, &s32); 1050 error = copyout(&s32, p32, sizeof(s32)); 1051 } 1052 return (error); 1053} 1054 1055int 1056ia32_semsys(struct thread *td, struct ia32_semsys_args *uap) 1057{ 1058 /* 1059 * Vector through to semsys if it is loaded. 1060 */ 1061 return sysent[169].sy_call(td, uap); 1062} 1063 1064int 1065ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap) 1066{ 1067 /* 1068 * Vector through to msgsys if it is loaded. 1069 */ 1070 return sysent[170].sy_call(td, uap); 1071} 1072 1073int 1074ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap) 1075{ 1076 /* 1077 * Vector through to shmsys if it is loaded. 1078 */ 1079 return sysent[171].sy_call(td, uap); 1080} 1081 1082int 1083ia32_pread(struct thread *td, struct ia32_pread_args *uap) 1084{ 1085 struct pread_args ap; 1086 1087 ap.fd = uap->fd; 1088 ap.buf = uap->buf; 1089 ap.nbyte = uap->nbyte; 1090 ap.offset = (uap->offsetlo 1091 | ((off_t)uap->offsethi << 32)); 1092 return (pread(td, &ap)); 1093} 1094 1095int 1096ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap) 1097{ 1098 struct pwrite_args ap; 1099 1100 ap.fd = uap->fd; 1101 ap.buf = uap->buf; 1102 ap.nbyte = uap->nbyte; 1103 ap.offset = (uap->offsetlo 1104 | ((off_t)uap->offsethi << 32)); 1105 return (pwrite(td, &ap)); 1106} 1107 1108int 1109ia32_lseek(struct thread *td, struct ia32_lseek_args *uap) 1110{ 1111 int error; 1112 struct lseek_args ap; 1113 off_t pos; 1114 1115 ap.fd = uap->fd; 1116 ap.offset = (uap->offsetlo 1117 | ((off_t)uap->offsethi << 32)); 1118 ap.whence = uap->whence; 1119 error = lseek(td, &ap); 1120 /* Expand the quad return into two parts for eax and edx */ 1121 pos = *(off_t *)(td->td_retval); 1122 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1123 td->td_retval[1] = pos >> 32; /* %edx */ 1124 return error; 1125} 1126 1127int 1128ia32_truncate(struct thread *td, struct ia32_truncate_args *uap) 1129{ 1130 struct truncate_args ap; 1131 1132 ap.path = uap->path; 1133 ap.length = (uap->lengthlo 1134 | ((off_t)uap->lengthhi << 32)); 1135 return (truncate(td, &ap)); 1136} 1137 1138int 1139ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap) 1140{ 1141 struct ftruncate_args ap; 1142 1143 ap.fd = uap->fd; 1144 ap.length = (uap->lengthlo 1145 | ((off_t)uap->lengthhi << 32)); 1146 return (ftruncate(td, &ap)); 1147} 1148 1149#ifdef COMPAT_FREEBSD4 1150int 1151freebsd4_ia32_sendfile(struct thread *td, 1152 struct freebsd4_ia32_sendfile_args *uap) 1153{ 1154 struct freebsd4_sendfile_args ap; 1155 1156 ap.fd = uap->fd; 1157 ap.s = uap->s; 1158 ap.offset = (uap->offsetlo 1159 | ((off_t)uap->offsethi << 32)); 1160 ap.nbytes = uap->nbytes; /* XXX check */ 1161 ap.hdtr = uap->hdtr; /* XXX check */ 1162 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1163 ap.flags = uap->flags; 1164 return (freebsd4_sendfile(td, &ap)); 1165} 1166#endif 1167 1168int 1169ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap) 1170{ 1171 struct sendfile_args ap; 1172 1173 ap.fd = uap->fd; 1174 ap.s = uap->s; 1175 ap.offset = (uap->offsetlo 1176 | ((off_t)uap->offsethi << 32)); 1177 ap.nbytes = uap->nbytes; /* XXX check */ 1178 ap.hdtr = uap->hdtr; /* XXX check */ 1179 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1180 ap.flags = uap->flags; 1181 return (sendfile(td, &ap)); 1182} 1183 1184struct stat32 { 1185 udev_t st_dev; 1186 ino_t st_ino; 1187 mode_t st_mode; 1188 nlink_t st_nlink; 1189 uid_t st_uid; 1190 gid_t st_gid; 1191 udev_t st_rdev; 1192 struct timespec32 st_atimespec; 1193 struct timespec32 st_mtimespec; 1194 struct timespec32 st_ctimespec; 1195 off_t st_size; 1196 int64_t st_blocks; 1197 u_int32_t st_blksize; 1198 u_int32_t st_flags; 1199 u_int32_t st_gen; 1200}; 1201 1202static void 1203copy_stat( struct stat *in, struct stat32 *out) 1204{ 1205 CP(*in, *out, st_dev); 1206 CP(*in, *out, st_ino); 1207 CP(*in, *out, st_mode); 1208 CP(*in, *out, st_nlink); 1209 CP(*in, *out, st_uid); 1210 CP(*in, *out, st_gid); 1211 CP(*in, *out, st_rdev); 1212 TS_CP(*in, *out, st_atimespec); 1213 TS_CP(*in, *out, st_mtimespec); 1214 TS_CP(*in, *out, st_ctimespec); 1215 CP(*in, *out, st_size); 1216 CP(*in, *out, st_blocks); 1217 CP(*in, *out, st_blksize); 1218 CP(*in, *out, st_flags); 1219 CP(*in, *out, st_gen); 1220} 1221 1222int 1223ia32_stat(struct thread *td, struct ia32_stat_args *uap) 1224{ 1225 int error; 1226 caddr_t sg; 1227 struct stat32 *p32, s32; 1228 struct stat *p = NULL, s; 1229 1230 p32 = uap->ub; 1231 if (p32) { 1232 sg = stackgap_init(); 1233 p = stackgap_alloc(&sg, sizeof(struct stat)); 1234 uap->ub = (struct stat32 *)p; 1235 } 1236 error = stat(td, (struct stat_args *) uap); 1237 if (error) 1238 return (error); 1239 if (p32) { 1240 error = copyin(p, &s, sizeof(s)); 1241 if (error) 1242 return (error); 1243 copy_stat(&s, &s32); 1244 error = copyout(&s32, p32, sizeof(s32)); 1245 } 1246 return (error); 1247} 1248 1249int 1250ia32_fstat(struct thread *td, struct ia32_fstat_args *uap) 1251{ 1252 int error; 1253 caddr_t sg; 1254 struct stat32 *p32, s32; 1255 struct stat *p = NULL, s; 1256 1257 p32 = uap->ub; 1258 if (p32) { 1259 sg = stackgap_init(); 1260 p = stackgap_alloc(&sg, sizeof(struct stat)); 1261 uap->ub = (struct stat32 *)p; 1262 } 1263 error = fstat(td, (struct fstat_args *) uap); 1264 if (error) 1265 return (error); 1266 if (p32) { 1267 error = copyin(p, &s, sizeof(s)); 1268 if (error) 1269 return (error); 1270 copy_stat(&s, &s32); 1271 error = copyout(&s32, p32, sizeof(s32)); 1272 } 1273 return (error); 1274} 1275 1276int 1277ia32_lstat(struct thread *td, struct ia32_lstat_args *uap) 1278{ 1279 int error; 1280 caddr_t sg; 1281 struct stat32 *p32, s32; 1282 struct stat *p = NULL, s; 1283 1284 p32 = uap->ub; 1285 if (p32) { 1286 sg = stackgap_init(); 1287 p = stackgap_alloc(&sg, sizeof(struct stat)); 1288 uap->ub = (struct stat32 *)p; 1289 } 1290 error = lstat(td, (struct lstat_args *) uap); 1291 if (error) 1292 return (error); 1293 if (p32) { 1294 error = copyin(p, &s, sizeof(s)); 1295 if (error) 1296 return (error); 1297 copy_stat(&s, &s32); 1298 error = copyout(&s32, p32, sizeof(s32)); 1299 } 1300 return (error); 1301} 1302 1303/* 1304 * MPSAFE 1305 */ 1306int 1307ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap) 1308{ 1309 int error, name[CTL_MAXNAME]; 1310 size_t j, oldlen; 1311 1312 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1313 return (EINVAL); 1314 1315 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 1316 if (error) 1317 return (error); 1318 1319 mtx_lock(&Giant); 1320 1321 if (uap->oldlenp) 1322 oldlen = fuword32(uap->oldlenp); 1323 else 1324 oldlen = 0; 1325 error = userland_sysctl(td, name, uap->namelen, 1326 uap->old, &oldlen, 1, 1327 uap->new, uap->newlen, &j); 1328 if (error && error != ENOMEM) 1329 goto done2; 1330 if (uap->oldlenp) { 1331 suword32(uap->oldlenp, j); 1332 } 1333done2: 1334 mtx_unlock(&Giant); 1335 return (error); 1336} 1337 1338struct sigaction32 { 1339 u_int32_t sa_u; 1340 int sa_flags; 1341 sigset_t sa_mask; 1342}; 1343 1344int 1345ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap) 1346{ 1347 struct sigaction32 s32; 1348 struct sigaction sa, osa, *sap; 1349 int error; 1350 1351 if (uap->act) { 1352 error = copyin(uap->act, &s32, sizeof(s32)); 1353 if (error) 1354 return (error); 1355 sa.sa_handler = PTRIN(s32.sa_u); 1356 CP(s32, sa, sa_flags); 1357 CP(s32, sa, sa_mask); 1358 sap = &sa; 1359 } else 1360 sap = NULL; 1361 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1362 if (error != 0 && uap->oact != NULL) { 1363 s32.sa_u = PTROUT(osa.sa_handler); 1364 CP(osa, s32, sa_flags); 1365 CP(osa, s32, sa_mask); 1366 error = copyout(&s32, uap->oact, sizeof(s32)); 1367 } 1368 return (error); 1369} 1370 1371#ifdef COMPAT_FREEBSD4 1372int 1373freebsd4_ia32_sigaction(struct thread *td, struct freebsd4_ia32_sigaction_args *uap) 1374{ 1375 struct sigaction32 s32; 1376 struct sigaction sa, osa, *sap; 1377 int error; 1378 1379 if (uap->act) { 1380 error = copyin(uap->act, &s32, sizeof(s32)); 1381 if (error) 1382 return (error); 1383 sa.sa_handler = PTRIN(s32.sa_u); 1384 CP(s32, sa, sa_flags); 1385 CP(s32, sa, sa_mask); 1386 sap = &sa; 1387 } else 1388 sap = NULL; 1389 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1390 if (error != 0 && uap->oact != NULL) { 1391 s32.sa_u = PTROUT(osa.sa_handler); 1392 CP(osa, s32, sa_flags); 1393 CP(osa, s32, sa_mask); 1394 error = copyout(&s32, uap->oact, sizeof(s32)); 1395 } 1396 return (error); 1397} 1398#endif 1399 1400#if 0 1401 1402int 1403ia32_xxx(struct thread *td, struct ia32_xxx_args *uap) 1404{ 1405 int error; 1406 caddr_t sg; 1407 struct yyy32 *p32, s32; 1408 struct yyy *p = NULL, s; 1409 1410 p32 = uap->zzz; 1411 if (p32) { 1412 sg = stackgap_init(); 1413 p = stackgap_alloc(&sg, sizeof(struct yyy)); 1414 uap->zzz = (struct yyy32 *)p; 1415 error = copyin(p32, &s32, sizeof(s32)); 1416 if (error) 1417 return (error); 1418 /* translate in */ 1419 error = copyout(&s, p, sizeof(s)); 1420 if (error) 1421 return (error); 1422 } 1423 error = xxx(td, (struct xxx_args *) uap); 1424 if (error) 1425 return (error); 1426 if (p32) { 1427 error = copyin(p, &s, sizeof(s)); 1428 if (error) 1429 return (error); 1430 /* translate out */ 1431 error = copyout(&s32, p32, sizeof(s32)); 1432 } 1433 return (error); 1434} 1435 1436#endif 1437