freebsd32_misc.c revision 170870
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 170870 2007-06-17 04:37:57Z mjacob $"); 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/clock.h> 36#include <sys/exec.h> 37#include <sys/fcntl.h> 38#include <sys/filedesc.h> 39#include <sys/namei.h> 40#include <sys/imgact.h> 41#include <sys/kernel.h> 42#include <sys/limits.h> 43#include <sys/lock.h> 44#include <sys/malloc.h> 45#include <sys/file.h> /* Must come after sys/malloc.h */ 46#include <sys/mbuf.h> 47#include <sys/mman.h> 48#include <sys/module.h> 49#include <sys/mount.h> 50#include <sys/mutex.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/thr.h> 69#include <sys/unistd.h> 70#include <sys/ucontext.h> 71#include <sys/vnode.h> 72#include <sys/wait.h> 73#include <sys/ipc.h> 74#include <sys/shm.h> 75 76#include <vm/vm.h> 77#include <vm/vm_kern.h> 78#include <vm/vm_param.h> 79#include <vm/pmap.h> 80#include <vm/vm_map.h> 81#include <vm/vm_object.h> 82#include <vm/vm_extern.h> 83 84#include <machine/cpu.h> 85 86#include <compat/freebsd32/freebsd32_util.h> 87#include <compat/freebsd32/freebsd32.h> 88#include <compat/freebsd32/freebsd32_signal.h> 89#include <compat/freebsd32/freebsd32_proto.h> 90 91CTASSERT(sizeof(struct timeval32) == 8); 92CTASSERT(sizeof(struct timespec32) == 8); 93CTASSERT(sizeof(struct statfs32) == 256); 94CTASSERT(sizeof(struct rusage32) == 72); 95 96int 97freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 98{ 99 int error, status; 100 struct rusage32 ru32; 101 struct rusage ru, *rup; 102 103 if (uap->rusage != NULL) 104 rup = &ru; 105 else 106 rup = NULL; 107 error = kern_wait(td, uap->pid, &status, uap->options, rup); 108 if (error) 109 return (error); 110 if (uap->status != NULL) 111 error = copyout(&status, uap->status, sizeof(status)); 112 if (uap->rusage != NULL && error == 0) { 113 TV_CP(ru, ru32, ru_utime); 114 TV_CP(ru, ru32, ru_stime); 115 CP(ru, ru32, ru_maxrss); 116 CP(ru, ru32, ru_ixrss); 117 CP(ru, ru32, ru_idrss); 118 CP(ru, ru32, ru_isrss); 119 CP(ru, ru32, ru_minflt); 120 CP(ru, ru32, ru_majflt); 121 CP(ru, ru32, ru_nswap); 122 CP(ru, ru32, ru_inblock); 123 CP(ru, ru32, ru_oublock); 124 CP(ru, ru32, ru_msgsnd); 125 CP(ru, ru32, ru_msgrcv); 126 CP(ru, ru32, ru_nsignals); 127 CP(ru, ru32, ru_nvcsw); 128 CP(ru, ru32, ru_nivcsw); 129 error = copyout(&ru32, uap->rusage, sizeof(ru32)); 130 } 131 return (error); 132} 133 134#ifdef COMPAT_FREEBSD4 135static void 136copy_statfs(struct statfs *in, struct statfs32 *out) 137{ 138 139 bzero(out, sizeof(*out)); 140 CP(*in, *out, f_bsize); 141 CP(*in, *out, f_iosize); 142 CP(*in, *out, f_blocks); 143 CP(*in, *out, f_bfree); 144 CP(*in, *out, f_bavail); 145 CP(*in, *out, f_files); 146 CP(*in, *out, f_ffree); 147 CP(*in, *out, f_fsid); 148 CP(*in, *out, f_owner); 149 CP(*in, *out, f_type); 150 CP(*in, *out, f_flags); 151 CP(*in, *out, f_flags); 152 CP(*in, *out, f_syncwrites); 153 CP(*in, *out, f_asyncwrites); 154 strlcpy(out->f_fstypename, 155 in->f_fstypename, MFSNAMELEN); 156 strlcpy(out->f_mntonname, 157 in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 158 CP(*in, *out, f_syncreads); 159 CP(*in, *out, f_asyncreads); 160 strlcpy(out->f_mntfromname, 161 in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 162} 163#endif 164 165#ifdef COMPAT_FREEBSD4 166int 167freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 168{ 169 struct statfs *buf, *sp; 170 struct statfs32 stat32; 171 size_t count, size; 172 int error; 173 174 count = uap->bufsize / sizeof(struct statfs32); 175 size = count * sizeof(struct statfs); 176 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 177 if (size > 0) { 178 count = td->td_retval[0]; 179 sp = buf; 180 while (count > 0 && error == 0) { 181 copy_statfs(sp, &stat32); 182 error = copyout(&stat32, uap->buf, sizeof(stat32)); 183 sp++; 184 uap->buf++; 185 count--; 186 } 187 free(buf, M_TEMP); 188 } 189 return (error); 190} 191#endif 192 193CTASSERT(sizeof(struct sigaltstack32) == 12); 194 195int 196freebsd32_sigaltstack(struct thread *td, 197 struct freebsd32_sigaltstack_args *uap) 198{ 199 struct sigaltstack32 s32; 200 struct sigaltstack ss, oss, *ssp; 201 int error; 202 203 if (uap->ss != NULL) { 204 error = copyin(uap->ss, &s32, sizeof(s32)); 205 if (error) 206 return (error); 207 PTRIN_CP(s32, ss, ss_sp); 208 CP(s32, ss, ss_size); 209 CP(s32, ss, ss_flags); 210 ssp = &ss; 211 } else 212 ssp = NULL; 213 error = kern_sigaltstack(td, ssp, &oss); 214 if (error == 0 && uap->oss != NULL) { 215 PTROUT_CP(oss, s32, ss_sp); 216 CP(oss, s32, ss_size); 217 CP(oss, s32, ss_flags); 218 error = copyout(&s32, uap->oss, sizeof(s32)); 219 } 220 return (error); 221} 222 223/* 224 * Custom version of exec_copyin_args() so that we can translate 225 * the pointers. 226 */ 227static int 228freebsd32_exec_copyin_args(struct image_args *args, char *fname, 229 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 230{ 231 char *argp, *envp; 232 u_int32_t *p32, arg; 233 size_t length; 234 int error; 235 236 bzero(args, sizeof(*args)); 237 if (argv == NULL) 238 return (EFAULT); 239 240 /* 241 * Allocate temporary demand zeroed space for argument and 242 * environment strings 243 */ 244 args->buf = (char *) kmem_alloc_wait(exec_map, 245 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 246 if (args->buf == NULL) 247 return (ENOMEM); 248 args->begin_argv = args->buf; 249 args->endp = args->begin_argv; 250 args->stringspace = ARG_MAX; 251 252 args->fname = args->buf + ARG_MAX; 253 254 /* 255 * Copy the file name. 256 */ 257 error = (segflg == UIO_SYSSPACE) ? 258 copystr(fname, args->fname, PATH_MAX, &length) : 259 copyinstr(fname, args->fname, PATH_MAX, &length); 260 if (error != 0) 261 goto err_exit; 262 263 /* 264 * extract arguments first 265 */ 266 p32 = argv; 267 for (;;) { 268 error = copyin(p32++, &arg, sizeof(arg)); 269 if (error) 270 goto err_exit; 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 error = E2BIG; 278 goto err_exit; 279 } 280 args->stringspace -= length; 281 args->endp += length; 282 args->argc++; 283 } 284 285 args->begin_envv = args->endp; 286 287 /* 288 * extract environment strings 289 */ 290 if (envv) { 291 p32 = envv; 292 for (;;) { 293 error = copyin(p32++, &arg, sizeof(arg)); 294 if (error) 295 goto err_exit; 296 if (arg == 0) 297 break; 298 envp = PTRIN(arg); 299 error = copyinstr(envp, args->endp, args->stringspace, 300 &length); 301 if (error) { 302 if (error == ENAMETOOLONG) 303 error = E2BIG; 304 goto err_exit; 305 } 306 args->stringspace -= length; 307 args->endp += length; 308 args->envc++; 309 } 310 } 311 312 return (0); 313 314err_exit: 315 kmem_free_wakeup(exec_map, (vm_offset_t)args->buf, 316 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 317 args->buf = NULL; 318 return (error); 319} 320 321int 322freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 323{ 324 struct image_args eargs; 325 int error; 326 327 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 328 uap->argv, uap->envv); 329 if (error == 0) 330 error = kern_execve(td, &eargs, NULL); 331 return (error); 332} 333 334#ifdef __ia64__ 335static int 336freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 337 int prot, int fd, off_t pos) 338{ 339 vm_map_t map; 340 vm_map_entry_t entry; 341 int rv; 342 343 map = &td->td_proc->p_vmspace->vm_map; 344 if (fd != -1) 345 prot |= VM_PROT_WRITE; 346 347 if (vm_map_lookup_entry(map, start, &entry)) { 348 if ((entry->protection & prot) != prot) { 349 rv = vm_map_protect(map, 350 trunc_page(start), 351 round_page(end), 352 entry->protection | prot, 353 FALSE); 354 if (rv != KERN_SUCCESS) 355 return (EINVAL); 356 } 357 } else { 358 vm_offset_t addr = trunc_page(start); 359 rv = vm_map_find(map, 0, 0, 360 &addr, PAGE_SIZE, FALSE, prot, 361 VM_PROT_ALL, 0); 362 if (rv != KERN_SUCCESS) 363 return (EINVAL); 364 } 365 366 if (fd != -1) { 367 struct pread_args r; 368 r.fd = fd; 369 r.buf = (void *) start; 370 r.nbyte = end - start; 371 r.offset = pos; 372 return (pread(td, &r)); 373 } else { 374 while (start < end) { 375 subyte((void *) start, 0); 376 start++; 377 } 378 return (0); 379 } 380} 381#endif 382 383int 384freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 385{ 386 struct mmap_args ap; 387 vm_offset_t addr = (vm_offset_t) uap->addr; 388 vm_size_t len = uap->len; 389 int prot = uap->prot; 390 int flags = uap->flags; 391 int fd = uap->fd; 392 off_t pos = (uap->poslo 393 | ((off_t)uap->poshi << 32)); 394#ifdef __ia64__ 395 vm_size_t pageoff; 396 int error; 397 398 /* 399 * Attempt to handle page size hassles. 400 */ 401 pageoff = (pos & PAGE_MASK); 402 if (flags & MAP_FIXED) { 403 vm_offset_t start, end; 404 start = addr; 405 end = addr + len; 406 407 if (start != trunc_page(start)) { 408 error = freebsd32_mmap_partial(td, start, 409 round_page(start), prot, 410 fd, pos); 411 if (fd != -1) 412 pos += round_page(start) - start; 413 start = round_page(start); 414 } 415 if (end != round_page(end)) { 416 vm_offset_t t = trunc_page(end); 417 error = freebsd32_mmap_partial(td, t, end, 418 prot, fd, 419 pos + t - start); 420 end = trunc_page(end); 421 } 422 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 423 /* 424 * We can't map this region at all. The specified 425 * address doesn't have the same alignment as the file 426 * position. Fake the mapping by simply reading the 427 * entire region into memory. First we need to make 428 * sure the region exists. 429 */ 430 vm_map_t map; 431 struct pread_args r; 432 int rv; 433 434 prot |= VM_PROT_WRITE; 435 map = &td->td_proc->p_vmspace->vm_map; 436 rv = vm_map_remove(map, start, end); 437 if (rv != KERN_SUCCESS) 438 return (EINVAL); 439 rv = vm_map_find(map, 0, 0, 440 &start, end - start, FALSE, 441 prot, VM_PROT_ALL, 0); 442 if (rv != KERN_SUCCESS) 443 return (EINVAL); 444 r.fd = fd; 445 r.buf = (void *) start; 446 r.nbyte = end - start; 447 r.offset = pos; 448 error = pread(td, &r); 449 if (error) 450 return (error); 451 452 td->td_retval[0] = addr; 453 return (0); 454 } 455 if (end == start) { 456 /* 457 * After dealing with the ragged ends, there 458 * might be none left. 459 */ 460 td->td_retval[0] = addr; 461 return (0); 462 } 463 addr = start; 464 len = end - start; 465 } 466#endif 467 468 ap.addr = (void *) addr; 469 ap.len = len; 470 ap.prot = prot; 471 ap.flags = flags; 472 ap.fd = fd; 473 ap.pos = pos; 474 475 return (mmap(td, &ap)); 476} 477 478struct itimerval32 { 479 struct timeval32 it_interval; 480 struct timeval32 it_value; 481}; 482 483CTASSERT(sizeof(struct itimerval32) == 16); 484 485int 486freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 487{ 488 struct itimerval itv, oitv, *itvp; 489 struct itimerval32 i32; 490 int error; 491 492 if (uap->itv != NULL) { 493 error = copyin(uap->itv, &i32, sizeof(i32)); 494 if (error) 495 return (error); 496 TV_CP(i32, itv, it_interval); 497 TV_CP(i32, itv, it_value); 498 itvp = &itv; 499 } else 500 itvp = NULL; 501 error = kern_setitimer(td, uap->which, itvp, &oitv); 502 if (error || uap->oitv == NULL) 503 return (error); 504 TV_CP(oitv, i32, it_interval); 505 TV_CP(oitv, i32, it_value); 506 return (copyout(&i32, uap->oitv, sizeof(i32))); 507} 508 509int 510freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 511{ 512 struct itimerval itv; 513 struct itimerval32 i32; 514 int error; 515 516 error = kern_getitimer(td, uap->which, &itv); 517 if (error || uap->itv == NULL) 518 return (error); 519 TV_CP(itv, i32, it_interval); 520 TV_CP(itv, i32, it_value); 521 return (copyout(&i32, uap->itv, sizeof(i32))); 522} 523 524int 525freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 526{ 527 struct timeval32 tv32; 528 struct timeval tv, *tvp; 529 int error; 530 531 if (uap->tv != NULL) { 532 error = copyin(uap->tv, &tv32, sizeof(tv32)); 533 if (error) 534 return (error); 535 CP(tv32, tv, tv_sec); 536 CP(tv32, tv, tv_usec); 537 tvp = &tv; 538 } else 539 tvp = NULL; 540 /* 541 * XXX big-endian needs to convert the fd_sets too. 542 * XXX Do pointers need PTRIN()? 543 */ 544 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); 545} 546 547struct kevent32 { 548 u_int32_t ident; /* identifier for this event */ 549 short filter; /* filter for event */ 550 u_short flags; 551 u_int fflags; 552 int32_t data; 553 u_int32_t udata; /* opaque user data identifier */ 554}; 555 556CTASSERT(sizeof(struct kevent32) == 20); 557static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 558static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 559 560/* 561 * Copy 'count' items into the destination list pointed to by uap->eventlist. 562 */ 563static int 564freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 565{ 566 struct freebsd32_kevent_args *uap; 567 struct kevent32 ks32[KQ_NEVENTS]; 568 int i, error = 0; 569 570 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 571 uap = (struct freebsd32_kevent_args *)arg; 572 573 for (i = 0; i < count; i++) { 574 CP(kevp[i], ks32[i], ident); 575 CP(kevp[i], ks32[i], filter); 576 CP(kevp[i], ks32[i], flags); 577 CP(kevp[i], ks32[i], fflags); 578 CP(kevp[i], ks32[i], data); 579 PTROUT_CP(kevp[i], ks32[i], udata); 580 } 581 error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 582 if (error == 0) 583 uap->eventlist += count; 584 return (error); 585} 586 587/* 588 * Copy 'count' items from the list pointed to by uap->changelist. 589 */ 590static int 591freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 592{ 593 struct freebsd32_kevent_args *uap; 594 struct kevent32 ks32[KQ_NEVENTS]; 595 int i, error = 0; 596 597 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 598 uap = (struct freebsd32_kevent_args *)arg; 599 600 error = copyin(uap->changelist, ks32, count * sizeof *ks32); 601 if (error) 602 goto done; 603 uap->changelist += count; 604 605 for (i = 0; i < count; i++) { 606 CP(ks32[i], kevp[i], ident); 607 CP(ks32[i], kevp[i], filter); 608 CP(ks32[i], kevp[i], flags); 609 CP(ks32[i], kevp[i], fflags); 610 CP(ks32[i], kevp[i], data); 611 PTRIN_CP(ks32[i], kevp[i], udata); 612 } 613done: 614 return (error); 615} 616 617int 618freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 619{ 620 struct timespec32 ts32; 621 struct timespec ts, *tsp; 622 struct kevent_copyops k_ops = { uap, 623 freebsd32_kevent_copyout, 624 freebsd32_kevent_copyin}; 625 int error; 626 627 628 if (uap->timeout) { 629 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 630 if (error) 631 return (error); 632 CP(ts32, ts, tv_sec); 633 CP(ts32, ts, tv_nsec); 634 tsp = &ts; 635 } else 636 tsp = NULL; 637 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 638 &k_ops, tsp); 639 return (error); 640} 641 642int 643freebsd32_gettimeofday(struct thread *td, 644 struct freebsd32_gettimeofday_args *uap) 645{ 646 struct timeval atv; 647 struct timeval32 atv32; 648 struct timezone rtz; 649 int error = 0; 650 651 if (uap->tp) { 652 microtime(&atv); 653 CP(atv, atv32, tv_sec); 654 CP(atv, atv32, tv_usec); 655 error = copyout(&atv32, uap->tp, sizeof (atv32)); 656 } 657 if (error == 0 && uap->tzp != NULL) { 658 rtz.tz_minuteswest = tz_minuteswest; 659 rtz.tz_dsttime = tz_dsttime; 660 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 661 } 662 return (error); 663} 664 665int 666freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 667{ 668 struct rusage32 s32; 669 struct rusage s; 670 int error; 671 672 error = kern_getrusage(td, uap->who, &s); 673 if (error) 674 return (error); 675 if (uap->rusage != NULL) { 676 TV_CP(s, s32, ru_utime); 677 TV_CP(s, s32, ru_stime); 678 CP(s, s32, ru_maxrss); 679 CP(s, s32, ru_ixrss); 680 CP(s, s32, ru_idrss); 681 CP(s, s32, ru_isrss); 682 CP(s, s32, ru_minflt); 683 CP(s, s32, ru_majflt); 684 CP(s, s32, ru_nswap); 685 CP(s, s32, ru_inblock); 686 CP(s, s32, ru_oublock); 687 CP(s, s32, ru_msgsnd); 688 CP(s, s32, ru_msgrcv); 689 CP(s, s32, ru_nsignals); 690 CP(s, s32, ru_nvcsw); 691 CP(s, s32, ru_nivcsw); 692 error = copyout(&s32, uap->rusage, sizeof(s32)); 693 } 694 return (error); 695} 696 697struct iovec32 { 698 u_int32_t iov_base; 699 int iov_len; 700}; 701 702CTASSERT(sizeof(struct iovec32) == 8); 703 704static int 705freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 706{ 707 struct iovec32 iov32; 708 struct iovec *iov; 709 struct uio *uio; 710 u_int iovlen; 711 int error, i; 712 713 *uiop = NULL; 714 if (iovcnt > UIO_MAXIOV) 715 return (EINVAL); 716 iovlen = iovcnt * sizeof(struct iovec); 717 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 718 iov = (struct iovec *)(uio + 1); 719 for (i = 0; i < iovcnt; i++) { 720 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 721 if (error) { 722 free(uio, M_IOV); 723 return (error); 724 } 725 iov[i].iov_base = PTRIN(iov32.iov_base); 726 iov[i].iov_len = iov32.iov_len; 727 } 728 uio->uio_iov = iov; 729 uio->uio_iovcnt = iovcnt; 730 uio->uio_segflg = UIO_USERSPACE; 731 uio->uio_offset = -1; 732 uio->uio_resid = 0; 733 for (i = 0; i < iovcnt; i++) { 734 if (iov->iov_len > INT_MAX - uio->uio_resid) { 735 free(uio, M_IOV); 736 return (EINVAL); 737 } 738 uio->uio_resid += iov->iov_len; 739 iov++; 740 } 741 *uiop = uio; 742 return (0); 743} 744 745int 746freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 747{ 748 struct uio *auio; 749 int error; 750 751 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 752 if (error) 753 return (error); 754 error = kern_readv(td, uap->fd, auio); 755 free(auio, M_IOV); 756 return (error); 757} 758 759int 760freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 761{ 762 struct uio *auio; 763 int error; 764 765 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 766 if (error) 767 return (error); 768 error = kern_writev(td, uap->fd, auio); 769 free(auio, M_IOV); 770 return (error); 771} 772 773int 774freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap) 775{ 776 struct uio *auio; 777 int error; 778 779 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 780 if (error) 781 return (error); 782 error = kern_preadv(td, uap->fd, auio, uap->offset); 783 free(auio, M_IOV); 784 return (error); 785} 786 787int 788freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) 789{ 790 struct uio *auio; 791 int error; 792 793 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 794 if (error) 795 return (error); 796 error = kern_pwritev(td, uap->fd, auio, uap->offset); 797 free(auio, M_IOV); 798 return (error); 799} 800 801static int 802freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp, 803 int error) 804{ 805 struct iovec32 iov32; 806 struct iovec *iov; 807 u_int iovlen; 808 int i; 809 810 *iovp = NULL; 811 if (iovcnt > UIO_MAXIOV) 812 return (error); 813 iovlen = iovcnt * sizeof(struct iovec); 814 iov = malloc(iovlen, M_IOV, M_WAITOK); 815 for (i = 0; i < iovcnt; i++) { 816 error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32)); 817 if (error) { 818 free(iov, M_IOV); 819 return (error); 820 } 821 iov[i].iov_base = PTRIN(iov32.iov_base); 822 iov[i].iov_len = iov32.iov_len; 823 } 824 *iovp = iov; 825 return (0); 826} 827 828struct msghdr32 { 829 u_int32_t msg_name; 830 socklen_t msg_namelen; 831 u_int32_t msg_iov; 832 int msg_iovlen; 833 u_int32_t msg_control; 834 socklen_t msg_controllen; 835 int msg_flags; 836}; 837CTASSERT(sizeof(struct msghdr32) == 28); 838 839static int 840freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg) 841{ 842 struct msghdr32 m32; 843 int error; 844 845 error = copyin(msg32, &m32, sizeof(m32)); 846 if (error) 847 return (error); 848 msg->msg_name = PTRIN(m32.msg_name); 849 msg->msg_namelen = m32.msg_namelen; 850 msg->msg_iov = PTRIN(m32.msg_iov); 851 msg->msg_iovlen = m32.msg_iovlen; 852 msg->msg_control = PTRIN(m32.msg_control); 853 msg->msg_controllen = m32.msg_controllen; 854 msg->msg_flags = m32.msg_flags; 855 return (0); 856} 857 858static int 859freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32) 860{ 861 struct msghdr32 m32; 862 int error; 863 864 m32.msg_name = PTROUT(msg->msg_name); 865 m32.msg_namelen = msg->msg_namelen; 866 m32.msg_iov = PTROUT(msg->msg_iov); 867 m32.msg_iovlen = msg->msg_iovlen; 868 m32.msg_control = PTROUT(msg->msg_control); 869 m32.msg_controllen = msg->msg_controllen; 870 m32.msg_flags = msg->msg_flags; 871 error = copyout(&m32, msg32, sizeof(m32)); 872 return (error); 873} 874 875#define FREEBSD32_ALIGNBYTES (sizeof(int) - 1) 876#define FREEBSD32_ALIGN(p) \ 877 (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES) 878#define FREEBSD32_CMSG_SPACE(l) \ 879 (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l)) 880 881#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ 882 FREEBSD32_ALIGN(sizeof(struct cmsghdr))) 883static int 884freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) 885{ 886 struct cmsghdr *cm; 887 void *data; 888 socklen_t clen, datalen; 889 int error; 890 caddr_t ctlbuf; 891 int len, maxlen, copylen; 892 struct mbuf *m; 893 error = 0; 894 895 len = msg->msg_controllen; 896 maxlen = msg->msg_controllen; 897 msg->msg_controllen = 0; 898 899 m = control; 900 ctlbuf = msg->msg_control; 901 902 while (m && len > 0) { 903 cm = mtod(m, struct cmsghdr *); 904 clen = m->m_len; 905 906 while (cm != NULL) { 907 908 if (sizeof(struct cmsghdr) > clen || 909 cm->cmsg_len > clen) { 910 error = EINVAL; 911 break; 912 } 913 914 data = CMSG_DATA(cm); 915 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 916 917 /* Adjust message length */ 918 cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + 919 datalen; 920 921 922 /* Copy cmsghdr */ 923 copylen = sizeof(struct cmsghdr); 924 if (len < copylen) { 925 msg->msg_flags |= MSG_CTRUNC; 926 copylen = len; 927 } 928 929 error = copyout(cm,ctlbuf,copylen); 930 if (error) 931 goto exit; 932 933 ctlbuf += FREEBSD32_ALIGN(copylen); 934 len -= FREEBSD32_ALIGN(copylen); 935 936 if (len <= 0) 937 break; 938 939 /* Copy data */ 940 copylen = datalen; 941 if (len < copylen) { 942 msg->msg_flags |= MSG_CTRUNC; 943 copylen = len; 944 } 945 946 error = copyout(data,ctlbuf,copylen); 947 if (error) 948 goto exit; 949 950 ctlbuf += FREEBSD32_ALIGN(copylen); 951 len -= FREEBSD32_ALIGN(copylen); 952 953 if (CMSG_SPACE(datalen) < clen) { 954 clen -= CMSG_SPACE(datalen); 955 cm = (struct cmsghdr *) 956 ((caddr_t)cm + CMSG_SPACE(datalen)); 957 } else { 958 clen = 0; 959 cm = NULL; 960 } 961 } 962 m = m->m_next; 963 } 964 965 msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control; 966 967exit: 968 return (error); 969 970} 971 972int 973freebsd32_recvmsg(td, uap) 974 struct thread *td; 975 struct freebsd32_recvmsg_args /* { 976 int s; 977 struct msghdr32 *msg; 978 int flags; 979 } */ *uap; 980{ 981 struct msghdr msg; 982 struct msghdr32 m32; 983 struct iovec *uiov, *iov; 984 struct mbuf *control = NULL; 985 struct mbuf **controlp; 986 987 int error; 988 error = copyin(uap->msg, &m32, sizeof(m32)); 989 if (error) 990 return (error); 991 error = freebsd32_copyinmsghdr(uap->msg, &msg); 992 if (error) 993 return (error); 994 error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov, 995 EMSGSIZE); 996 if (error) 997 return (error); 998 msg.msg_flags = uap->flags; 999 uiov = msg.msg_iov; 1000 msg.msg_iov = iov; 1001 1002 controlp = (msg.msg_control != NULL) ? &control : NULL; 1003 error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp); 1004 if (error == 0) { 1005 msg.msg_iov = uiov; 1006 1007 if (control != NULL) 1008 error = freebsd32_copy_msg_out(&msg, control); 1009 1010 if (error == 0) 1011 error = freebsd32_copyoutmsghdr(&msg, uap->msg); 1012 } 1013 free(iov, M_IOV); 1014 1015 if (control != NULL) 1016 m_freem(control); 1017 1018 return (error); 1019} 1020 1021 1022static int 1023freebsd32_convert_msg_in(struct mbuf **controlp) 1024{ 1025 struct mbuf *control = *controlp; 1026 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 1027 void *data; 1028 socklen_t clen = control->m_len, datalen; 1029 int error; 1030 1031 error = 0; 1032 *controlp = NULL; 1033 1034 while (cm != NULL) { 1035 if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) { 1036 error = EINVAL; 1037 break; 1038 } 1039 1040 data = FREEBSD32_CMSG_DATA(cm); 1041 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1042 1043 *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type, 1044 cm->cmsg_level); 1045 controlp = &(*controlp)->m_next; 1046 1047 if (FREEBSD32_CMSG_SPACE(datalen) < clen) { 1048 clen -= FREEBSD32_CMSG_SPACE(datalen); 1049 cm = (struct cmsghdr *) 1050 ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen)); 1051 } else { 1052 clen = 0; 1053 cm = NULL; 1054 } 1055 } 1056 1057 m_freem(control); 1058 return (error); 1059} 1060 1061 1062int 1063freebsd32_sendmsg(struct thread *td, 1064 struct freebsd32_sendmsg_args *uap) 1065{ 1066 struct msghdr msg; 1067 struct msghdr32 m32; 1068 struct iovec *iov; 1069 struct mbuf *control = NULL; 1070 struct sockaddr *to = NULL; 1071 int error; 1072 1073 error = copyin(uap->msg, &m32, sizeof(m32)); 1074 if (error) 1075 return (error); 1076 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1077 if (error) 1078 return (error); 1079 error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov, 1080 EMSGSIZE); 1081 if (error) 1082 return (error); 1083 msg.msg_iov = iov; 1084 if (msg.msg_name != NULL) { 1085 error = getsockaddr(&to, msg.msg_name, msg.msg_namelen); 1086 if (error) { 1087 to = NULL; 1088 goto out; 1089 } 1090 msg.msg_name = to; 1091 } 1092 1093 if (msg.msg_control) { 1094 if (msg.msg_controllen < sizeof(struct cmsghdr)) { 1095 error = EINVAL; 1096 goto out; 1097 } 1098 1099 error = sockargs(&control, msg.msg_control, 1100 msg.msg_controllen, MT_CONTROL); 1101 if (error) 1102 goto out; 1103 1104 error = freebsd32_convert_msg_in(&control); 1105 if (error) 1106 goto out; 1107 } 1108 1109 error = kern_sendit(td, uap->s, &msg, uap->flags, control, 1110 UIO_USERSPACE); 1111 1112out: 1113 free(iov, M_IOV); 1114 if (to) 1115 free(to, M_SONAME); 1116 return (error); 1117} 1118 1119int 1120freebsd32_recvfrom(struct thread *td, 1121 struct freebsd32_recvfrom_args *uap) 1122{ 1123 struct msghdr msg; 1124 struct iovec aiov; 1125 int error; 1126 1127 if (uap->fromlenaddr) { 1128 error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen, 1129 sizeof(msg.msg_namelen)); 1130 if (error) 1131 return (error); 1132 } else { 1133 msg.msg_namelen = 0; 1134 } 1135 1136 msg.msg_name = PTRIN(uap->from); 1137 msg.msg_iov = &aiov; 1138 msg.msg_iovlen = 1; 1139 aiov.iov_base = PTRIN(uap->buf); 1140 aiov.iov_len = uap->len; 1141 msg.msg_control = NULL; 1142 msg.msg_flags = uap->flags; 1143 error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL); 1144 if (error == 0 && uap->fromlenaddr) 1145 error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr), 1146 sizeof (msg.msg_namelen)); 1147 return (error); 1148} 1149 1150int 1151freebsd32_settimeofday(struct thread *td, 1152 struct freebsd32_settimeofday_args *uap) 1153{ 1154 struct timeval32 tv32; 1155 struct timeval tv, *tvp; 1156 struct timezone tz, *tzp; 1157 int error; 1158 1159 if (uap->tv) { 1160 error = copyin(uap->tv, &tv32, sizeof(tv32)); 1161 if (error) 1162 return (error); 1163 CP(tv32, tv, tv_sec); 1164 CP(tv32, tv, tv_usec); 1165 tvp = &tv; 1166 } else 1167 tvp = NULL; 1168 if (uap->tzp) { 1169 error = copyin(uap->tzp, &tz, sizeof(tz)); 1170 if (error) 1171 return (error); 1172 tzp = &tz; 1173 } else 1174 tzp = NULL; 1175 return (kern_settimeofday(td, tvp, tzp)); 1176} 1177 1178int 1179freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 1180{ 1181 struct timeval32 s32[2]; 1182 struct timeval s[2], *sp; 1183 int error; 1184 1185 if (uap->tptr != NULL) { 1186 error = copyin(uap->tptr, s32, sizeof(s32)); 1187 if (error) 1188 return (error); 1189 CP(s32[0], s[0], tv_sec); 1190 CP(s32[0], s[0], tv_usec); 1191 CP(s32[1], s[1], tv_sec); 1192 CP(s32[1], s[1], tv_usec); 1193 sp = s; 1194 } else 1195 sp = NULL; 1196 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1197} 1198 1199int 1200freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap) 1201{ 1202 struct timeval32 s32[2]; 1203 struct timeval s[2], *sp; 1204 int error; 1205 1206 if (uap->tptr != NULL) { 1207 error = copyin(uap->tptr, s32, sizeof(s32)); 1208 if (error) 1209 return (error); 1210 CP(s32[0], s[0], tv_sec); 1211 CP(s32[0], s[0], tv_usec); 1212 CP(s32[1], s[1], tv_sec); 1213 CP(s32[1], s[1], tv_usec); 1214 sp = s; 1215 } else 1216 sp = NULL; 1217 return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1218} 1219 1220int 1221freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap) 1222{ 1223 struct timeval32 s32[2]; 1224 struct timeval s[2], *sp; 1225 int error; 1226 1227 if (uap->tptr != NULL) { 1228 error = copyin(uap->tptr, s32, sizeof(s32)); 1229 if (error) 1230 return (error); 1231 CP(s32[0], s[0], tv_sec); 1232 CP(s32[0], s[0], tv_usec); 1233 CP(s32[1], s[1], tv_sec); 1234 CP(s32[1], s[1], tv_usec); 1235 sp = s; 1236 } else 1237 sp = NULL; 1238 return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE)); 1239} 1240 1241 1242int 1243freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 1244{ 1245 struct timeval32 tv32; 1246 struct timeval delta, olddelta, *deltap; 1247 int error; 1248 1249 if (uap->delta) { 1250 error = copyin(uap->delta, &tv32, sizeof(tv32)); 1251 if (error) 1252 return (error); 1253 CP(tv32, delta, tv_sec); 1254 CP(tv32, delta, tv_usec); 1255 deltap = δ 1256 } else 1257 deltap = NULL; 1258 error = kern_adjtime(td, deltap, &olddelta); 1259 if (uap->olddelta && error == 0) { 1260 CP(olddelta, tv32, tv_sec); 1261 CP(olddelta, tv32, tv_usec); 1262 error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 1263 } 1264 return (error); 1265} 1266 1267#ifdef COMPAT_FREEBSD4 1268int 1269freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 1270{ 1271 struct statfs32 s32; 1272 struct statfs s; 1273 int error; 1274 1275 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 1276 if (error) 1277 return (error); 1278 copy_statfs(&s, &s32); 1279 return (copyout(&s32, uap->buf, sizeof(s32))); 1280} 1281#endif 1282 1283#ifdef COMPAT_FREEBSD4 1284int 1285freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 1286{ 1287 struct statfs32 s32; 1288 struct statfs s; 1289 int error; 1290 1291 error = kern_fstatfs(td, uap->fd, &s); 1292 if (error) 1293 return (error); 1294 copy_statfs(&s, &s32); 1295 return (copyout(&s32, uap->buf, sizeof(s32))); 1296} 1297#endif 1298 1299#ifdef COMPAT_FREEBSD4 1300int 1301freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 1302{ 1303 struct statfs32 s32; 1304 struct statfs s; 1305 fhandle_t fh; 1306 int error; 1307 1308 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 1309 return (error); 1310 error = kern_fhstatfs(td, fh, &s); 1311 if (error) 1312 return (error); 1313 copy_statfs(&s, &s32); 1314 return (copyout(&s32, uap->buf, sizeof(s32))); 1315} 1316#endif 1317 1318int 1319freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1320{ 1321 /* 1322 * Vector through to semsys if it is loaded. 1323 */ 1324 return sysent[SYS_semsys].sy_call(td, uap); 1325} 1326 1327int 1328freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1329{ 1330 switch (uap->which) { 1331 case 2: 1332 return (freebsd32_msgsnd(td, 1333 (struct freebsd32_msgsnd_args *)&uap->a2)); 1334 break; 1335 case 3: 1336 return (freebsd32_msgrcv(td, 1337 (struct freebsd32_msgrcv_args *)&uap->a2)); 1338 break; 1339 default: 1340 /* 1341 * Vector through to msgsys if it is loaded. 1342 */ 1343 return (sysent[SYS_msgsys].sy_call(td, uap)); 1344 break; 1345 } 1346} 1347 1348int 1349freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap) 1350{ 1351 const void *msgp; 1352 long mtype; 1353 int32_t mtype32; 1354 int error; 1355 1356 if (!SYSCALL_MODULE_PRESENT(msgsnd)) 1357 return (nosys(td, (struct nosys_args *)uap)); 1358 1359 msgp = PTRIN(uap->msgp); 1360 if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0) 1361 return (error); 1362 mtype = mtype32; 1363 return (kern_msgsnd(td, uap->msqid, 1364 (const char *)msgp + sizeof(mtype32), 1365 uap->msgsz, uap->msgflg, mtype)); 1366} 1367 1368int 1369freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap) 1370{ 1371 void *msgp; 1372 long mtype; 1373 int32_t mtype32; 1374 int error; 1375 1376 if (!SYSCALL_MODULE_PRESENT(msgrcv)) 1377 return (nosys(td, (struct nosys_args *)uap)); 1378 1379 msgp = PTRIN(uap->msgp); 1380 if ((error = kern_msgrcv(td, uap->msqid, 1381 (char *)msgp + sizeof(mtype32), uap->msgsz, 1382 uap->msgtyp, uap->msgflg, &mtype)) != 0) 1383 return (error); 1384 mtype32 = (int32_t)mtype; 1385 return (copyout(&mtype32, msgp, sizeof(mtype32))); 1386} 1387 1388int 1389freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1390{ 1391 1392 switch (uap->which) { 1393 case 0: { /* shmat */ 1394 struct shmat_args ap; 1395 1396 ap.shmid = uap->a2; 1397 ap.shmaddr = PTRIN(uap->a3); 1398 ap.shmflg = uap->a4; 1399 return (sysent[SYS_shmat].sy_call(td, &ap)); 1400 } 1401 case 2: { /* shmdt */ 1402 struct shmdt_args ap; 1403 1404 ap.shmaddr = PTRIN(uap->a2); 1405 return (sysent[SYS_shmdt].sy_call(td, &ap)); 1406 } 1407 case 3: { /* shmget */ 1408 struct shmget_args ap; 1409 1410 ap.key = uap->a2; 1411 ap.size = uap->a3; 1412 ap.shmflg = uap->a4; 1413 return (sysent[SYS_shmget].sy_call(td, &ap)); 1414 } 1415 case 4: { /* shmctl */ 1416 struct freebsd32_shmctl_args ap; 1417 1418 ap.shmid = uap->a2; 1419 ap.cmd = uap->a3; 1420 ap.buf = PTRIN(uap->a4); 1421 return (freebsd32_shmctl(td, &ap)); 1422 } 1423 case 1: /* oshmctl */ 1424 default: 1425 return (EINVAL); 1426 } 1427} 1428 1429struct ipc_perm32 { 1430 uint16_t cuid; 1431 uint16_t cgid; 1432 uint16_t uid; 1433 uint16_t gid; 1434 uint16_t mode; 1435 uint16_t seq; 1436 uint32_t key; 1437}; 1438struct shmid_ds32 { 1439 struct ipc_perm32 shm_perm; 1440 int32_t shm_segsz; 1441 int32_t shm_lpid; 1442 int32_t shm_cpid; 1443 int16_t shm_nattch; 1444 int32_t shm_atime; 1445 int32_t shm_dtime; 1446 int32_t shm_ctime; 1447 uint32_t shm_internal; 1448}; 1449struct shm_info32 { 1450 int32_t used_ids; 1451 uint32_t shm_tot; 1452 uint32_t shm_rss; 1453 uint32_t shm_swp; 1454 uint32_t swap_attempts; 1455 uint32_t swap_successes; 1456}; 1457struct shminfo32 { 1458 uint32_t shmmax; 1459 uint32_t shmmin; 1460 uint32_t shmmni; 1461 uint32_t shmseg; 1462 uint32_t shmall; 1463}; 1464 1465int 1466freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap) 1467{ 1468 int error = 0; 1469 union { 1470 struct shmid_ds shmid_ds; 1471 struct shm_info shm_info; 1472 struct shminfo shminfo; 1473 } u; 1474 union { 1475 struct shmid_ds32 shmid_ds32; 1476 struct shm_info32 shm_info32; 1477 struct shminfo32 shminfo32; 1478 } u32; 1479 size_t sz; 1480 1481 if (uap->cmd == IPC_SET) { 1482 if ((error = copyin(uap->buf, &u32.shmid_ds32, 1483 sizeof(u32.shmid_ds32)))) 1484 goto done; 1485 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid); 1486 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid); 1487 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid); 1488 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid); 1489 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode); 1490 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq); 1491 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key); 1492 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz); 1493 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid); 1494 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid); 1495 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch); 1496 CP(u32.shmid_ds32, u.shmid_ds, shm_atime); 1497 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime); 1498 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime); 1499 PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal); 1500 } 1501 1502 error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz); 1503 if (error) 1504 goto done; 1505 1506 /* Cases in which we need to copyout */ 1507 switch (uap->cmd) { 1508 case IPC_INFO: 1509 CP(u.shminfo, u32.shminfo32, shmmax); 1510 CP(u.shminfo, u32.shminfo32, shmmin); 1511 CP(u.shminfo, u32.shminfo32, shmmni); 1512 CP(u.shminfo, u32.shminfo32, shmseg); 1513 CP(u.shminfo, u32.shminfo32, shmall); 1514 error = copyout(&u32.shminfo32, uap->buf, 1515 sizeof(u32.shminfo32)); 1516 break; 1517 case SHM_INFO: 1518 CP(u.shm_info, u32.shm_info32, used_ids); 1519 CP(u.shm_info, u32.shm_info32, shm_rss); 1520 CP(u.shm_info, u32.shm_info32, shm_tot); 1521 CP(u.shm_info, u32.shm_info32, shm_swp); 1522 CP(u.shm_info, u32.shm_info32, swap_attempts); 1523 CP(u.shm_info, u32.shm_info32, swap_successes); 1524 error = copyout(&u32.shm_info32, uap->buf, 1525 sizeof(u32.shm_info32)); 1526 break; 1527 case SHM_STAT: 1528 case IPC_STAT: 1529 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid); 1530 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid); 1531 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid); 1532 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid); 1533 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode); 1534 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq); 1535 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key); 1536 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); 1537 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid); 1538 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid); 1539 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch); 1540 CP(u.shmid_ds, u32.shmid_ds32, shm_atime); 1541 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime); 1542 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime); 1543 PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal); 1544 error = copyout(&u32.shmid_ds32, uap->buf, 1545 sizeof(u32.shmid_ds32)); 1546 break; 1547 } 1548 1549done: 1550 if (error) { 1551 /* Invalidate the return value */ 1552 td->td_retval[0] = -1; 1553 } 1554 return (error); 1555} 1556 1557int 1558freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1559{ 1560 struct pread_args ap; 1561 1562 ap.fd = uap->fd; 1563 ap.buf = uap->buf; 1564 ap.nbyte = uap->nbyte; 1565 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1566 return (pread(td, &ap)); 1567} 1568 1569int 1570freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1571{ 1572 struct pwrite_args ap; 1573 1574 ap.fd = uap->fd; 1575 ap.buf = uap->buf; 1576 ap.nbyte = uap->nbyte; 1577 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1578 return (pwrite(td, &ap)); 1579} 1580 1581int 1582freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1583{ 1584 int error; 1585 struct lseek_args ap; 1586 off_t pos; 1587 1588 ap.fd = uap->fd; 1589 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1590 ap.whence = uap->whence; 1591 error = lseek(td, &ap); 1592 /* Expand the quad return into two parts for eax and edx */ 1593 pos = *(off_t *)(td->td_retval); 1594 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1595 td->td_retval[1] = pos >> 32; /* %edx */ 1596 return error; 1597} 1598 1599int 1600freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1601{ 1602 struct truncate_args ap; 1603 1604 ap.path = uap->path; 1605 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1606 return (truncate(td, &ap)); 1607} 1608 1609int 1610freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1611{ 1612 struct ftruncate_args ap; 1613 1614 ap.fd = uap->fd; 1615 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1616 return (ftruncate(td, &ap)); 1617} 1618 1619struct sf_hdtr32 { 1620 uint32_t headers; 1621 int hdr_cnt; 1622 uint32_t trailers; 1623 int trl_cnt; 1624}; 1625 1626static int 1627freebsd32_do_sendfile(struct thread *td, 1628 struct freebsd32_sendfile_args *uap, int compat) 1629{ 1630 struct sendfile_args ap; 1631 struct sf_hdtr32 hdtr32; 1632 struct sf_hdtr hdtr; 1633 struct uio *hdr_uio, *trl_uio; 1634 struct iovec32 *iov32; 1635 int error; 1636 1637 hdr_uio = trl_uio = NULL; 1638 1639 ap.fd = uap->fd; 1640 ap.s = uap->s; 1641 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1642 ap.nbytes = uap->nbytes; 1643 ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */ 1644 ap.sbytes = uap->sbytes; 1645 ap.flags = uap->flags; 1646 1647 if (uap->hdtr != NULL) { 1648 error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32)); 1649 if (error) 1650 goto out; 1651 PTRIN_CP(hdtr32, hdtr, headers); 1652 CP(hdtr32, hdtr, hdr_cnt); 1653 PTRIN_CP(hdtr32, hdtr, trailers); 1654 CP(hdtr32, hdtr, trl_cnt); 1655 1656 if (hdtr.headers != NULL) { 1657 iov32 = PTRIN(hdtr32.headers); 1658 error = freebsd32_copyinuio(iov32, 1659 hdtr32.hdr_cnt, &hdr_uio); 1660 if (error) 1661 goto out; 1662 } 1663 if (hdtr.trailers != NULL) { 1664 iov32 = PTRIN(hdtr32.trailers); 1665 error = freebsd32_copyinuio(iov32, 1666 hdtr32.trl_cnt, &trl_uio); 1667 if (error) 1668 goto out; 1669 } 1670 } 1671 1672 error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat); 1673out: 1674 if (hdr_uio) 1675 free(hdr_uio, M_IOV); 1676 if (trl_uio) 1677 free(trl_uio, M_IOV); 1678 return (error); 1679} 1680 1681#ifdef COMPAT_FREEBSD4 1682int 1683freebsd4_freebsd32_sendfile(struct thread *td, 1684 struct freebsd4_freebsd32_sendfile_args *uap) 1685{ 1686 return (freebsd32_do_sendfile(td, 1687 (struct freebsd32_sendfile_args *)uap, 1)); 1688} 1689#endif 1690 1691int 1692freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1693{ 1694 1695 return (freebsd32_do_sendfile(td, uap, 0)); 1696} 1697 1698struct stat32 { 1699 dev_t st_dev; 1700 ino_t st_ino; 1701 mode_t st_mode; 1702 nlink_t st_nlink; 1703 uid_t st_uid; 1704 gid_t st_gid; 1705 dev_t st_rdev; 1706 struct timespec32 st_atimespec; 1707 struct timespec32 st_mtimespec; 1708 struct timespec32 st_ctimespec; 1709 off_t st_size; 1710 int64_t st_blocks; 1711 u_int32_t st_blksize; 1712 u_int32_t st_flags; 1713 u_int32_t st_gen; 1714 struct timespec32 st_birthtimespec; 1715 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1716 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1717}; 1718 1719 1720CTASSERT(sizeof(struct stat32) == 96); 1721 1722static void 1723copy_stat( struct stat *in, struct stat32 *out) 1724{ 1725 CP(*in, *out, st_dev); 1726 CP(*in, *out, st_ino); 1727 CP(*in, *out, st_mode); 1728 CP(*in, *out, st_nlink); 1729 CP(*in, *out, st_uid); 1730 CP(*in, *out, st_gid); 1731 CP(*in, *out, st_rdev); 1732 TS_CP(*in, *out, st_atimespec); 1733 TS_CP(*in, *out, st_mtimespec); 1734 TS_CP(*in, *out, st_ctimespec); 1735 CP(*in, *out, st_size); 1736 CP(*in, *out, st_blocks); 1737 CP(*in, *out, st_blksize); 1738 CP(*in, *out, st_flags); 1739 CP(*in, *out, st_gen); 1740} 1741 1742int 1743freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1744{ 1745 struct stat sb; 1746 struct stat32 sb32; 1747 int error; 1748 1749 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1750 if (error) 1751 return (error); 1752 copy_stat(&sb, &sb32); 1753 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1754 return (error); 1755} 1756 1757int 1758freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1759{ 1760 struct stat ub; 1761 struct stat32 ub32; 1762 int error; 1763 1764 error = kern_fstat(td, uap->fd, &ub); 1765 if (error) 1766 return (error); 1767 copy_stat(&ub, &ub32); 1768 error = copyout(&ub32, uap->ub, sizeof(ub32)); 1769 return (error); 1770} 1771 1772int 1773freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1774{ 1775 struct stat sb; 1776 struct stat32 sb32; 1777 int error; 1778 1779 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1780 if (error) 1781 return (error); 1782 copy_stat(&sb, &sb32); 1783 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1784 return (error); 1785} 1786 1787/* 1788 * MPSAFE 1789 */ 1790int 1791freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1792{ 1793 int error, name[CTL_MAXNAME]; 1794 size_t j, oldlen; 1795 1796 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1797 return (EINVAL); 1798 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 1799 if (error) 1800 return (error); 1801 mtx_lock(&Giant); 1802 if (uap->oldlenp) 1803 oldlen = fuword32(uap->oldlenp); 1804 else 1805 oldlen = 0; 1806 error = userland_sysctl(td, name, uap->namelen, 1807 uap->old, &oldlen, 1, 1808 uap->new, uap->newlen, &j, SCTL_MASK32); 1809 if (error && error != ENOMEM) 1810 goto done2; 1811 if (uap->oldlenp) 1812 suword32(uap->oldlenp, j); 1813done2: 1814 mtx_unlock(&Giant); 1815 return (error); 1816} 1817 1818struct sigaction32 { 1819 u_int32_t sa_u; 1820 int sa_flags; 1821 sigset_t sa_mask; 1822}; 1823 1824CTASSERT(sizeof(struct sigaction32) == 24); 1825 1826int 1827freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1828{ 1829 struct sigaction32 s32; 1830 struct sigaction sa, osa, *sap; 1831 int error; 1832 1833 if (uap->act) { 1834 error = copyin(uap->act, &s32, sizeof(s32)); 1835 if (error) 1836 return (error); 1837 sa.sa_handler = PTRIN(s32.sa_u); 1838 CP(s32, sa, sa_flags); 1839 CP(s32, sa, sa_mask); 1840 sap = &sa; 1841 } else 1842 sap = NULL; 1843 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1844 if (error == 0 && uap->oact != NULL) { 1845 s32.sa_u = PTROUT(osa.sa_handler); 1846 CP(osa, s32, sa_flags); 1847 CP(osa, s32, sa_mask); 1848 error = copyout(&s32, uap->oact, sizeof(s32)); 1849 } 1850 return (error); 1851} 1852 1853#ifdef COMPAT_FREEBSD4 1854int 1855freebsd4_freebsd32_sigaction(struct thread *td, 1856 struct freebsd4_freebsd32_sigaction_args *uap) 1857{ 1858 struct sigaction32 s32; 1859 struct sigaction sa, osa, *sap; 1860 int error; 1861 1862 if (uap->act) { 1863 error = copyin(uap->act, &s32, sizeof(s32)); 1864 if (error) 1865 return (error); 1866 sa.sa_handler = PTRIN(s32.sa_u); 1867 CP(s32, sa, sa_flags); 1868 CP(s32, sa, sa_mask); 1869 sap = &sa; 1870 } else 1871 sap = NULL; 1872 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1873 if (error == 0 && uap->oact != NULL) { 1874 s32.sa_u = PTROUT(osa.sa_handler); 1875 CP(osa, s32, sa_flags); 1876 CP(osa, s32, sa_mask); 1877 error = copyout(&s32, uap->oact, sizeof(s32)); 1878 } 1879 return (error); 1880} 1881#endif 1882 1883#ifdef COMPAT_43 1884struct osigaction32 { 1885 u_int32_t sa_u; 1886 osigset_t sa_mask; 1887 int sa_flags; 1888}; 1889 1890#define ONSIG 32 1891 1892int 1893ofreebsd32_sigaction(struct thread *td, 1894 struct ofreebsd32_sigaction_args *uap) 1895{ 1896 struct osigaction32 s32; 1897 struct sigaction sa, osa, *sap; 1898 int error; 1899 1900 if (uap->signum <= 0 || uap->signum >= ONSIG) 1901 return (EINVAL); 1902 1903 if (uap->nsa) { 1904 error = copyin(uap->nsa, &s32, sizeof(s32)); 1905 if (error) 1906 return (error); 1907 sa.sa_handler = PTRIN(s32.sa_u); 1908 CP(s32, sa, sa_flags); 1909 OSIG2SIG(s32.sa_mask, sa.sa_mask); 1910 sap = &sa; 1911 } else 1912 sap = NULL; 1913 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1914 if (error == 0 && uap->osa != NULL) { 1915 s32.sa_u = PTROUT(osa.sa_handler); 1916 CP(osa, s32, sa_flags); 1917 SIG2OSIG(osa.sa_mask, s32.sa_mask); 1918 error = copyout(&s32, uap->osa, sizeof(s32)); 1919 } 1920 return (error); 1921} 1922 1923int 1924ofreebsd32_sigprocmask(struct thread *td, 1925 struct ofreebsd32_sigprocmask_args *uap) 1926{ 1927 sigset_t set, oset; 1928 int error; 1929 1930 OSIG2SIG(uap->mask, set); 1931 error = kern_sigprocmask(td, uap->how, &set, &oset, 1); 1932 SIG2OSIG(oset, td->td_retval[0]); 1933 return (error); 1934} 1935 1936int 1937ofreebsd32_sigpending(struct thread *td, 1938 struct ofreebsd32_sigpending_args *uap) 1939{ 1940 struct proc *p = td->td_proc; 1941 sigset_t siglist; 1942 1943 PROC_LOCK(p); 1944 siglist = p->p_siglist; 1945 SIGSETOR(siglist, td->td_siglist); 1946 PROC_UNLOCK(p); 1947 SIG2OSIG(siglist, td->td_retval[0]); 1948 return (0); 1949} 1950 1951struct sigvec32 { 1952 u_int32_t sv_handler; 1953 int sv_mask; 1954 int sv_flags; 1955}; 1956 1957int 1958ofreebsd32_sigvec(struct thread *td, 1959 struct ofreebsd32_sigvec_args *uap) 1960{ 1961 struct sigvec32 vec; 1962 struct sigaction sa, osa, *sap; 1963 int error; 1964 1965 if (uap->signum <= 0 || uap->signum >= ONSIG) 1966 return (EINVAL); 1967 1968 if (uap->nsv) { 1969 error = copyin(uap->nsv, &vec, sizeof(vec)); 1970 if (error) 1971 return (error); 1972 sa.sa_handler = PTRIN(vec.sv_handler); 1973 OSIG2SIG(vec.sv_mask, sa.sa_mask); 1974 sa.sa_flags = vec.sv_flags; 1975 sa.sa_flags ^= SA_RESTART; 1976 sap = &sa; 1977 } else 1978 sap = NULL; 1979 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1980 if (error == 0 && uap->osv != NULL) { 1981 vec.sv_handler = PTROUT(osa.sa_handler); 1982 SIG2OSIG(osa.sa_mask, vec.sv_mask); 1983 vec.sv_flags = osa.sa_flags; 1984 vec.sv_flags &= ~SA_NOCLDWAIT; 1985 vec.sv_flags ^= SA_RESTART; 1986 error = copyout(&vec, uap->osv, sizeof(vec)); 1987 } 1988 return (error); 1989} 1990 1991int 1992ofreebsd32_sigblock(struct thread *td, 1993 struct ofreebsd32_sigblock_args *uap) 1994{ 1995 struct proc *p = td->td_proc; 1996 sigset_t set; 1997 1998 OSIG2SIG(uap->mask, set); 1999 SIG_CANTMASK(set); 2000 PROC_LOCK(p); 2001 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 2002 SIGSETOR(td->td_sigmask, set); 2003 PROC_UNLOCK(p); 2004 return (0); 2005} 2006 2007int 2008ofreebsd32_sigsetmask(struct thread *td, 2009 struct ofreebsd32_sigsetmask_args *uap) 2010{ 2011 struct proc *p = td->td_proc; 2012 sigset_t set; 2013 2014 OSIG2SIG(uap->mask, set); 2015 SIG_CANTMASK(set); 2016 PROC_LOCK(p); 2017 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 2018 SIGSETLO(td->td_sigmask, set); 2019 signotify(td); 2020 PROC_UNLOCK(p); 2021 return (0); 2022} 2023 2024int 2025ofreebsd32_sigsuspend(struct thread *td, 2026 struct ofreebsd32_sigsuspend_args *uap) 2027{ 2028 struct proc *p = td->td_proc; 2029 sigset_t mask; 2030 2031 PROC_LOCK(p); 2032 td->td_oldsigmask = td->td_sigmask; 2033 td->td_pflags |= TDP_OLDMASK; 2034 OSIG2SIG(uap->mask, mask); 2035 SIG_CANTMASK(mask); 2036 SIGSETLO(td->td_sigmask, mask); 2037 signotify(td); 2038 while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) 2039 /* void */; 2040 PROC_UNLOCK(p); 2041 /* always return EINTR rather than ERESTART... */ 2042 return (EINTR); 2043} 2044 2045struct sigstack32 { 2046 u_int32_t ss_sp; 2047 int ss_onstack; 2048}; 2049 2050int 2051ofreebsd32_sigstack(struct thread *td, 2052 struct ofreebsd32_sigstack_args *uap) 2053{ 2054 struct sigstack32 s32; 2055 struct sigstack nss, oss; 2056 int error = 0, unss; 2057 2058 if (uap->nss != NULL) { 2059 error = copyin(uap->nss, &s32, sizeof(s32)); 2060 if (error) 2061 return (error); 2062 nss.ss_sp = PTRIN(s32.ss_sp); 2063 CP(s32, nss, ss_onstack); 2064 unss = 1; 2065 } else { 2066 unss = 0; 2067 } 2068 oss.ss_sp = td->td_sigstk.ss_sp; 2069 oss.ss_onstack = sigonstack(cpu_getstack(td)); 2070 if (unss) { 2071 td->td_sigstk.ss_sp = nss.ss_sp; 2072 td->td_sigstk.ss_size = 0; 2073 td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK); 2074 td->td_pflags |= TDP_ALTSTACK; 2075 } 2076 if (uap->oss != NULL) { 2077 s32.ss_sp = PTROUT(oss.ss_sp); 2078 CP(oss, s32, ss_onstack); 2079 error = copyout(&s32, uap->oss, sizeof(s32)); 2080 } 2081 return (error); 2082} 2083#endif 2084 2085int 2086freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 2087{ 2088 struct timespec32 rmt32, rqt32; 2089 struct timespec rmt, rqt; 2090 int error; 2091 2092 error = copyin(uap->rqtp, &rqt32, sizeof(rqt32)); 2093 if (error) 2094 return (error); 2095 2096 CP(rqt32, rqt, tv_sec); 2097 CP(rqt32, rqt, tv_nsec); 2098 2099 if (uap->rmtp && 2100 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 2101 return (EFAULT); 2102 error = kern_nanosleep(td, &rqt, &rmt); 2103 if (error && uap->rmtp) { 2104 int error2; 2105 2106 CP(rmt, rmt32, tv_sec); 2107 CP(rmt, rmt32, tv_nsec); 2108 2109 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32)); 2110 if (error2) 2111 error = error2; 2112 } 2113 return (error); 2114} 2115 2116int 2117freebsd32_clock_gettime(struct thread *td, 2118 struct freebsd32_clock_gettime_args *uap) 2119{ 2120 struct timespec ats; 2121 struct timespec32 ats32; 2122 int error; 2123 2124 error = kern_clock_gettime(td, uap->clock_id, &ats); 2125 if (error == 0) { 2126 CP(ats, ats32, tv_sec); 2127 CP(ats, ats32, tv_nsec); 2128 error = copyout(&ats32, uap->tp, sizeof(ats32)); 2129 } 2130 return (error); 2131} 2132 2133int 2134freebsd32_clock_settime(struct thread *td, 2135 struct freebsd32_clock_settime_args *uap) 2136{ 2137 struct timespec ats; 2138 struct timespec32 ats32; 2139 int error; 2140 2141 error = copyin(uap->tp, &ats32, sizeof(ats32)); 2142 if (error) 2143 return (error); 2144 CP(ats32, ats, tv_sec); 2145 CP(ats32, ats, tv_nsec); 2146 2147 return (kern_clock_settime(td, uap->clock_id, &ats)); 2148} 2149 2150int 2151freebsd32_clock_getres(struct thread *td, 2152 struct freebsd32_clock_getres_args *uap) 2153{ 2154 struct timespec ts; 2155 struct timespec32 ts32; 2156 int error; 2157 2158 if (uap->tp == NULL) 2159 return (0); 2160 error = kern_clock_getres(td, uap->clock_id, &ts); 2161 if (error == 0) { 2162 CP(ts, ts32, tv_sec); 2163 CP(ts, ts32, tv_nsec); 2164 error = copyout(&ts32, uap->tp, sizeof(ts32)); 2165 } 2166 return (error); 2167} 2168 2169int 2170freebsd32_thr_new(struct thread *td, 2171 struct freebsd32_thr_new_args *uap) 2172{ 2173 struct thr_param32 param32; 2174 struct thr_param param; 2175 int error; 2176 2177 if (uap->param_size < 0 || 2178 uap->param_size > sizeof(struct thr_param32)) 2179 return (EINVAL); 2180 bzero(¶m, sizeof(struct thr_param)); 2181 bzero(¶m32, sizeof(struct thr_param32)); 2182 error = copyin(uap->param, ¶m32, uap->param_size); 2183 if (error != 0) 2184 return (error); 2185 param.start_func = PTRIN(param32.start_func); 2186 param.arg = PTRIN(param32.arg); 2187 param.stack_base = PTRIN(param32.stack_base); 2188 param.stack_size = param32.stack_size; 2189 param.tls_base = PTRIN(param32.tls_base); 2190 param.tls_size = param32.tls_size; 2191 param.child_tid = PTRIN(param32.child_tid); 2192 param.parent_tid = PTRIN(param32.parent_tid); 2193 param.flags = param32.flags; 2194 param.rtp = PTRIN(param32.rtp); 2195 param.spare[0] = PTRIN(param32.spare[0]); 2196 param.spare[1] = PTRIN(param32.spare[1]); 2197 param.spare[2] = PTRIN(param32.spare[2]); 2198 2199 return (kern_thr_new(td, ¶m)); 2200} 2201 2202int 2203freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap) 2204{ 2205 struct timespec32 ts32; 2206 struct timespec ts, *tsp; 2207 int error; 2208 2209 error = 0; 2210 tsp = NULL; 2211 if (uap->timeout != NULL) { 2212 error = copyin((const void *)uap->timeout, (void *)&ts32, 2213 sizeof(struct timespec32)); 2214 if (error != 0) 2215 return (error); 2216 ts.tv_sec = ts32.tv_sec; 2217 ts.tv_nsec = ts32.tv_nsec; 2218 tsp = &ts; 2219 } 2220 return (kern_thr_suspend(td, tsp)); 2221} 2222 2223void 2224siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst) 2225{ 2226 bzero(dst, sizeof(*dst)); 2227 dst->si_signo = src->si_signo; 2228 dst->si_errno = src->si_errno; 2229 dst->si_code = src->si_code; 2230 dst->si_pid = src->si_pid; 2231 dst->si_uid = src->si_uid; 2232 dst->si_status = src->si_status; 2233 dst->si_addr = dst->si_addr; 2234 dst->si_value.sigval_int = src->si_value.sival_int; 2235 dst->si_timerid = src->si_timerid; 2236 dst->si_overrun = src->si_overrun; 2237} 2238 2239int 2240freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap) 2241{ 2242 struct timespec32 ts32; 2243 struct timespec ts; 2244 struct timespec *timeout; 2245 sigset_t set; 2246 ksiginfo_t ksi; 2247 struct siginfo32 si32; 2248 int error; 2249 2250 if (uap->timeout) { 2251 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 2252 if (error) 2253 return (error); 2254 ts.tv_sec = ts32.tv_sec; 2255 ts.tv_nsec = ts32.tv_nsec; 2256 timeout = &ts; 2257 } else 2258 timeout = NULL; 2259 2260 error = copyin(uap->set, &set, sizeof(set)); 2261 if (error) 2262 return (error); 2263 2264 error = kern_sigtimedwait(td, set, &ksi, timeout); 2265 if (error) 2266 return (error); 2267 2268 if (uap->info) { 2269 siginfo_to_siginfo32(&ksi.ksi_info, &si32); 2270 error = copyout(&si32, uap->info, sizeof(struct siginfo32)); 2271 } 2272 2273 if (error == 0) 2274 td->td_retval[0] = ksi.ksi_signo; 2275 return (error); 2276} 2277 2278/* 2279 * MPSAFE 2280 */ 2281int 2282freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap) 2283{ 2284 ksiginfo_t ksi; 2285 struct siginfo32 si32; 2286 sigset_t set; 2287 int error; 2288 2289 error = copyin(uap->set, &set, sizeof(set)); 2290 if (error) 2291 return (error); 2292 2293 error = kern_sigtimedwait(td, set, &ksi, NULL); 2294 if (error) 2295 return (error); 2296 2297 if (uap->info) { 2298 siginfo_to_siginfo32(&ksi.ksi_info, &si32); 2299 error = copyout(&si32, uap->info, sizeof(struct siginfo32)); 2300 } 2301 if (error == 0) 2302 td->td_retval[0] = ksi.ksi_signo; 2303 return (error); 2304} 2305 2306#if 0 2307 2308int 2309freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 2310{ 2311 int error; 2312 struct yyy32 *p32, s32; 2313 struct yyy *p = NULL, s; 2314 2315 if (uap->zzz) { 2316 error = copyin(uap->zzz, &s32, sizeof(s32)); 2317 if (error) 2318 return (error); 2319 /* translate in */ 2320 p = &s; 2321 } 2322 error = kern_xxx(td, p); 2323 if (error) 2324 return (error); 2325 if (uap->zzz) { 2326 /* translate out */ 2327 error = copyout(&s32, p32, sizeof(s32)); 2328 } 2329 return (error); 2330} 2331 2332#endif 2333