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