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