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