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