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