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