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