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/mbuf.h> 45 #include <sys/mman.h> 46 #include <sys/module.h> 47 #include <sys/mount.h> 48 #include <sys/mutex.h> 49 #include <sys/namei.h> 50 #include <sys/param.h> 51 #include <sys/proc.h> 52 #include <sys/reboot.h> 53 #include <sys/resource.h> 54 #include <sys/resourcevar.h> 55 #include <sys/selinfo.h> 56 #include <sys/eventvar.h> /* Must come after sys/selinfo.h */ 57 #include <sys/pipe.h> /* Must come after sys/selinfo.h */ 58 #include <sys/signal.h> 59 #include <sys/signalvar.h> 60 #include <sys/socket.h> 61 #include <sys/socketvar.h> 62 #include <sys/stat.h> 63 #include <sys/syscall.h> 64 #include <sys/syscallsubr.h> 65 #include <sys/sysctl.h> 66 #include <sys/sysent.h> 67 #include <sys/sysproto.h> 68 #include <sys/systm.h> 69 #include <sys/unistd.h> 70 #include <sys/vnode.h> 71 #include <sys/wait.h> 72 73 #include <vm/vm.h> 74 #include <vm/vm_kern.h> 75 #include <vm/vm_param.h> 76 #include <vm/pmap.h> 77 #include <vm/vm_map.h> 78 #include <vm/vm_object.h> 79 #include <vm/vm_extern.h> 80 81 #include <machine/cpu.h> 82 83 #include <compat/freebsd32/freebsd32_util.h> 84 #include <compat/freebsd32/freebsd32.h> 85 #include <compat/freebsd32/freebsd32_proto.h> 86 87 CTASSERT(sizeof(struct timeval32) == 8); 88 CTASSERT(sizeof(struct timespec32) == 8); 89 CTASSERT(sizeof(struct statfs32) == 256); 90 CTASSERT(sizeof(struct rusage32) == 72); 91 92 int 93 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 94 { 95 int error, status; 96 struct rusage32 ru32; 97 struct rusage ru, *rup; 98 99 if (uap->rusage != NULL) 100 rup = &ru; 101 else 102 rup = NULL; 103 error = kern_wait(td, uap->pid, &status, uap->options, rup); 104 if (error) 105 return (error); 106 if (uap->status != NULL) 107 error = copyout(&status, uap->status, sizeof(status)); 108 if (uap->rusage != NULL && error == 0) { 109 TV_CP(ru, ru32, ru_utime); 110 TV_CP(ru, ru32, ru_stime); 111 CP(ru, ru32, ru_maxrss); 112 CP(ru, ru32, ru_ixrss); 113 CP(ru, ru32, ru_idrss); 114 CP(ru, ru32, ru_isrss); 115 CP(ru, ru32, ru_minflt); 116 CP(ru, ru32, ru_majflt); 117 CP(ru, ru32, ru_nswap); 118 CP(ru, ru32, ru_inblock); 119 CP(ru, ru32, ru_oublock); 120 CP(ru, ru32, ru_msgsnd); 121 CP(ru, ru32, ru_msgrcv); 122 CP(ru, ru32, ru_nsignals); 123 CP(ru, ru32, ru_nvcsw); 124 CP(ru, ru32, ru_nivcsw); 125 error = copyout(&ru32, uap->rusage, sizeof(ru32)); 126 } 127 return (error); 128 } 129 130 #ifdef COMPAT_FREEBSD4 131 static void 132 copy_statfs(struct statfs *in, struct statfs32 *out) 133 { 134 135 bzero(out, sizeof(*out)); 136 CP(*in, *out, f_bsize); 137 CP(*in, *out, f_iosize); 138 CP(*in, *out, f_blocks); 139 CP(*in, *out, f_bfree); 140 CP(*in, *out, f_bavail); 141 CP(*in, *out, f_files); 142 CP(*in, *out, f_ffree); 143 CP(*in, *out, f_fsid); 144 CP(*in, *out, f_owner); 145 CP(*in, *out, f_type); 146 CP(*in, *out, f_flags); 147 CP(*in, *out, f_flags); 148 CP(*in, *out, f_syncwrites); 149 CP(*in, *out, f_asyncwrites); 150 strlcpy(out->f_fstypename, 151 in->f_fstypename, MFSNAMELEN); 152 strlcpy(out->f_mntonname, 153 in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 154 CP(*in, *out, f_syncreads); 155 CP(*in, *out, f_asyncreads); 156 strlcpy(out->f_mntfromname, 157 in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 158 } 159 #endif 160 161 #ifdef COMPAT_FREEBSD4 162 int 163 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 164 { 165 struct statfs *buf, *sp; 166 struct statfs32 stat32; 167 size_t count, size; 168 int error; 169 170 count = uap->bufsize / sizeof(struct statfs32); 171 size = count * sizeof(struct statfs); 172 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 173 if (size > 0) { 174 count = td->td_retval[0]; 175 sp = buf; 176 while (count > 0 && error == 0) { 177 copy_statfs(sp, &stat32); 178 error = copyout(&stat32, uap->buf, sizeof(stat32)); 179 sp++; 180 uap->buf++; 181 count--; 182 } 183 free(buf, M_TEMP); 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 /* 226 * Custom version of exec_copyin_args() so that we can translate 227 * the pointers. 228 */ 229 static int 230 freebsd32_exec_copyin_args(struct image_args *args, char *fname, 231 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 232 { 233 char *argp, *envp; 234 u_int32_t *p32, arg; 235 size_t length; 236 int error; 237 238 bzero(args, sizeof(*args)); 239 if (argv == NULL) 240 return (EFAULT); 241 242 /* 243 * Allocate temporary demand zeroed space for argument and 244 * environment strings 245 */ 246 args->buf = (char *) kmem_alloc_wait(exec_map, 247 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 248 if (args->buf == NULL) 249 return (ENOMEM); 250 args->begin_argv = args->buf; 251 args->endp = args->begin_argv; 252 args->stringspace = ARG_MAX; 253 254 args->fname = args->buf + ARG_MAX; 255 256 /* 257 * Copy the file name. 258 */ 259 error = (segflg == UIO_SYSSPACE) ? 260 copystr(fname, args->fname, PATH_MAX, &length) : 261 copyinstr(fname, args->fname, PATH_MAX, &length); 262 if (error != 0) 263 goto err_exit; 264 265 /* 266 * extract arguments first 267 */ 268 p32 = argv; 269 for (;;) { 270 error = copyin(p32++, &arg, sizeof(arg)); 271 if (error) 272 goto err_exit; 273 if (arg == 0) 274 break; 275 argp = PTRIN(arg); 276 error = copyinstr(argp, args->endp, args->stringspace, &length); 277 if (error) { 278 if (error == ENAMETOOLONG) 279 error = E2BIG; 280 goto err_exit; 281 } 282 args->stringspace -= length; 283 args->endp += length; 284 args->argc++; 285 } 286 287 args->begin_envv = args->endp; 288 289 /* 290 * extract environment strings 291 */ 292 if (envv) { 293 p32 = envv; 294 for (;;) { 295 error = copyin(p32++, &arg, sizeof(arg)); 296 if (error) 297 goto err_exit; 298 if (arg == 0) 299 break; 300 envp = PTRIN(arg); 301 error = copyinstr(envp, args->endp, args->stringspace, 302 &length); 303 if (error) { 304 if (error == ENAMETOOLONG) 305 error = E2BIG; 306 goto err_exit; 307 } 308 args->stringspace -= length; 309 args->endp += length; 310 args->envc++; 311 } 312 } 313 314 return (0); 315 316 err_exit: 317 kmem_free_wakeup(exec_map, (vm_offset_t)args->buf, 318 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 319 args->buf = NULL; 320 return (error); 321 } 322 323 int 324 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 325 { 326 struct image_args eargs; 327 int error; 328 329 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 330 uap->argv, uap->envv); 331 if (error == 0) 332 error = kern_execve(td, &eargs, NULL); 333 return (error); 334 } 335 336 #ifdef __ia64__ 337 static int 338 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 339 int prot, int fd, off_t pos) 340 { 341 vm_map_t map; 342 vm_map_entry_t entry; 343 int rv; 344 345 map = &td->td_proc->p_vmspace->vm_map; 346 if (fd != -1) 347 prot |= VM_PROT_WRITE; 348 349 if (vm_map_lookup_entry(map, start, &entry)) { 350 if ((entry->protection & prot) != prot) { 351 rv = vm_map_protect(map, 352 trunc_page(start), 353 round_page(end), 354 entry->protection | prot, 355 FALSE); 356 if (rv != KERN_SUCCESS) 357 return (EINVAL); 358 } 359 } else { 360 vm_offset_t addr = trunc_page(start); 361 rv = vm_map_find(map, 0, 0, 362 &addr, PAGE_SIZE, FALSE, prot, 363 VM_PROT_ALL, 0); 364 if (rv != KERN_SUCCESS) 365 return (EINVAL); 366 } 367 368 if (fd != -1) { 369 struct pread_args r; 370 r.fd = fd; 371 r.buf = (void *) start; 372 r.nbyte = end - start; 373 r.offset = pos; 374 return (pread(td, &r)); 375 } else { 376 while (start < end) { 377 subyte((void *) start, 0); 378 start++; 379 } 380 return (0); 381 } 382 } 383 #endif 384 385 int 386 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 387 { 388 struct mmap_args ap; 389 vm_offset_t addr = (vm_offset_t) uap->addr; 390 vm_size_t len = uap->len; 391 int prot = uap->prot; 392 int flags = uap->flags; 393 int fd = uap->fd; 394 off_t pos = (uap->poslo 395 | ((off_t)uap->poshi << 32)); 396 #ifdef __ia64__ 397 vm_size_t pageoff; 398 int error; 399 400 /* 401 * Attempt to handle page size hassles. 402 */ 403 pageoff = (pos & PAGE_MASK); 404 if (flags & MAP_FIXED) { 405 vm_offset_t start, end; 406 start = addr; 407 end = addr + len; 408 409 mtx_lock(&Giant); 410 if (start != trunc_page(start)) { 411 error = freebsd32_mmap_partial(td, start, 412 round_page(start), prot, 413 fd, pos); 414 if (fd != -1) 415 pos += round_page(start) - start; 416 start = round_page(start); 417 } 418 if (end != round_page(end)) { 419 vm_offset_t t = trunc_page(end); 420 error = freebsd32_mmap_partial(td, t, end, 421 prot, fd, 422 pos + t - start); 423 end = trunc_page(end); 424 } 425 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 426 /* 427 * We can't map this region at all. The specified 428 * address doesn't have the same alignment as the file 429 * position. Fake the mapping by simply reading the 430 * entire region into memory. First we need to make 431 * sure the region exists. 432 */ 433 vm_map_t map; 434 struct pread_args r; 435 int rv; 436 437 prot |= VM_PROT_WRITE; 438 map = &td->td_proc->p_vmspace->vm_map; 439 rv = vm_map_remove(map, start, end); 440 if (rv != KERN_SUCCESS) { 441 mtx_unlock(&Giant); 442 return (EINVAL); 443 } 444 rv = vm_map_find(map, 0, 0, 445 &start, end - start, FALSE, 446 prot, VM_PROT_ALL, 0); 447 mtx_unlock(&Giant); 448 if (rv != KERN_SUCCESS) 449 return (EINVAL); 450 r.fd = fd; 451 r.buf = (void *) start; 452 r.nbyte = end - start; 453 r.offset = pos; 454 error = pread(td, &r); 455 if (error) 456 return (error); 457 458 td->td_retval[0] = addr; 459 return (0); 460 } 461 mtx_unlock(&Giant); 462 if (end == start) { 463 /* 464 * After dealing with the ragged ends, there 465 * might be none left. 466 */ 467 td->td_retval[0] = addr; 468 return (0); 469 } 470 addr = start; 471 len = end - start; 472 } 473 #endif 474 475 ap.addr = (void *) addr; 476 ap.len = len; 477 ap.prot = prot; 478 ap.flags = flags; 479 ap.fd = fd; 480 ap.pos = pos; 481 482 return (mmap(td, &ap)); 483 } 484 485 struct itimerval32 { 486 struct timeval32 it_interval; 487 struct timeval32 it_value; 488 }; 489 490 CTASSERT(sizeof(struct itimerval32) == 16); 491 492 int 493 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 494 { 495 struct itimerval itv, oitv, *itvp; 496 struct itimerval32 i32; 497 int error; 498 499 if (uap->itv != NULL) { 500 error = copyin(uap->itv, &i32, sizeof(i32)); 501 if (error) 502 return (error); 503 TV_CP(i32, itv, it_interval); 504 TV_CP(i32, itv, it_value); 505 itvp = &itv; 506 } else 507 itvp = NULL; 508 error = kern_setitimer(td, uap->which, itvp, &oitv); 509 if (error || uap->oitv == NULL) 510 return (error); 511 TV_CP(oitv, i32, it_interval); 512 TV_CP(oitv, i32, it_value); 513 return (copyout(&i32, uap->oitv, sizeof(i32))); 514 } 515 516 int 517 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 518 { 519 struct itimerval itv; 520 struct itimerval32 i32; 521 int error; 522 523 error = kern_getitimer(td, uap->which, &itv); 524 if (error || uap->itv == NULL) 525 return (error); 526 TV_CP(itv, i32, it_interval); 527 TV_CP(itv, i32, it_value); 528 return (copyout(&i32, uap->itv, sizeof(i32))); 529 } 530 531 int 532 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 533 { 534 struct timeval32 tv32; 535 struct timeval tv, *tvp; 536 int error; 537 538 if (uap->tv != NULL) { 539 error = copyin(uap->tv, &tv32, sizeof(tv32)); 540 if (error) 541 return (error); 542 CP(tv32, tv, tv_sec); 543 CP(tv32, tv, tv_usec); 544 tvp = &tv; 545 } else 546 tvp = NULL; 547 /* 548 * XXX big-endian needs to convert the fd_sets too. 549 * XXX Do pointers need PTRIN()? 550 */ 551 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); 552 } 553 554 struct kevent32 { 555 u_int32_t ident; /* identifier for this event */ 556 short filter; /* filter for event */ 557 u_short flags; 558 u_int fflags; 559 int32_t data; 560 u_int32_t udata; /* opaque user data identifier */ 561 }; 562 563 CTASSERT(sizeof(struct kevent32) == 20); 564 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 565 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 566 567 /* 568 * Copy 'count' items into the destination list pointed to by uap->eventlist. 569 */ 570 static int 571 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 572 { 573 struct freebsd32_kevent_args *uap; 574 struct kevent32 ks32[KQ_NEVENTS]; 575 int i, error = 0; 576 577 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 578 uap = (struct freebsd32_kevent_args *)arg; 579 580 for (i = 0; i < count; i++) { 581 CP(kevp[i], ks32[i], ident); 582 CP(kevp[i], ks32[i], filter); 583 CP(kevp[i], ks32[i], flags); 584 CP(kevp[i], ks32[i], fflags); 585 CP(kevp[i], ks32[i], data); 586 PTROUT_CP(kevp[i], ks32[i], udata); 587 } 588 error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 589 if (error == 0) 590 uap->eventlist += count; 591 return (error); 592 } 593 594 /* 595 * Copy 'count' items from the list pointed to by uap->changelist. 596 */ 597 static int 598 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 599 { 600 struct freebsd32_kevent_args *uap; 601 struct kevent32 ks32[KQ_NEVENTS]; 602 int i, error = 0; 603 604 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 605 uap = (struct freebsd32_kevent_args *)arg; 606 607 error = copyin(uap->changelist, ks32, count * sizeof *ks32); 608 if (error) 609 goto done; 610 uap->changelist += count; 611 612 for (i = 0; i < count; i++) { 613 CP(ks32[i], kevp[i], ident); 614 CP(ks32[i], kevp[i], filter); 615 CP(ks32[i], kevp[i], flags); 616 CP(ks32[i], kevp[i], fflags); 617 CP(ks32[i], kevp[i], data); 618 PTRIN_CP(ks32[i], kevp[i], udata); 619 } 620 done: 621 return (error); 622 } 623 624 int 625 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 626 { 627 struct timespec32 ts32; 628 struct timespec ts, *tsp; 629 struct kevent_copyops k_ops = { uap, 630 freebsd32_kevent_copyout, 631 freebsd32_kevent_copyin}; 632 int error; 633 634 635 if (uap->timeout) { 636 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 637 if (error) 638 return (error); 639 CP(ts32, ts, tv_sec); 640 CP(ts32, ts, tv_nsec); 641 tsp = &ts; 642 } else 643 tsp = NULL; 644 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 645 &k_ops, tsp); 646 return (error); 647 } 648 649 int 650 freebsd32_gettimeofday(struct thread *td, 651 struct freebsd32_gettimeofday_args *uap) 652 { 653 struct timeval atv; 654 struct timeval32 atv32; 655 struct timezone rtz; 656 int error = 0; 657 658 if (uap->tp) { 659 microtime(&atv); 660 CP(atv, atv32, tv_sec); 661 CP(atv, atv32, tv_usec); 662 error = copyout(&atv32, uap->tp, sizeof (atv32)); 663 } 664 if (error == 0 && uap->tzp != NULL) { 665 rtz.tz_minuteswest = tz_minuteswest; 666 rtz.tz_dsttime = tz_dsttime; 667 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 668 } 669 return (error); 670 } 671 672 int 673 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 674 { 675 struct rusage32 s32; 676 struct rusage s; 677 int error; 678 679 error = kern_getrusage(td, uap->who, &s); 680 if (error) 681 return (error); 682 if (uap->rusage != NULL) { 683 TV_CP(s, s32, ru_utime); 684 TV_CP(s, s32, ru_stime); 685 CP(s, s32, ru_maxrss); 686 CP(s, s32, ru_ixrss); 687 CP(s, s32, ru_idrss); 688 CP(s, s32, ru_isrss); 689 CP(s, s32, ru_minflt); 690 CP(s, s32, ru_majflt); 691 CP(s, s32, ru_nswap); 692 CP(s, s32, ru_inblock); 693 CP(s, s32, ru_oublock); 694 CP(s, s32, ru_msgsnd); 695 CP(s, s32, ru_msgrcv); 696 CP(s, s32, ru_nsignals); 697 CP(s, s32, ru_nvcsw); 698 CP(s, s32, ru_nivcsw); 699 error = copyout(&s32, uap->rusage, sizeof(s32)); 700 } 701 return (error); 702 } 703 704 struct iovec32 { 705 u_int32_t iov_base; 706 int iov_len; 707 }; 708 709 CTASSERT(sizeof(struct iovec32) == 8); 710 711 static int 712 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 713 { 714 struct iovec32 iov32; 715 struct iovec *iov; 716 struct uio *uio; 717 u_int iovlen; 718 int error, i; 719 720 *uiop = NULL; 721 if (iovcnt > UIO_MAXIOV) 722 return (EINVAL); 723 iovlen = iovcnt * sizeof(struct iovec); 724 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 725 iov = (struct iovec *)(uio + 1); 726 for (i = 0; i < iovcnt; i++) { 727 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 728 if (error) { 729 free(uio, M_IOV); 730 return (error); 731 } 732 iov[i].iov_base = PTRIN(iov32.iov_base); 733 iov[i].iov_len = iov32.iov_len; 734 } 735 uio->uio_iov = iov; 736 uio->uio_iovcnt = iovcnt; 737 uio->uio_segflg = UIO_USERSPACE; 738 uio->uio_offset = -1; 739 uio->uio_resid = 0; 740 for (i = 0; i < iovcnt; i++) { 741 if (iov->iov_len > INT_MAX - uio->uio_resid) { 742 free(uio, M_IOV); 743 return (EINVAL); 744 } 745 uio->uio_resid += iov->iov_len; 746 iov++; 747 } 748 *uiop = uio; 749 return (0); 750 } 751 752 int 753 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 754 { 755 struct uio *auio; 756 int error; 757 758 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 759 if (error) 760 return (error); 761 error = kern_readv(td, uap->fd, auio); 762 free(auio, M_IOV); 763 return (error); 764 } 765 766 int 767 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 768 { 769 struct uio *auio; 770 int error; 771 772 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 773 if (error) 774 return (error); 775 error = kern_writev(td, uap->fd, auio); 776 free(auio, M_IOV); 777 return (error); 778 } 779 780 int 781 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap) 782 { 783 struct uio *auio; 784 int error; 785 786 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 787 if (error) 788 return (error); 789 error = kern_preadv(td, uap->fd, auio, uap->offset); 790 free(auio, M_IOV); 791 return (error); 792 } 793 794 int 795 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) 796 { 797 struct uio *auio; 798 int error; 799 800 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 801 if (error) 802 return (error); 803 error = kern_pwritev(td, uap->fd, auio, uap->offset); 804 free(auio, M_IOV); 805 return (error); 806 } 807 808 static int 809 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp, 810 int error) 811 { 812 struct iovec32 iov32; 813 struct iovec *iov; 814 u_int iovlen; 815 int i; 816 817 *iovp = NULL; 818 if (iovcnt > UIO_MAXIOV) 819 return (error); 820 iovlen = iovcnt * sizeof(struct iovec); 821 iov = malloc(iovlen, M_IOV, M_WAITOK); 822 for (i = 0; i < iovcnt; i++) { 823 error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32)); 824 if (error) { 825 free(iov, M_IOV); 826 return (error); 827 } 828 iov[i].iov_base = PTRIN(iov32.iov_base); 829 iov[i].iov_len = iov32.iov_len; 830 } 831 *iovp = iov; 832 return (0); 833 } 834 835 static int 836 freebsd32_copyoutiov(struct iovec *iov, u_int iovcnt, struct iovec32 *iovp, 837 int error) 838 { 839 struct iovec32 iov32; 840 int i; 841 842 if (iovcnt > UIO_MAXIOV) 843 return (error); 844 for (i = 0; i < iovcnt; i++) { 845 iov32.iov_base = PTROUT(iov[i].iov_base); 846 iov32.iov_len = iov[i].iov_len; 847 error = copyout(&iov32, &iovp[i], sizeof(iov32)); 848 if (error) 849 return (error); 850 } 851 return (0); 852 } 853 854 855 struct msghdr32 { 856 u_int32_t msg_name; 857 socklen_t msg_namelen; 858 u_int32_t msg_iov; 859 int msg_iovlen; 860 u_int32_t msg_control; 861 socklen_t msg_controllen; 862 int msg_flags; 863 }; 864 CTASSERT(sizeof(struct msghdr32) == 28); 865 866 static int 867 freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg) 868 { 869 struct msghdr32 m32; 870 int error; 871 872 error = copyin(msg32, &m32, sizeof(m32)); 873 if (error) 874 return (error); 875 msg->msg_name = PTRIN(m32.msg_name); 876 msg->msg_namelen = m32.msg_namelen; 877 msg->msg_iov = PTRIN(m32.msg_iov); 878 msg->msg_iovlen = m32.msg_iovlen; 879 msg->msg_control = PTRIN(m32.msg_control); 880 msg->msg_controllen = m32.msg_controllen; 881 msg->msg_flags = m32.msg_flags; 882 return (0); 883 } 884 885 static int 886 freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32) 887 { 888 struct msghdr32 m32; 889 int error; 890 891 m32.msg_name = PTROUT(msg->msg_name); 892 m32.msg_namelen = msg->msg_namelen; 893 m32.msg_iov = PTROUT(msg->msg_iov); 894 m32.msg_iovlen = msg->msg_iovlen; 895 m32.msg_control = PTROUT(msg->msg_control); 896 m32.msg_controllen = msg->msg_controllen; 897 m32.msg_flags = msg->msg_flags; 898 error = copyout(&m32, msg32, sizeof(m32)); 899 return (error); 900 } 901 902 #define FREEBSD32_ALIGNBYTES (sizeof(int) - 1) 903 #define FREEBSD32_ALIGN(p) \ 904 (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES) 905 #define FREEBSD32_CMSG_SPACE(l) \ 906 (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l)) 907 908 #define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ 909 FREEBSD32_ALIGN(sizeof(struct cmsghdr))) 910 static int 911 freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) 912 { 913 struct cmsghdr *cm; 914 void *data; 915 socklen_t clen, datalen; 916 int error; 917 caddr_t ctlbuf; 918 int len, maxlen, copylen; 919 struct mbuf *m; 920 error = 0; 921 922 len = msg->msg_controllen; 923 maxlen = msg->msg_controllen; 924 msg->msg_controllen = 0; 925 926 m = control; 927 ctlbuf = msg->msg_control; 928 929 while (m && len > 0) { 930 cm = mtod(m, struct cmsghdr *); 931 clen = m->m_len; 932 933 while (cm != NULL) { 934 935 if (sizeof(struct cmsghdr) > clen || 936 cm->cmsg_len > clen) { 937 error = EINVAL; 938 break; 939 } 940 941 data = CMSG_DATA(cm); 942 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 943 944 /* Adjust message length */ 945 cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + 946 datalen; 947 948 949 /* Copy cmsghdr */ 950 copylen = sizeof(struct cmsghdr); 951 if (len < copylen) { 952 msg->msg_flags |= MSG_CTRUNC; 953 copylen = len; 954 } 955 956 error = copyout(cm,ctlbuf,copylen); 957 if (error) 958 goto exit; 959 960 ctlbuf += FREEBSD32_ALIGN(copylen); 961 len -= FREEBSD32_ALIGN(copylen); 962 963 if (len <= 0) 964 break; 965 966 /* Copy data */ 967 copylen = datalen; 968 if (len < copylen) { 969 msg->msg_flags |= MSG_CTRUNC; 970 copylen = len; 971 } 972 973 error = copyout(data,ctlbuf,copylen); 974 if (error) 975 goto exit; 976 977 ctlbuf += FREEBSD32_ALIGN(copylen); 978 len -= FREEBSD32_ALIGN(copylen); 979 980 if (CMSG_SPACE(datalen) < clen) { 981 clen -= CMSG_SPACE(datalen); 982 cm = (struct cmsghdr *) 983 ((caddr_t)cm + CMSG_SPACE(datalen)); 984 } else { 985 clen = 0; 986 cm = NULL; 987 } 988 } 989 m = m->m_next; 990 } 991 992 msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control; 993 994 exit: 995 return (error); 996 997 } 998 999 int 1000 freebsd32_recvmsg(td, uap) 1001 struct thread *td; 1002 struct freebsd32_recvmsg_args /* { 1003 int s; 1004 struct msghdr32 *msg; 1005 int flags; 1006 } */ *uap; 1007 { 1008 struct msghdr msg; 1009 struct msghdr32 m32; 1010 struct iovec *uiov, *iov; 1011 struct mbuf *control = NULL; 1012 struct mbuf **controlp; 1013 1014 int error; 1015 error = copyin(uap->msg, &m32, sizeof(m32)); 1016 if (error) 1017 return (error); 1018 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1019 if (error) 1020 return (error); 1021 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 1022 m32.msg_iovlen, &iov, EMSGSIZE); 1023 if (error) 1024 return (error); 1025 msg.msg_flags = uap->flags; 1026 uiov = msg.msg_iov; 1027 msg.msg_iov = iov; 1028 1029 controlp = (msg.msg_control != NULL) ? &control : NULL; 1030 error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp); 1031 if (error == 0) { 1032 msg.msg_iov = uiov; 1033 1034 if (control != NULL) 1035 error = freebsd32_copy_msg_out(&msg, control); 1036 1037 if (error == 0) 1038 error = freebsd32_copyoutmsghdr(&msg, uap->msg); 1039 1040 if (error == 0) 1041 error = freebsd32_copyoutiov(iov, m32.msg_iovlen, 1042 (struct iovec32 *)(uintptr_t)m32.msg_iov, EMSGSIZE); 1043 } 1044 free(iov, M_IOV); 1045 1046 if (control != NULL) 1047 m_freem(control); 1048 1049 return (error); 1050 } 1051 1052 1053 static int 1054 freebsd32_convert_msg_in(struct mbuf **controlp) 1055 { 1056 struct mbuf *control = *controlp; 1057 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 1058 void *data; 1059 socklen_t clen = control->m_len, datalen; 1060 int error; 1061 1062 error = 0; 1063 *controlp = NULL; 1064 1065 while (cm != NULL) { 1066 if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) { 1067 error = EINVAL; 1068 break; 1069 } 1070 1071 data = FREEBSD32_CMSG_DATA(cm); 1072 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1073 1074 *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type, 1075 cm->cmsg_level); 1076 controlp = &(*controlp)->m_next; 1077 1078 if (FREEBSD32_CMSG_SPACE(datalen) < clen) { 1079 clen -= FREEBSD32_CMSG_SPACE(datalen); 1080 cm = (struct cmsghdr *) 1081 ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen)); 1082 } else { 1083 clen = 0; 1084 cm = NULL; 1085 } 1086 } 1087 1088 m_freem(control); 1089 return (error); 1090 } 1091 1092 1093 int 1094 freebsd32_sendmsg(struct thread *td, 1095 struct freebsd32_sendmsg_args *uap) 1096 { 1097 struct msghdr msg; 1098 struct msghdr32 m32; 1099 struct iovec *iov; 1100 struct mbuf *control = NULL; 1101 struct sockaddr *to = NULL; 1102 int error; 1103 1104 error = copyin(uap->msg, &m32, sizeof(m32)); 1105 if (error) 1106 return (error); 1107 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1108 if (error) 1109 return (error); 1110 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 1111 m32.msg_iovlen, &iov, EMSGSIZE); 1112 if (error) 1113 return (error); 1114 msg.msg_iov = iov; 1115 if (msg.msg_name != NULL) { 1116 error = getsockaddr(&to, msg.msg_name, msg.msg_namelen); 1117 if (error) { 1118 to = NULL; 1119 goto out; 1120 } 1121 msg.msg_name = to; 1122 } 1123 1124 if (msg.msg_control) { 1125 if (msg.msg_controllen < sizeof(struct cmsghdr)) { 1126 error = EINVAL; 1127 goto out; 1128 } 1129 1130 error = sockargs(&control, msg.msg_control, 1131 msg.msg_controllen, MT_CONTROL); 1132 if (error) 1133 goto out; 1134 1135 error = freebsd32_convert_msg_in(&control); 1136 if (error) 1137 goto out; 1138 } 1139 1140 error = kern_sendit(td, uap->s, &msg, uap->flags, control, 1141 UIO_USERSPACE); 1142 1143 out: 1144 free(iov, M_IOV); 1145 if (to) 1146 free(to, M_SONAME); 1147 return (error); 1148 } 1149 1150 int 1151 freebsd32_recvfrom(struct thread *td, 1152 struct freebsd32_recvfrom_args *uap) 1153 { 1154 struct msghdr msg; 1155 struct iovec aiov; 1156 int error; 1157 1158 if (uap->fromlenaddr) { 1159 error = copyin((void *)(uintptr_t)uap->fromlenaddr, 1160 &msg.msg_namelen, sizeof(msg.msg_namelen)); 1161 if (error) 1162 return (error); 1163 } else { 1164 msg.msg_namelen = 0; 1165 } 1166 1167 msg.msg_name = (void *)(uintptr_t)uap->from; 1168 msg.msg_iov = &aiov; 1169 msg.msg_iovlen = 1; 1170 aiov.iov_base = (void *)(uintptr_t)uap->buf; 1171 aiov.iov_len = uap->len; 1172 msg.msg_control = 0; 1173 msg.msg_flags = uap->flags; 1174 error = kern_recvit(td, uap->s, &msg, 1175 (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE, NULL); 1176 return (error); 1177 } 1178 1179 int 1180 freebsd32_settimeofday(struct thread *td, 1181 struct freebsd32_settimeofday_args *uap) 1182 { 1183 struct timeval32 tv32; 1184 struct timeval tv, *tvp; 1185 struct timezone tz, *tzp; 1186 int error; 1187 1188 if (uap->tv) { 1189 error = copyin(uap->tv, &tv32, sizeof(tv32)); 1190 if (error) 1191 return (error); 1192 CP(tv32, tv, tv_sec); 1193 CP(tv32, tv, tv_usec); 1194 tvp = &tv; 1195 } else 1196 tvp = NULL; 1197 if (uap->tzp) { 1198 error = copyin(uap->tzp, &tz, sizeof(tz)); 1199 if (error) 1200 return (error); 1201 tzp = &tz; 1202 } else 1203 tzp = NULL; 1204 return (kern_settimeofday(td, tvp, tzp)); 1205 } 1206 1207 int 1208 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 1209 { 1210 struct timeval32 s32[2]; 1211 struct timeval s[2], *sp; 1212 int error; 1213 1214 if (uap->tptr != NULL) { 1215 error = copyin(uap->tptr, s32, sizeof(s32)); 1216 if (error) 1217 return (error); 1218 CP(s32[0], s[0], tv_sec); 1219 CP(s32[0], s[0], tv_usec); 1220 CP(s32[1], s[1], tv_sec); 1221 CP(s32[1], s[1], tv_usec); 1222 sp = s; 1223 } else 1224 sp = NULL; 1225 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1226 } 1227 1228 int 1229 freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap) 1230 { 1231 struct timeval32 s32[2]; 1232 struct timeval s[2], *sp; 1233 int error; 1234 1235 if (uap->tptr != NULL) { 1236 error = copyin(uap->tptr, s32, sizeof(s32)); 1237 if (error) 1238 return (error); 1239 CP(s32[0], s[0], tv_sec); 1240 CP(s32[0], s[0], tv_usec); 1241 CP(s32[1], s[1], tv_sec); 1242 CP(s32[1], s[1], tv_usec); 1243 sp = s; 1244 } else 1245 sp = NULL; 1246 return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1247 } 1248 1249 int 1250 freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap) 1251 { 1252 struct timeval32 s32[2]; 1253 struct timeval s[2], *sp; 1254 int error; 1255 1256 if (uap->tptr != NULL) { 1257 error = copyin(uap->tptr, s32, sizeof(s32)); 1258 if (error) 1259 return (error); 1260 CP(s32[0], s[0], tv_sec); 1261 CP(s32[0], s[0], tv_usec); 1262 CP(s32[1], s[1], tv_sec); 1263 CP(s32[1], s[1], tv_usec); 1264 sp = s; 1265 } else 1266 sp = NULL; 1267 return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE)); 1268 } 1269 1270 1271 int 1272 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 1273 { 1274 struct timeval32 tv32; 1275 struct timeval delta, olddelta, *deltap; 1276 int error; 1277 1278 if (uap->delta) { 1279 error = copyin(uap->delta, &tv32, sizeof(tv32)); 1280 if (error) 1281 return (error); 1282 CP(tv32, delta, tv_sec); 1283 CP(tv32, delta, tv_usec); 1284 deltap = δ 1285 } else 1286 deltap = NULL; 1287 error = kern_adjtime(td, deltap, &olddelta); 1288 if (uap->olddelta && error == 0) { 1289 CP(olddelta, tv32, tv_sec); 1290 CP(olddelta, tv32, tv_usec); 1291 error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 1292 } 1293 return (error); 1294 } 1295 1296 #ifdef COMPAT_FREEBSD4 1297 int 1298 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 1299 { 1300 struct statfs32 s32; 1301 struct statfs s; 1302 int error; 1303 1304 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 1305 if (error) 1306 return (error); 1307 copy_statfs(&s, &s32); 1308 return (copyout(&s32, uap->buf, sizeof(s32))); 1309 } 1310 #endif 1311 1312 #ifdef COMPAT_FREEBSD4 1313 int 1314 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 1315 { 1316 struct statfs32 s32; 1317 struct statfs s; 1318 int error; 1319 1320 error = kern_fstatfs(td, uap->fd, &s); 1321 if (error) 1322 return (error); 1323 copy_statfs(&s, &s32); 1324 return (copyout(&s32, uap->buf, sizeof(s32))); 1325 } 1326 #endif 1327 1328 #ifdef COMPAT_FREEBSD4 1329 int 1330 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 1331 { 1332 struct statfs32 s32; 1333 struct statfs s; 1334 fhandle_t fh; 1335 int error; 1336 1337 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 1338 return (error); 1339 error = kern_fhstatfs(td, fh, &s); 1340 if (error) 1341 return (error); 1342 copy_statfs(&s, &s32); 1343 return (copyout(&s32, uap->buf, sizeof(s32))); 1344 } 1345 #endif 1346 1347 int 1348 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1349 { 1350 /* 1351 * Vector through to semsys if it is loaded. 1352 */ 1353 return sysent[SYS_semsys].sy_call(td, uap); 1354 } 1355 1356 int 1357 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1358 { 1359 /* 1360 * Vector through to msgsys if it is loaded. 1361 */ 1362 return sysent[SYS_msgsys].sy_call(td, uap); 1363 } 1364 1365 int 1366 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1367 { 1368 /* 1369 * Vector through to shmsys if it is loaded. 1370 */ 1371 return sysent[SYS_shmsys].sy_call(td, uap); 1372 } 1373 1374 int 1375 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1376 { 1377 struct pread_args ap; 1378 1379 ap.fd = uap->fd; 1380 ap.buf = uap->buf; 1381 ap.nbyte = uap->nbyte; 1382 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1383 return (pread(td, &ap)); 1384 } 1385 1386 int 1387 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1388 { 1389 struct pwrite_args ap; 1390 1391 ap.fd = uap->fd; 1392 ap.buf = uap->buf; 1393 ap.nbyte = uap->nbyte; 1394 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1395 return (pwrite(td, &ap)); 1396 } 1397 1398 int 1399 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1400 { 1401 int error; 1402 struct lseek_args ap; 1403 off_t pos; 1404 1405 ap.fd = uap->fd; 1406 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1407 ap.whence = uap->whence; 1408 error = lseek(td, &ap); 1409 /* Expand the quad return into two parts for eax and edx */ 1410 pos = *(off_t *)(td->td_retval); 1411 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1412 td->td_retval[1] = pos >> 32; /* %edx */ 1413 return error; 1414 } 1415 1416 int 1417 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1418 { 1419 struct truncate_args ap; 1420 1421 ap.path = uap->path; 1422 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1423 return (truncate(td, &ap)); 1424 } 1425 1426 int 1427 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1428 { 1429 struct ftruncate_args ap; 1430 1431 ap.fd = uap->fd; 1432 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1433 return (ftruncate(td, &ap)); 1434 } 1435 1436 struct sf_hdtr32 { 1437 uint32_t headers; 1438 int hdr_cnt; 1439 uint32_t trailers; 1440 int trl_cnt; 1441 }; 1442 1443 static int 1444 freebsd32_do_sendfile(struct thread *td, 1445 struct freebsd32_sendfile_args *uap, int compat) 1446 { 1447 struct sendfile_args ap; 1448 struct sf_hdtr32 hdtr32; 1449 struct sf_hdtr hdtr; 1450 struct uio *hdr_uio, *trl_uio; 1451 struct iovec32 *iov32; 1452 int error; 1453 1454 hdr_uio = trl_uio = NULL; 1455 1456 ap.fd = uap->fd; 1457 ap.s = uap->s; 1458 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1459 ap.nbytes = uap->nbytes; 1460 ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */ 1461 ap.sbytes = uap->sbytes; 1462 ap.flags = uap->flags; 1463 1464 if (uap->hdtr != NULL) { 1465 error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32)); 1466 if (error) 1467 goto out; 1468 PTRIN_CP(hdtr32, hdtr, headers); 1469 CP(hdtr32, hdtr, hdr_cnt); 1470 PTRIN_CP(hdtr32, hdtr, trailers); 1471 CP(hdtr32, hdtr, trl_cnt); 1472 1473 if (hdtr.headers != NULL) { 1474 iov32 = (struct iovec32 *)(uintptr_t)hdtr32.headers; 1475 error = freebsd32_copyinuio(iov32, 1476 hdtr32.hdr_cnt, &hdr_uio); 1477 if (error) 1478 goto out; 1479 } 1480 if (hdtr.trailers != NULL) { 1481 iov32 = (struct iovec32 *)(uintptr_t)hdtr32.trailers; 1482 error = freebsd32_copyinuio(iov32, 1483 hdtr32.trl_cnt, &trl_uio); 1484 if (error) 1485 goto out; 1486 } 1487 } 1488 1489 error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat); 1490 out: 1491 if (hdr_uio) 1492 free(hdr_uio, M_IOV); 1493 if (trl_uio) 1494 free(trl_uio, M_IOV); 1495 return (error); 1496 } 1497 1498 #ifdef COMPAT_FREEBSD4 1499 int 1500 freebsd4_freebsd32_sendfile(struct thread *td, 1501 struct freebsd4_freebsd32_sendfile_args *uap) 1502 { 1503 return (freebsd32_do_sendfile(td, 1504 (struct freebsd32_sendfile_args *)uap, 1)); 1505 } 1506 #endif 1507 1508 int 1509 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1510 { 1511 1512 return (freebsd32_do_sendfile(td, uap, 0)); 1513 } 1514 1515 struct stat32 { 1516 dev_t st_dev; 1517 ino_t st_ino; 1518 mode_t st_mode; 1519 nlink_t st_nlink; 1520 uid_t st_uid; 1521 gid_t st_gid; 1522 dev_t st_rdev; 1523 struct timespec32 st_atimespec; 1524 struct timespec32 st_mtimespec; 1525 struct timespec32 st_ctimespec; 1526 off_t st_size; 1527 int64_t st_blocks; 1528 u_int32_t st_blksize; 1529 u_int32_t st_flags; 1530 u_int32_t st_gen; 1531 struct timespec32 st_birthtimespec; 1532 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1533 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1534 }; 1535 1536 1537 CTASSERT(sizeof(struct stat32) == 96); 1538 1539 static void 1540 copy_stat( struct stat *in, struct stat32 *out) 1541 { 1542 CP(*in, *out, st_dev); 1543 CP(*in, *out, st_ino); 1544 CP(*in, *out, st_mode); 1545 CP(*in, *out, st_nlink); 1546 CP(*in, *out, st_uid); 1547 CP(*in, *out, st_gid); 1548 CP(*in, *out, st_rdev); 1549 TS_CP(*in, *out, st_atimespec); 1550 TS_CP(*in, *out, st_mtimespec); 1551 TS_CP(*in, *out, st_ctimespec); 1552 CP(*in, *out, st_size); 1553 CP(*in, *out, st_blocks); 1554 CP(*in, *out, st_blksize); 1555 CP(*in, *out, st_flags); 1556 CP(*in, *out, st_gen); 1557 } 1558 1559 int 1560 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1561 { 1562 struct stat sb; 1563 struct stat32 sb32; 1564 int error; 1565 1566 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1567 if (error) 1568 return (error); 1569 copy_stat(&sb, &sb32); 1570 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1571 return (error); 1572 } 1573 1574 int 1575 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1576 { 1577 struct stat ub; 1578 struct stat32 ub32; 1579 int error; 1580 1581 error = kern_fstat(td, uap->fd, &ub); 1582 if (error) 1583 return (error); 1584 copy_stat(&ub, &ub32); 1585 error = copyout(&ub32, uap->ub, sizeof(ub32)); 1586 return (error); 1587 } 1588 1589 int 1590 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1591 { 1592 struct stat sb; 1593 struct stat32 sb32; 1594 int error; 1595 1596 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1597 if (error) 1598 return (error); 1599 copy_stat(&sb, &sb32); 1600 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1601 return (error); 1602 } 1603 1604 /* 1605 * MPSAFE 1606 */ 1607 int 1608 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1609 { 1610 int error, name[CTL_MAXNAME]; 1611 size_t j, oldlen; 1612 1613 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1614 return (EINVAL); 1615 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 1616 if (error) 1617 return (error); 1618 mtx_lock(&Giant); 1619 if (uap->oldlenp) 1620 oldlen = fuword32(uap->oldlenp); 1621 else 1622 oldlen = 0; 1623 error = userland_sysctl(td, name, uap->namelen, 1624 uap->old, &oldlen, 1, 1625 uap->new, uap->newlen, &j, SCTL_MASK32); 1626 if (error && error != ENOMEM) 1627 goto done2; 1628 if (uap->oldlenp) 1629 suword32(uap->oldlenp, j); 1630 done2: 1631 mtx_unlock(&Giant); 1632 return (error); 1633 } 1634 1635 struct sigaction32 { 1636 u_int32_t sa_u; 1637 int sa_flags; 1638 sigset_t sa_mask; 1639 }; 1640 1641 CTASSERT(sizeof(struct sigaction32) == 24); 1642 1643 int 1644 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1645 { 1646 struct sigaction32 s32; 1647 struct sigaction sa, osa, *sap; 1648 int error; 1649 1650 if (uap->act) { 1651 error = copyin(uap->act, &s32, sizeof(s32)); 1652 if (error) 1653 return (error); 1654 sa.sa_handler = PTRIN(s32.sa_u); 1655 CP(s32, sa, sa_flags); 1656 CP(s32, sa, sa_mask); 1657 sap = &sa; 1658 } else 1659 sap = NULL; 1660 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1661 if (error == 0 && uap->oact != NULL) { 1662 s32.sa_u = PTROUT(osa.sa_handler); 1663 CP(osa, s32, sa_flags); 1664 CP(osa, s32, sa_mask); 1665 error = copyout(&s32, uap->oact, sizeof(s32)); 1666 } 1667 return (error); 1668 } 1669 1670 #ifdef COMPAT_FREEBSD4 1671 int 1672 freebsd4_freebsd32_sigaction(struct thread *td, 1673 struct freebsd4_freebsd32_sigaction_args *uap) 1674 { 1675 struct sigaction32 s32; 1676 struct sigaction sa, osa, *sap; 1677 int error; 1678 1679 if (uap->act) { 1680 error = copyin(uap->act, &s32, sizeof(s32)); 1681 if (error) 1682 return (error); 1683 sa.sa_handler = PTRIN(s32.sa_u); 1684 CP(s32, sa, sa_flags); 1685 CP(s32, sa, sa_mask); 1686 sap = &sa; 1687 } else 1688 sap = NULL; 1689 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1690 if (error == 0 && uap->oact != NULL) { 1691 s32.sa_u = PTROUT(osa.sa_handler); 1692 CP(osa, s32, sa_flags); 1693 CP(osa, s32, sa_mask); 1694 error = copyout(&s32, uap->oact, sizeof(s32)); 1695 } 1696 return (error); 1697 } 1698 #endif 1699 1700 #ifdef COMPAT_43 1701 struct osigaction32 { 1702 u_int32_t sa_u; 1703 osigset_t sa_mask; 1704 int sa_flags; 1705 }; 1706 1707 #define ONSIG 32 1708 1709 int 1710 ofreebsd32_sigaction(struct thread *td, 1711 struct ofreebsd32_sigaction_args *uap) 1712 { 1713 struct osigaction32 s32; 1714 struct sigaction sa, osa, *sap; 1715 int error; 1716 1717 if (uap->signum <= 0 || uap->signum >= ONSIG) 1718 return (EINVAL); 1719 1720 if (uap->nsa) { 1721 error = copyin(uap->nsa, &s32, sizeof(s32)); 1722 if (error) 1723 return (error); 1724 sa.sa_handler = PTRIN(s32.sa_u); 1725 CP(s32, sa, sa_flags); 1726 OSIG2SIG(s32.sa_mask, sa.sa_mask); 1727 sap = &sa; 1728 } else 1729 sap = NULL; 1730 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1731 if (error == 0 && uap->osa != NULL) { 1732 s32.sa_u = PTROUT(osa.sa_handler); 1733 CP(osa, s32, sa_flags); 1734 SIG2OSIG(osa.sa_mask, s32.sa_mask); 1735 error = copyout(&s32, uap->osa, sizeof(s32)); 1736 } 1737 return (error); 1738 } 1739 1740 int 1741 ofreebsd32_sigprocmask(struct thread *td, 1742 struct ofreebsd32_sigprocmask_args *uap) 1743 { 1744 sigset_t set, oset; 1745 int error; 1746 1747 OSIG2SIG(uap->mask, set); 1748 error = kern_sigprocmask(td, uap->how, &set, &oset, 1); 1749 SIG2OSIG(oset, td->td_retval[0]); 1750 return (error); 1751 } 1752 1753 int 1754 ofreebsd32_sigpending(struct thread *td, 1755 struct ofreebsd32_sigpending_args *uap) 1756 { 1757 struct proc *p = td->td_proc; 1758 sigset_t siglist; 1759 1760 PROC_LOCK(p); 1761 siglist = p->p_siglist; 1762 SIGSETOR(siglist, td->td_siglist); 1763 PROC_UNLOCK(p); 1764 SIG2OSIG(siglist, td->td_retval[0]); 1765 return (0); 1766 } 1767 1768 struct sigvec32 { 1769 u_int32_t sv_handler; 1770 int sv_mask; 1771 int sv_flags; 1772 }; 1773 1774 int 1775 ofreebsd32_sigvec(struct thread *td, 1776 struct ofreebsd32_sigvec_args *uap) 1777 { 1778 struct sigvec32 vec; 1779 struct sigaction sa, osa, *sap; 1780 int error; 1781 1782 if (uap->signum <= 0 || uap->signum >= ONSIG) 1783 return (EINVAL); 1784 1785 if (uap->nsv) { 1786 error = copyin(uap->nsv, &vec, sizeof(vec)); 1787 if (error) 1788 return (error); 1789 sa.sa_handler = PTRIN(vec.sv_handler); 1790 OSIG2SIG(vec.sv_mask, sa.sa_mask); 1791 sa.sa_flags = vec.sv_flags; 1792 sa.sa_flags ^= SA_RESTART; 1793 sap = &sa; 1794 } else 1795 sap = NULL; 1796 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1797 if (error == 0 && uap->osv != NULL) { 1798 vec.sv_handler = PTROUT(osa.sa_handler); 1799 SIG2OSIG(osa.sa_mask, vec.sv_mask); 1800 vec.sv_flags = osa.sa_flags; 1801 vec.sv_flags &= ~SA_NOCLDWAIT; 1802 vec.sv_flags ^= SA_RESTART; 1803 error = copyout(&vec, uap->osv, sizeof(vec)); 1804 } 1805 return (error); 1806 } 1807 1808 int 1809 ofreebsd32_sigblock(struct thread *td, 1810 struct ofreebsd32_sigblock_args *uap) 1811 { 1812 struct proc *p = td->td_proc; 1813 sigset_t set; 1814 1815 OSIG2SIG(uap->mask, set); 1816 SIG_CANTMASK(set); 1817 PROC_LOCK(p); 1818 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 1819 SIGSETOR(td->td_sigmask, set); 1820 PROC_UNLOCK(p); 1821 return (0); 1822 } 1823 1824 int 1825 ofreebsd32_sigsetmask(struct thread *td, 1826 struct ofreebsd32_sigsetmask_args *uap) 1827 { 1828 struct proc *p = td->td_proc; 1829 sigset_t set; 1830 1831 OSIG2SIG(uap->mask, set); 1832 SIG_CANTMASK(set); 1833 PROC_LOCK(p); 1834 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 1835 SIGSETLO(td->td_sigmask, set); 1836 signotify(td); 1837 PROC_UNLOCK(p); 1838 return (0); 1839 } 1840 1841 int 1842 ofreebsd32_sigsuspend(struct thread *td, 1843 struct ofreebsd32_sigsuspend_args *uap) 1844 { 1845 struct proc *p = td->td_proc; 1846 sigset_t mask; 1847 1848 PROC_LOCK(p); 1849 td->td_oldsigmask = td->td_sigmask; 1850 td->td_pflags |= TDP_OLDMASK; 1851 OSIG2SIG(uap->mask, mask); 1852 SIG_CANTMASK(mask); 1853 SIGSETLO(td->td_sigmask, mask); 1854 signotify(td); 1855 while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) 1856 /* void */; 1857 PROC_UNLOCK(p); 1858 /* always return EINTR rather than ERESTART... */ 1859 return (EINTR); 1860 } 1861 1862 struct sigstack32 { 1863 u_int32_t ss_sp; 1864 int ss_onstack; 1865 }; 1866 1867 int 1868 ofreebsd32_sigstack(struct thread *td, 1869 struct ofreebsd32_sigstack_args *uap) 1870 { 1871 struct sigstack32 s32; 1872 struct sigstack nss, oss; 1873 int error = 0; 1874 1875 if (uap->nss != NULL) { 1876 error = copyin(uap->nss, &s32, sizeof(s32)); 1877 if (error) 1878 return (error); 1879 nss.ss_sp = PTRIN(s32.ss_sp); 1880 CP(s32, nss, ss_onstack); 1881 } 1882 oss.ss_sp = td->td_sigstk.ss_sp; 1883 oss.ss_onstack = sigonstack(cpu_getstack(td)); 1884 if (uap->nss != NULL) { 1885 td->td_sigstk.ss_sp = nss.ss_sp; 1886 td->td_sigstk.ss_size = 0; 1887 td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK; 1888 td->td_pflags |= TDP_ALTSTACK; 1889 } 1890 if (uap->oss != NULL) { 1891 s32.ss_sp = PTROUT(oss.ss_sp); 1892 CP(oss, s32, ss_onstack); 1893 error = copyout(&s32, uap->oss, sizeof(s32)); 1894 } 1895 return (error); 1896 } 1897 #endif 1898 1899 int 1900 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 1901 { 1902 struct timespec32 rmt32, rqt32; 1903 struct timespec rmt, rqt; 1904 int error; 1905 1906 error = copyin(uap->rqtp, &rqt32, sizeof(rqt32)); 1907 if (error) 1908 return (error); 1909 1910 CP(rqt32, rqt, tv_sec); 1911 CP(rqt32, rqt, tv_nsec); 1912 1913 if (uap->rmtp && 1914 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 1915 return (EFAULT); 1916 error = kern_nanosleep(td, &rqt, &rmt); 1917 if (error && uap->rmtp) { 1918 int error2; 1919 1920 CP(rmt, rmt32, tv_sec); 1921 CP(rmt, rmt32, tv_nsec); 1922 1923 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32)); 1924 if (error2) 1925 error = error2; 1926 } 1927 return (error); 1928 } 1929 1930 int 1931 freebsd32_clock_gettime(struct thread *td, 1932 struct freebsd32_clock_gettime_args *uap) 1933 { 1934 struct timespec ats; 1935 struct timespec32 ats32; 1936 int error; 1937 1938 error = kern_clock_gettime(td, uap->clock_id, &ats); 1939 if (error == 0) { 1940 CP(ats, ats32, tv_sec); 1941 CP(ats, ats32, tv_nsec); 1942 error = copyout(&ats32, uap->tp, sizeof(ats32)); 1943 } 1944 return (error); 1945 } 1946 1947 int 1948 freebsd32_clock_settime(struct thread *td, 1949 struct freebsd32_clock_settime_args *uap) 1950 { 1951 struct timespec ats; 1952 struct timespec32 ats32; 1953 int error; 1954 1955 error = copyin(uap->tp, &ats32, sizeof(ats32)); 1956 if (error) 1957 return (error); 1958 CP(ats32, ats, tv_sec); 1959 CP(ats32, ats, tv_nsec); 1960 1961 return (kern_clock_settime(td, uap->clock_id, &ats)); 1962 } 1963 1964 int 1965 freebsd32_clock_getres(struct thread *td, 1966 struct freebsd32_clock_getres_args *uap) 1967 { 1968 struct timespec ts; 1969 struct timespec32 ts32; 1970 int error; 1971 1972 if (uap->tp == NULL) 1973 return (0); 1974 error = kern_clock_getres(td, uap->clock_id, &ts); 1975 if (error == 0) { 1976 CP(ts, ts32, tv_sec); 1977 CP(ts, ts32, tv_nsec); 1978 error = copyout(&ts32, uap->tp, sizeof(ts32)); 1979 } 1980 return (error); 1981 } 1982 1983 #if 0 1984 1985 int 1986 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 1987 { 1988 int error; 1989 struct yyy32 *p32, s32; 1990 struct yyy *p = NULL, s; 1991 1992 if (uap->zzz) { 1993 error = copyin(uap->zzz, &s32, sizeof(s32)); 1994 if (error) 1995 return (error); 1996 /* translate in */ 1997 p = &s; 1998 } 1999 error = kern_xxx(td, p); 2000 if (error) 2001 return (error); 2002 if (uap->zzz) { 2003 /* translate out */ 2004 error = copyout(&s32, p32, sizeof(s32)); 2005 } 2006 return (error); 2007 } 2008 2009 #endif 2010