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