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