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