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