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