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