freebsd32_misc.c revision 118031
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 118031 2003-07-25 21:19:19Z obrien $"); 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 <amd64/ia32/ia32_util.h> 79#include <amd64/ia32/ia32.h> 80#include <amd64/ia32/ia32_proto.h> 81 82static const char ia32_emul_path[] = "/compat/ia32"; 83/* 84 * [ taken from the linux emulator ] 85 * Search an alternate path before passing pathname arguments on 86 * to system calls. Useful for keeping a separate 'emulation tree'. 87 * 88 * If cflag is set, we check if an attempt can be made to create 89 * the named file, i.e. we check if the directory it should 90 * be in exists. 91 */ 92int 93ia32_emul_find(td, sgp, prefix, path, pbuf, cflag) 94 struct thread *td; 95 caddr_t *sgp; /* Pointer to stackgap memory */ 96 const char *prefix; 97 char *path; 98 char **pbuf; 99 int cflag; 100{ 101 int error; 102 size_t len, sz; 103 char *buf, *cp, *ptr; 104 struct ucred *ucred; 105 struct nameidata nd; 106 struct nameidata ndroot; 107 struct vattr vat; 108 struct vattr vatroot; 109 110 buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 111 *pbuf = path; 112 113 for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 114 continue; 115 116 sz = MAXPATHLEN - (ptr - buf); 117 118 /* 119 * If sgp is not given then the path is already in kernel space 120 */ 121 if (sgp == NULL) 122 error = copystr(path, ptr, sz, &len); 123 else 124 error = copyinstr(path, ptr, sz, &len); 125 126 if (error) { 127 free(buf, M_TEMP); 128 return error; 129 } 130 131 if (*ptr != '/') { 132 free(buf, M_TEMP); 133 return EINVAL; 134 } 135 136 /* 137 * We know that there is a / somewhere in this pathname. 138 * Search backwards for it, to find the file's parent dir 139 * to see if it exists in the alternate tree. If it does, 140 * and we want to create a file (cflag is set). We don't 141 * need to worry about the root comparison in this case. 142 */ 143 144 if (cflag) { 145 for (cp = &ptr[len] - 1; *cp != '/'; cp--) 146 ; 147 *cp = '\0'; 148 149 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 150 151 if ((error = namei(&nd)) != 0) { 152 free(buf, M_TEMP); 153 return error; 154 } 155 156 *cp = '/'; 157 } else { 158 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 159 160 if ((error = namei(&nd)) != 0) { 161 free(buf, M_TEMP); 162 return error; 163 } 164 165 /* 166 * We now compare the vnode of the ia32_root to the one 167 * vnode asked. If they resolve to be the same, then we 168 * ignore the match so that the real root gets used. 169 * This avoids the problem of traversing "../.." to find the 170 * root directory and never finding it, because "/" resolves 171 * to the emulation root directory. This is expensive :-( 172 */ 173 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path, 174 td); 175 176 if ((error = namei(&ndroot)) != 0) { 177 /* Cannot happen! */ 178 free(buf, M_TEMP); 179 vrele(nd.ni_vp); 180 return error; 181 } 182 183 ucred = td->td_ucred; 184 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) { 185 goto bad; 186 } 187 188 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred, 189 td)) != 0) { 190 goto bad; 191 } 192 193 if (vat.va_fsid == vatroot.va_fsid && 194 vat.va_fileid == vatroot.va_fileid) { 195 error = ENOENT; 196 goto bad; 197 } 198 199 } 200 if (sgp == NULL) 201 *pbuf = buf; 202 else { 203 sz = &ptr[len] - buf; 204 *pbuf = stackgap_alloc(sgp, sz + 1); 205 error = copyout(buf, *pbuf, sz); 206 free(buf, M_TEMP); 207 } 208 209 vrele(nd.ni_vp); 210 if (!cflag) 211 vrele(ndroot.ni_vp); 212 213 return error; 214 215bad: 216 vrele(ndroot.ni_vp); 217 vrele(nd.ni_vp); 218 free(buf, M_TEMP); 219 return error; 220} 221 222int 223ia32_open(struct thread *td, struct ia32_open_args *uap) 224{ 225 caddr_t sg; 226 227 sg = stackgap_init(); 228 CHECKALTEXIST(td, &sg, uap->path); 229 230 return open(td, (struct open_args *) uap); 231} 232 233int 234ia32_wait4(struct thread *td, struct ia32_wait4_args *uap) 235{ 236 int error; 237 caddr_t sg; 238 struct rusage32 *rusage32, ru32; 239 struct rusage *rusage = NULL, ru; 240 241 rusage32 = uap->rusage; 242 if (rusage32) { 243 sg = stackgap_init(); 244 rusage = stackgap_alloc(&sg, sizeof(struct rusage)); 245 uap->rusage = (struct rusage32 *)rusage; 246 } 247 error = wait4(td, (struct wait_args *)uap); 248 if (error) 249 return (error); 250 if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) { 251 TV_CP(ru, ru32, ru_utime); 252 TV_CP(ru, ru32, ru_stime); 253 CP(ru, ru32, ru_maxrss); 254 CP(ru, ru32, ru_ixrss); 255 CP(ru, ru32, ru_idrss); 256 CP(ru, ru32, ru_isrss); 257 CP(ru, ru32, ru_minflt); 258 CP(ru, ru32, ru_majflt); 259 CP(ru, ru32, ru_nswap); 260 CP(ru, ru32, ru_inblock); 261 CP(ru, ru32, ru_oublock); 262 CP(ru, ru32, ru_msgsnd); 263 CP(ru, ru32, ru_msgrcv); 264 CP(ru, ru32, ru_nsignals); 265 CP(ru, ru32, ru_nvcsw); 266 CP(ru, ru32, ru_nivcsw); 267 error = copyout(&ru32, rusage32, sizeof(ru32)); 268 } 269 return (error); 270} 271 272static void 273copy_statfs(struct statfs *in, struct statfs32 *out) 274{ 275 CP(*in, *out, f_bsize); 276 CP(*in, *out, f_iosize); 277 CP(*in, *out, f_blocks); 278 CP(*in, *out, f_bfree); 279 CP(*in, *out, f_bavail); 280 CP(*in, *out, f_files); 281 CP(*in, *out, f_ffree); 282 CP(*in, *out, f_fsid); 283 CP(*in, *out, f_owner); 284 CP(*in, *out, f_type); 285 CP(*in, *out, f_flags); 286 CP(*in, *out, f_flags); 287 CP(*in, *out, f_syncwrites); 288 CP(*in, *out, f_asyncwrites); 289 bcopy(in->f_fstypename, 290 out->f_fstypename, MFSNAMELEN); 291 bcopy(in->f_mntonname, 292 out->f_mntonname, MNAMELEN); 293 CP(*in, *out, f_syncreads); 294 CP(*in, *out, f_asyncreads); 295 bcopy(in->f_mntfromname, 296 out->f_mntfromname, MNAMELEN); 297} 298 299int 300ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap) 301{ 302 int error; 303 caddr_t sg; 304 struct statfs32 *sp32, stat32; 305 struct statfs *sp = NULL, stat; 306 int maxcount, count, i; 307 308 sp32 = uap->buf; 309 maxcount = uap->bufsize / sizeof(struct statfs32); 310 311 if (sp32) { 312 sg = stackgap_init(); 313 sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); 314 uap->buf = (struct statfs32 *)sp; 315 } 316 error = getfsstat(td, (struct getfsstat_args *) uap); 317 if (sp32 && !error) { 318 count = td->td_retval[0]; 319 for (i = 0; i < count; i++) { 320 error = copyin(&sp[i], &stat, sizeof(stat)); 321 if (error) 322 return (error); 323 copy_statfs(&stat, &stat32); 324 error = copyout(&stat32, &sp32[i], sizeof(stat32)); 325 if (error) 326 return (error); 327 } 328 } 329 return (error); 330} 331 332int 333ia32_access(struct thread *td, struct ia32_access_args *uap) 334{ 335 caddr_t sg; 336 337 sg = stackgap_init(); 338 CHECKALTEXIST(td, &sg, uap->path); 339 340 return access(td, (struct access_args *)uap); 341} 342 343int 344ia32_chflags(struct thread *td, struct ia32_chflags_args *uap) 345{ 346 caddr_t sg; 347 348 sg = stackgap_init(); 349 CHECKALTEXIST(td, &sg, uap->path); 350 351 return chflags(td, (struct chflags_args *)uap); 352} 353 354struct sigaltstack32 { 355 u_int32_t ss_sp; 356 u_int32_t ss_size; 357 int ss_flags; 358}; 359 360int 361ia32_sigaltstack(struct thread *td, struct ia32_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 387int 388ia32_execve(struct thread *td, struct ia32_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__ 444static int 445ia32_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 492int 493ia32_mmap(struct thread *td, struct ia32_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 = ia32_mmap_partial(td, start, round_page(start), 518 prot, fd, pos); 519 if (fd != -1) 520 pos += round_page(start) - start; 521 start = round_page(start); 522 } 523 if (end != round_page(end)) { 524 vm_offset_t t = trunc_page(end); 525 error = ia32_mmap_partial(td, t, end, 526 prot, fd, 527 pos + t - start); 528 end = trunc_page(end); 529 } 530 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 531 /* 532 * We can't map this region at all. The specified 533 * address doesn't have the same alignment as the file 534 * position. Fake the mapping by simply reading the 535 * entire region into memory. First we need to make 536 * sure the region exists. 537 */ 538 vm_map_t map; 539 struct pread_args r; 540 int rv; 541 542 prot |= VM_PROT_WRITE; 543 map = &td->td_proc->p_vmspace->vm_map; 544 rv = vm_map_remove(map, start, end); 545 if (rv != KERN_SUCCESS) 546 return (EINVAL); 547 rv = vm_map_find(map, 0, 0, 548 &start, end - start, FALSE, 549 prot, VM_PROT_ALL, 0); 550 if (rv != KERN_SUCCESS) 551 return (EINVAL); 552 r.fd = fd; 553 r.buf = (void *) start; 554 r.nbyte = end - start; 555 r.offset = pos; 556 error = pread(td, &r); 557 if (error) 558 return (error); 559 560 td->td_retval[0] = addr; 561 return (0); 562 } 563 if (end == start) { 564 /* 565 * After dealing with the ragged ends, there 566 * might be none left. 567 */ 568 td->td_retval[0] = addr; 569 return (0); 570 } 571 addr = start; 572 len = end - start; 573 } 574#endif 575 576 ap.addr = (void *) addr; 577 ap.len = len; 578 ap.prot = prot; 579 ap.flags = flags; 580 ap.fd = fd; 581 ap.pos = pos; 582 583 return (mmap(td, &ap)); 584} 585 586struct itimerval32 { 587 struct timeval32 it_interval; 588 struct timeval32 it_value; 589}; 590 591int 592ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap) 593{ 594 int error; 595 caddr_t sg; 596 struct itimerval32 *p32, *op32, s32; 597 struct itimerval *p = NULL, *op = NULL, s; 598 599 p32 = uap->itv; 600 if (p32) { 601 sg = stackgap_init(); 602 p = stackgap_alloc(&sg, sizeof(struct itimerval)); 603 uap->itv = (struct itimerval32 *)p; 604 error = copyin(p32, &s32, sizeof(s32)); 605 if (error) 606 return (error); 607 TV_CP(s32, s, it_interval); 608 TV_CP(s32, s, it_value); 609 error = copyout(&s, p, sizeof(s)); 610 if (error) 611 return (error); 612 } 613 op32 = uap->oitv; 614 if (op32) { 615 sg = stackgap_init(); 616 op = stackgap_alloc(&sg, sizeof(struct itimerval)); 617 uap->oitv = (struct itimerval32 *)op; 618 } 619 error = setitimer(td, (struct setitimer_args *) uap); 620 if (error) 621 return (error); 622 if (op32) { 623 error = copyin(op, &s, sizeof(s)); 624 if (error) 625 return (error); 626 TV_CP(s, s32, it_interval); 627 TV_CP(s, s32, it_value); 628 error = copyout(&s32, op32, sizeof(s32)); 629 } 630 return (error); 631} 632 633int 634ia32_select(struct thread *td, struct ia32_select_args *uap) 635{ 636 int error; 637 caddr_t sg; 638 struct timeval32 *p32, s32; 639 struct timeval *p = NULL, s; 640 641 p32 = uap->tv; 642 if (p32) { 643 sg = stackgap_init(); 644 p = stackgap_alloc(&sg, sizeof(struct timeval)); 645 uap->tv = (struct timeval32 *)p; 646 error = copyin(p32, &s32, sizeof(s32)); 647 if (error) 648 return (error); 649 CP(s32, s, tv_sec); 650 CP(s32, s, tv_usec); 651 error = copyout(&s, p, sizeof(s)); 652 if (error) 653 return (error); 654 } 655 /* 656 * XXX big-endian needs to convert the fd_sets too. 657 */ 658 return (select(td, (struct select_args *) uap)); 659} 660 661struct kevent32 { 662 u_int32_t ident; /* identifier for this event */ 663 short filter; /* filter for event */ 664 u_short flags; 665 u_int fflags; 666 int32_t data; 667 u_int32_t udata; /* opaque user data identifier */ 668}; 669 670int 671ia32_kevent(struct thread *td, struct ia32_kevent_args *uap) 672{ 673 int error; 674 caddr_t sg; 675 struct timespec32 ts32; 676 struct timespec ts; 677 struct kevent32 ks32; 678 struct kevent *ks; 679 struct kevent_args a; 680 int i; 681 682 sg = stackgap_init(); 683 684 a.fd = uap->fd; 685 a.changelist = uap->changelist; 686 a.nchanges = uap->nchanges; 687 a.eventlist = uap->eventlist; 688 a.nevents = uap->nevents; 689 a.timeout = NULL; 690 691 if (uap->timeout) { 692 a.timeout = stackgap_alloc(&sg, sizeof(struct timespec)); 693 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 694 if (error) 695 return (error); 696 CP(ts32, ts, tv_sec); 697 CP(ts32, ts, tv_nsec); 698 error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts)); 699 if (error) 700 return (error); 701 } 702 if (uap->changelist) { 703 a.changelist = (struct kevent *)stackgap_alloc(&sg, uap->nchanges * sizeof(struct kevent)); 704 for (i = 0; i < uap->nchanges; i++) { 705 error = copyin(&uap->changelist[i], &ks32, sizeof(ks32)); 706 if (error) 707 return (error); 708 ks = (struct kevent *)(uintptr_t)&a.changelist[i]; 709 CP(ks32, *ks, ident); 710 CP(ks32, *ks, filter); 711 CP(ks32, *ks, flags); 712 CP(ks32, *ks, fflags); 713 CP(ks32, *ks, data); 714 PTRIN_CP(ks32, *ks, udata); 715 } 716 } 717 if (uap->eventlist) { 718 a.eventlist = stackgap_alloc(&sg, uap->nevents * sizeof(struct kevent)); 719 } 720 error = kevent(td, &a); 721 if (uap->eventlist && error > 0) { 722 for (i = 0; i < error; i++) { 723 ks = &a.eventlist[i]; 724 CP(*ks, ks32, ident); 725 CP(*ks, ks32, filter); 726 CP(*ks, ks32, flags); 727 CP(*ks, ks32, fflags); 728 CP(*ks, ks32, data); 729 PTROUT_CP(*ks, ks32, udata); 730 error = copyout(&ks32, &uap->eventlist[i], sizeof(ks32)); 731 if (error) 732 return (error); 733 } 734 } 735 return error; 736} 737 738int 739ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap) 740{ 741 int error; 742 caddr_t sg; 743 struct timeval32 *p32, s32; 744 struct timeval *p = NULL, s; 745 746 p32 = uap->tp; 747 if (p32) { 748 sg = stackgap_init(); 749 p = stackgap_alloc(&sg, sizeof(struct timeval)); 750 uap->tp = (struct timeval32 *)p; 751 } 752 error = gettimeofday(td, (struct gettimeofday_args *) uap); 753 if (error) 754 return (error); 755 if (p32) { 756 error = copyin(p, &s, sizeof(s)); 757 if (error) 758 return (error); 759 CP(s, s32, tv_sec); 760 CP(s, s32, tv_usec); 761 error = copyout(&s32, p32, sizeof(s32)); 762 if (error) 763 return (error); 764 } 765 return (error); 766} 767 768int 769ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap) 770{ 771 int error; 772 caddr_t sg; 773 struct rusage32 *p32, s32; 774 struct rusage *p = NULL, s; 775 776 p32 = uap->rusage; 777 if (p32) { 778 sg = stackgap_init(); 779 p = stackgap_alloc(&sg, sizeof(struct rusage)); 780 uap->rusage = (struct rusage32 *)p; 781 } 782 error = getrusage(td, (struct getrusage_args *) uap); 783 if (error) 784 return (error); 785 if (p32) { 786 error = copyin(p, &s, sizeof(s)); 787 if (error) 788 return (error); 789 TV_CP(s, s32, ru_utime); 790 TV_CP(s, s32, ru_stime); 791 CP(s, s32, ru_maxrss); 792 CP(s, s32, ru_ixrss); 793 CP(s, s32, ru_idrss); 794 CP(s, s32, ru_isrss); 795 CP(s, s32, ru_minflt); 796 CP(s, s32, ru_majflt); 797 CP(s, s32, ru_nswap); 798 CP(s, s32, ru_inblock); 799 CP(s, s32, ru_oublock); 800 CP(s, s32, ru_msgsnd); 801 CP(s, s32, ru_msgrcv); 802 CP(s, s32, ru_nsignals); 803 CP(s, s32, ru_nvcsw); 804 CP(s, s32, ru_nivcsw); 805 error = copyout(&s32, p32, sizeof(s32)); 806 } 807 return (error); 808} 809 810struct iovec32 { 811 u_int32_t iov_base; 812 int iov_len; 813}; 814#define STACKGAPLEN 400 815 816int 817ia32_readv(struct thread *td, struct ia32_readv_args *uap) 818{ 819 int error, osize, nsize, i; 820 caddr_t sg; 821 struct readv_args /* { 822 syscallarg(int) fd; 823 syscallarg(struct iovec *) iovp; 824 syscallarg(u_int) iovcnt; 825 } */ a; 826 struct iovec32 *oio; 827 struct iovec *nio; 828 829 sg = stackgap_init(); 830 831 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 832 return (EINVAL); 833 834 osize = uap->iovcnt * sizeof (struct iovec32); 835 nsize = uap->iovcnt * sizeof (struct iovec); 836 837 oio = malloc(osize, M_TEMP, M_WAITOK); 838 nio = malloc(nsize, M_TEMP, M_WAITOK); 839 840 error = 0; 841 if ((error = copyin(uap->iovp, oio, osize))) 842 goto punt; 843 for (i = 0; i < uap->iovcnt; i++) { 844 nio[i].iov_base = PTRIN(oio[i].iov_base); 845 nio[i].iov_len = oio[i].iov_len; 846 } 847 848 a.fd = uap->fd; 849 a.iovp = stackgap_alloc(&sg, nsize); 850 a.iovcnt = uap->iovcnt; 851 852 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 853 goto punt; 854 error = readv(td, &a); 855 856punt: 857 free(oio, M_TEMP); 858 free(nio, M_TEMP); 859 return (error); 860} 861 862int 863ia32_writev(struct thread *td, struct ia32_writev_args *uap) 864{ 865 int error, i, nsize, osize; 866 caddr_t sg; 867 struct writev_args /* { 868 syscallarg(int) fd; 869 syscallarg(struct iovec *) iovp; 870 syscallarg(u_int) iovcnt; 871 } */ a; 872 struct iovec32 *oio; 873 struct iovec *nio; 874 875 sg = stackgap_init(); 876 877 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 878 return (EINVAL); 879 880 osize = uap->iovcnt * sizeof (struct iovec32); 881 nsize = uap->iovcnt * sizeof (struct iovec); 882 883 oio = malloc(osize, M_TEMP, M_WAITOK); 884 nio = malloc(nsize, M_TEMP, M_WAITOK); 885 886 error = 0; 887 if ((error = copyin(uap->iovp, oio, osize))) 888 goto punt; 889 for (i = 0; i < uap->iovcnt; i++) { 890 nio[i].iov_base = PTRIN(oio[i].iov_base); 891 nio[i].iov_len = oio[i].iov_len; 892 } 893 894 a.fd = uap->fd; 895 a.iovp = stackgap_alloc(&sg, nsize); 896 a.iovcnt = uap->iovcnt; 897 898 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 899 goto punt; 900 error = writev(td, &a); 901 902punt: 903 free(oio, M_TEMP); 904 free(nio, M_TEMP); 905 return (error); 906} 907 908int 909ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap) 910{ 911 int error; 912 caddr_t sg; 913 struct timeval32 *p32, s32; 914 struct timeval *p = NULL, s; 915 916 p32 = uap->tv; 917 if (p32) { 918 sg = stackgap_init(); 919 p = stackgap_alloc(&sg, sizeof(struct timeval)); 920 uap->tv = (struct timeval32 *)p; 921 error = copyin(p32, &s32, sizeof(s32)); 922 if (error) 923 return (error); 924 CP(s32, s, tv_sec); 925 CP(s32, s, tv_usec); 926 error = copyout(&s, p, sizeof(s)); 927 if (error) 928 return (error); 929 } 930 return (settimeofday(td, (struct settimeofday_args *) uap)); 931} 932 933int 934ia32_utimes(struct thread *td, struct ia32_utimes_args *uap) 935{ 936 int error; 937 caddr_t sg; 938 struct timeval32 *p32, s32[2]; 939 struct timeval *p = NULL, s[2]; 940 941 p32 = uap->tptr; 942 if (p32) { 943 sg = stackgap_init(); 944 p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); 945 uap->tptr = (struct timeval32 *)p; 946 error = copyin(p32, s32, sizeof(s32)); 947 if (error) 948 return (error); 949 CP(s32[0], s[0], tv_sec); 950 CP(s32[0], s[0], tv_usec); 951 CP(s32[1], s[1], tv_sec); 952 CP(s32[1], s[1], tv_usec); 953 error = copyout(s, p, sizeof(s)); 954 if (error) 955 return (error); 956 } 957 return (utimes(td, (struct utimes_args *) uap)); 958} 959 960int 961ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap) 962{ 963 int error; 964 caddr_t sg; 965 struct timeval32 *p32, *op32, s32; 966 struct timeval *p = NULL, *op = NULL, s; 967 968 p32 = uap->delta; 969 if (p32) { 970 sg = stackgap_init(); 971 p = stackgap_alloc(&sg, sizeof(struct timeval)); 972 uap->delta = (struct timeval32 *)p; 973 error = copyin(p32, &s32, sizeof(s32)); 974 if (error) 975 return (error); 976 CP(s32, s, tv_sec); 977 CP(s32, s, tv_usec); 978 error = copyout(&s, p, sizeof(s)); 979 if (error) 980 return (error); 981 } 982 op32 = uap->olddelta; 983 if (op32) { 984 sg = stackgap_init(); 985 op = stackgap_alloc(&sg, sizeof(struct timeval)); 986 uap->olddelta = (struct timeval32 *)op; 987 } 988 error = utimes(td, (struct utimes_args *) uap); 989 if (error) 990 return error; 991 if (op32) { 992 error = copyin(op, &s, sizeof(s)); 993 if (error) 994 return (error); 995 CP(s, s32, tv_sec); 996 CP(s, s32, tv_usec); 997 error = copyout(&s32, op32, sizeof(s32)); 998 } 999 return (error); 1000} 1001 1002int 1003ia32_statfs(struct thread *td, struct ia32_statfs_args *uap) 1004{ 1005 int error; 1006 caddr_t sg; 1007 struct statfs32 *p32, s32; 1008 struct statfs *p = NULL, s; 1009 1010 p32 = uap->buf; 1011 if (p32) { 1012 sg = stackgap_init(); 1013 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1014 uap->buf = (struct statfs32 *)p; 1015 } 1016 error = statfs(td, (struct statfs_args *) uap); 1017 if (error) 1018 return (error); 1019 if (p32) { 1020 error = copyin(p, &s, sizeof(s)); 1021 if (error) 1022 return (error); 1023 copy_statfs(&s, &s32); 1024 error = copyout(&s32, p32, sizeof(s32)); 1025 } 1026 return (error); 1027} 1028 1029int 1030ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap) 1031{ 1032 int error; 1033 caddr_t sg; 1034 struct statfs32 *p32, s32; 1035 struct statfs *p = NULL, s; 1036 1037 p32 = uap->buf; 1038 if (p32) { 1039 sg = stackgap_init(); 1040 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1041 uap->buf = (struct statfs32 *)p; 1042 } 1043 error = fstatfs(td, (struct fstatfs_args *) uap); 1044 if (error) 1045 return (error); 1046 if (p32) { 1047 error = copyin(p, &s, sizeof(s)); 1048 if (error) 1049 return (error); 1050 copy_statfs(&s, &s32); 1051 error = copyout(&s32, p32, sizeof(s32)); 1052 } 1053 return (error); 1054} 1055 1056int 1057ia32_semsys(struct thread *td, struct ia32_semsys_args *uap) 1058{ 1059 /* 1060 * Vector through to semsys if it is loaded. 1061 */ 1062 return sysent[169].sy_call(td, uap); 1063} 1064 1065int 1066ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap) 1067{ 1068 /* 1069 * Vector through to msgsys if it is loaded. 1070 */ 1071 return sysent[170].sy_call(td, uap); 1072} 1073 1074int 1075ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap) 1076{ 1077 /* 1078 * Vector through to shmsys if it is loaded. 1079 */ 1080 return sysent[171].sy_call(td, uap); 1081} 1082 1083int 1084ia32_pread(struct thread *td, struct ia32_pread_args *uap) 1085{ 1086 struct pread_args ap; 1087 1088 ap.fd = uap->fd; 1089 ap.buf = uap->buf; 1090 ap.nbyte = uap->nbyte; 1091 ap.offset = (uap->offsetlo 1092 | ((off_t)uap->offsethi << 32)); 1093 return (pread(td, &ap)); 1094} 1095 1096int 1097ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap) 1098{ 1099 struct pwrite_args ap; 1100 1101 ap.fd = uap->fd; 1102 ap.buf = uap->buf; 1103 ap.nbyte = uap->nbyte; 1104 ap.offset = (uap->offsetlo 1105 | ((off_t)uap->offsethi << 32)); 1106 return (pwrite(td, &ap)); 1107} 1108 1109int 1110ia32_lseek(struct thread *td, struct ia32_lseek_args *uap) 1111{ 1112 int error; 1113 struct lseek_args ap; 1114 off_t pos; 1115 1116 ap.fd = uap->fd; 1117 ap.offset = (uap->offsetlo 1118 | ((off_t)uap->offsethi << 32)); 1119 ap.whence = uap->whence; 1120 error = lseek(td, &ap); 1121 /* Expand the quad return into two parts for eax and edx */ 1122 pos = *(off_t *)(td->td_retval); 1123 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1124 td->td_retval[1] = pos >> 32; /* %edx */ 1125 return error; 1126} 1127 1128int 1129ia32_truncate(struct thread *td, struct ia32_truncate_args *uap) 1130{ 1131 struct truncate_args ap; 1132 1133 ap.path = uap->path; 1134 ap.length = (uap->lengthlo 1135 | ((off_t)uap->lengthhi << 32)); 1136 return (truncate(td, &ap)); 1137} 1138 1139int 1140ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap) 1141{ 1142 struct ftruncate_args ap; 1143 1144 ap.fd = uap->fd; 1145 ap.length = (uap->lengthlo 1146 | ((off_t)uap->lengthhi << 32)); 1147 return (ftruncate(td, &ap)); 1148} 1149 1150#ifdef COMPAT_FREEBSD4 1151int 1152freebsd4_ia32_sendfile(struct thread *td, 1153 struct freebsd4_ia32_sendfile_args *uap) 1154{ 1155 struct freebsd4_sendfile_args ap; 1156 1157 ap.fd = uap->fd; 1158 ap.s = uap->s; 1159 ap.offset = (uap->offsetlo 1160 | ((off_t)uap->offsethi << 32)); 1161 ap.nbytes = uap->nbytes; /* XXX check */ 1162 ap.hdtr = uap->hdtr; /* XXX check */ 1163 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1164 ap.flags = uap->flags; 1165 return (freebsd4_sendfile(td, &ap)); 1166} 1167#endif 1168 1169int 1170ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap) 1171{ 1172 struct sendfile_args ap; 1173 1174 ap.fd = uap->fd; 1175 ap.s = uap->s; 1176 ap.offset = (uap->offsetlo 1177 | ((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 1185struct 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 1203static void 1204copy_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 1223int 1224ia32_stat(struct thread *td, struct ia32_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 1250int 1251ia32_fstat(struct thread *td, struct ia32_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 1277int 1278ia32_lstat(struct thread *td, struct ia32_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 */ 1307int 1308ia32_sysctl(struct thread *td, struct ia32_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 } 1334done2: 1335 mtx_unlock(&Giant); 1336 return (error); 1337} 1338 1339struct sigaction32 { 1340 u_int32_t sa_u; 1341 int sa_flags; 1342 sigset_t sa_mask; 1343}; 1344 1345int 1346ia32_sigaction(struct thread *td, struct ia32_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 1373int 1374freebsd4_ia32_sigaction(struct thread *td, struct freebsd4_ia32_sigaction_args *uap) 1375{ 1376 struct sigaction32 s32; 1377 struct sigaction sa, osa, *sap; 1378 int error; 1379 1380 if (uap->act) { 1381 error = copyin(uap->act, &s32, sizeof(s32)); 1382 if (error) 1383 return (error); 1384 sa.sa_handler = PTRIN(s32.sa_u); 1385 CP(s32, sa, sa_flags); 1386 CP(s32, sa, sa_mask); 1387 sap = &sa; 1388 } else 1389 sap = NULL; 1390 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1391 if (error != 0 && uap->oact != NULL) { 1392 s32.sa_u = PTROUT(osa.sa_handler); 1393 CP(osa, s32, sa_flags); 1394 CP(osa, s32, sa_mask); 1395 error = copyout(&s32, uap->oact, sizeof(s32)); 1396 } 1397 return (error); 1398} 1399#endif 1400 1401#if 0 1402 1403int 1404ia32_xxx(struct thread *td, struct ia32_xxx_args *uap) 1405{ 1406 int error; 1407 caddr_t sg; 1408 struct yyy32 *p32, s32; 1409 struct yyy *p = NULL, s; 1410 1411 p32 = uap->zzz; 1412 if (p32) { 1413 sg = stackgap_init(); 1414 p = stackgap_alloc(&sg, sizeof(struct yyy)); 1415 uap->zzz = (struct yyy32 *)p; 1416 error = copyin(p32, &s32, sizeof(s32)); 1417 if (error) 1418 return (error); 1419 /* translate in */ 1420 error = copyout(&s, p, sizeof(s)); 1421 if (error) 1422 return (error); 1423 } 1424 error = xxx(td, (struct xxx_args *) uap); 1425 if (error) 1426 return (error); 1427 if (p32) { 1428 error = copyin(p, &s, sizeof(s)); 1429 if (error) 1430 return (error); 1431 /* translate out */ 1432 error = copyout(&s32, p32, sizeof(s32)); 1433 } 1434 return (error); 1435} 1436 1437#endif 1438