freebsd32_misc.c revision 151720
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 151720 2005-10-26 22:19:51Z peter $"); 29 30#include "opt_compat.h" 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/bus.h> 35#include <sys/exec.h> 36#include <sys/fcntl.h> 37#include <sys/filedesc.h> 38#include <sys/namei.h> 39#include <sys/imgact.h> 40#include <sys/kernel.h> 41#include <sys/lock.h> 42#include <sys/malloc.h> 43#include <sys/file.h> /* Must come after sys/malloc.h */ 44#include <sys/mman.h> 45#include <sys/module.h> 46#include <sys/mount.h> 47#include <sys/mutex.h> 48#include <sys/namei.h> 49#include <sys/param.h> 50#include <sys/proc.h> 51#include <sys/reboot.h> 52#include <sys/resource.h> 53#include <sys/resourcevar.h> 54#include <sys/selinfo.h> 55#include <sys/eventvar.h> /* Must come after sys/selinfo.h */ 56#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 57#include <sys/signal.h> 58#include <sys/signalvar.h> 59#include <sys/socket.h> 60#include <sys/socketvar.h> 61#include <sys/stat.h> 62#include <sys/syscall.h> 63#include <sys/syscallsubr.h> 64#include <sys/sysctl.h> 65#include <sys/sysent.h> 66#include <sys/sysproto.h> 67#include <sys/systm.h> 68#include <sys/unistd.h> 69#include <sys/vnode.h> 70#include <sys/wait.h> 71 72#include <vm/vm.h> 73#include <vm/vm_kern.h> 74#include <vm/vm_param.h> 75#include <vm/pmap.h> 76#include <vm/vm_map.h> 77#include <vm/vm_object.h> 78#include <vm/vm_extern.h> 79 80#include <machine/cpu.h> 81 82#include <compat/freebsd32/freebsd32_util.h> 83#include <compat/freebsd32/freebsd32.h> 84#include <compat/freebsd32/freebsd32_proto.h> 85 86CTASSERT(sizeof(struct timeval32) == 8); 87CTASSERT(sizeof(struct timespec32) == 8); 88CTASSERT(sizeof(struct statfs32) == 256); 89CTASSERT(sizeof(struct rusage32) == 72); 90 91int 92freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 93{ 94 int error, status; 95 struct rusage32 ru32; 96 struct rusage ru, *rup; 97 98 if (uap->rusage != NULL) 99 rup = &ru; 100 else 101 rup = NULL; 102 error = kern_wait(td, uap->pid, &status, uap->options, rup); 103 if (error) 104 return (error); 105 if (uap->status != NULL) 106 error = copyout(&status, uap->status, sizeof(status)); 107 if (uap->rusage != NULL && error == 0) { 108 TV_CP(ru, ru32, ru_utime); 109 TV_CP(ru, ru32, ru_stime); 110 CP(ru, ru32, ru_maxrss); 111 CP(ru, ru32, ru_ixrss); 112 CP(ru, ru32, ru_idrss); 113 CP(ru, ru32, ru_isrss); 114 CP(ru, ru32, ru_minflt); 115 CP(ru, ru32, ru_majflt); 116 CP(ru, ru32, ru_nswap); 117 CP(ru, ru32, ru_inblock); 118 CP(ru, ru32, ru_oublock); 119 CP(ru, ru32, ru_msgsnd); 120 CP(ru, ru32, ru_msgrcv); 121 CP(ru, ru32, ru_nsignals); 122 CP(ru, ru32, ru_nvcsw); 123 CP(ru, ru32, ru_nivcsw); 124 error = copyout(&ru32, uap->rusage, sizeof(ru32)); 125 } 126 return (error); 127} 128 129#ifdef COMPAT_FREEBSD4 130static void 131copy_statfs(struct statfs *in, struct statfs32 *out) 132{ 133 CP(*in, *out, f_bsize); 134 CP(*in, *out, f_iosize); 135 CP(*in, *out, f_blocks); 136 CP(*in, *out, f_bfree); 137 CP(*in, *out, f_bavail); 138 CP(*in, *out, f_files); 139 CP(*in, *out, f_ffree); 140 CP(*in, *out, f_fsid); 141 CP(*in, *out, f_owner); 142 CP(*in, *out, f_type); 143 CP(*in, *out, f_flags); 144 CP(*in, *out, f_flags); 145 CP(*in, *out, f_syncwrites); 146 CP(*in, *out, f_asyncwrites); 147 bcopy(in->f_fstypename, 148 out->f_fstypename, MFSNAMELEN); 149 bcopy(in->f_mntonname, 150 out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 151 CP(*in, *out, f_syncreads); 152 CP(*in, *out, f_asyncreads); 153 bcopy(in->f_mntfromname, 154 out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 155} 156#endif 157 158#ifdef COMPAT_FREEBSD4 159int 160freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 161{ 162 struct statfs *buf, *sp; 163 struct statfs32 stat32; 164 size_t count, size; 165 int error; 166 167 count = uap->bufsize / sizeof(struct statfs32); 168 size = count * sizeof(struct statfs); 169 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 170 if (size > 0) { 171 count = td->td_retval[0]; 172 sp = buf; 173 while (count > 0 && error == 0) { 174 copy_statfs(sp, &stat32); 175 error = copyout(&stat32, uap->buf, sizeof(stat32)); 176 sp++; 177 uap->buf++; 178 count--; 179 } 180 free(buf, M_TEMP); 181 } 182 return (error); 183} 184#endif 185 186struct sigaltstack32 { 187 u_int32_t ss_sp; 188 u_int32_t ss_size; 189 int ss_flags; 190}; 191 192CTASSERT(sizeof(struct sigaltstack32) == 12); 193 194int 195freebsd32_sigaltstack(struct thread *td, 196 struct freebsd32_sigaltstack_args *uap) 197{ 198 struct sigaltstack32 s32; 199 struct sigaltstack ss, oss, *ssp; 200 int error; 201 202 if (uap->ss != NULL) { 203 error = copyin(uap->ss, &s32, sizeof(s32)); 204 if (error) 205 return (error); 206 PTRIN_CP(s32, ss, ss_sp); 207 CP(s32, ss, ss_size); 208 CP(s32, ss, ss_flags); 209 ssp = &ss; 210 } else 211 ssp = NULL; 212 error = kern_sigaltstack(td, ssp, &oss); 213 if (error == 0 && uap->oss != NULL) { 214 PTROUT_CP(oss, s32, ss_sp); 215 CP(oss, s32, ss_size); 216 CP(oss, s32, ss_flags); 217 error = copyout(&s32, uap->oss, sizeof(s32)); 218 } 219 return (error); 220} 221 222/* 223 * Custom version of exec_copyin_args() so that we can translate 224 * the pointers. 225 */ 226static int 227freebsd32_exec_copyin_args(struct image_args *args, char *fname, 228 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 229{ 230 char *argp, *envp; 231 u_int32_t *p32, arg; 232 size_t length; 233 int error; 234 235 bzero(args, sizeof(*args)); 236 if (argv == NULL) 237 return (EFAULT); 238 239 /* 240 * Allocate temporary demand zeroed space for argument and 241 * environment strings 242 */ 243 args->buf = (char *) kmem_alloc_wait(exec_map, 244 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 245 if (args->buf == NULL) 246 return (ENOMEM); 247 args->begin_argv = args->buf; 248 args->endp = args->begin_argv; 249 args->stringspace = ARG_MAX; 250 251 args->fname = args->buf + ARG_MAX; 252 253 /* 254 * Copy the file name. 255 */ 256 error = (segflg == UIO_SYSSPACE) ? 257 copystr(fname, args->fname, PATH_MAX, &length) : 258 copyinstr(fname, args->fname, PATH_MAX, &length); 259 if (error != 0) 260 return (error); 261 262 /* 263 * extract arguments first 264 */ 265 p32 = argv; 266 for (;;) { 267 error = copyin(p32++, &arg, sizeof(arg)); 268 if (error) 269 return (error); 270 if (arg == 0) 271 break; 272 argp = PTRIN(arg); 273 error = copyinstr(argp, args->endp, args->stringspace, &length); 274 if (error) { 275 if (error == ENAMETOOLONG) 276 return (E2BIG); 277 else 278 return (error); 279 } 280 args->stringspace -= length; 281 args->endp += length; 282 args->argc++; 283 } 284 285 args->begin_envv = args->endp; 286 287 /* 288 * extract environment strings 289 */ 290 if (envv) { 291 p32 = envv; 292 for (;;) { 293 error = copyin(p32++, &arg, sizeof(arg)); 294 if (error) 295 return (error); 296 if (arg == 0) 297 break; 298 envp = PTRIN(arg); 299 error = copyinstr(envp, args->endp, args->stringspace, 300 &length); 301 if (error) { 302 if (error == ENAMETOOLONG) 303 return (E2BIG); 304 else 305 return (error); 306 } 307 args->stringspace -= length; 308 args->endp += length; 309 args->envc++; 310 } 311 } 312 313 return (0); 314} 315 316int 317freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 318{ 319 struct image_args eargs; 320 int error; 321 322 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 323 uap->argv, uap->envv); 324 if (error == 0) 325 error = kern_execve(td, &eargs, NULL); 326 exec_free_args(&eargs); 327 return (error); 328} 329 330#ifdef __ia64__ 331static int 332freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 333 int prot, int fd, off_t pos) 334{ 335 vm_map_t map; 336 vm_map_entry_t entry; 337 int rv; 338 339 map = &td->td_proc->p_vmspace->vm_map; 340 if (fd != -1) 341 prot |= VM_PROT_WRITE; 342 343 if (vm_map_lookup_entry(map, start, &entry)) { 344 if ((entry->protection & prot) != prot) { 345 rv = vm_map_protect(map, 346 trunc_page(start), 347 round_page(end), 348 entry->protection | prot, 349 FALSE); 350 if (rv != KERN_SUCCESS) 351 return (EINVAL); 352 } 353 } else { 354 vm_offset_t addr = trunc_page(start); 355 rv = vm_map_find(map, 0, 0, 356 &addr, PAGE_SIZE, FALSE, prot, 357 VM_PROT_ALL, 0); 358 if (rv != KERN_SUCCESS) 359 return (EINVAL); 360 } 361 362 if (fd != -1) { 363 struct pread_args r; 364 r.fd = fd; 365 r.buf = (void *) start; 366 r.nbyte = end - start; 367 r.offset = pos; 368 return (pread(td, &r)); 369 } else { 370 while (start < end) { 371 subyte((void *) start, 0); 372 start++; 373 } 374 return (0); 375 } 376} 377#endif 378 379int 380freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 381{ 382 struct mmap_args ap; 383 vm_offset_t addr = (vm_offset_t) uap->addr; 384 vm_size_t len = uap->len; 385 int prot = uap->prot; 386 int flags = uap->flags; 387 int fd = uap->fd; 388 off_t pos = (uap->poslo 389 | ((off_t)uap->poshi << 32)); 390#ifdef __ia64__ 391 vm_size_t pageoff; 392 int error; 393 394 /* 395 * Attempt to handle page size hassles. 396 */ 397 pageoff = (pos & PAGE_MASK); 398 if (flags & MAP_FIXED) { 399 vm_offset_t start, end; 400 start = addr; 401 end = addr + len; 402 403 mtx_lock(&Giant); 404 if (start != trunc_page(start)) { 405 error = freebsd32_mmap_partial(td, start, 406 round_page(start), prot, 407 fd, pos); 408 if (fd != -1) 409 pos += round_page(start) - start; 410 start = round_page(start); 411 } 412 if (end != round_page(end)) { 413 vm_offset_t t = trunc_page(end); 414 error = freebsd32_mmap_partial(td, t, end, 415 prot, fd, 416 pos + t - start); 417 end = trunc_page(end); 418 } 419 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 420 /* 421 * We can't map this region at all. The specified 422 * address doesn't have the same alignment as the file 423 * position. Fake the mapping by simply reading the 424 * entire region into memory. First we need to make 425 * sure the region exists. 426 */ 427 vm_map_t map; 428 struct pread_args r; 429 int rv; 430 431 prot |= VM_PROT_WRITE; 432 map = &td->td_proc->p_vmspace->vm_map; 433 rv = vm_map_remove(map, start, end); 434 if (rv != KERN_SUCCESS) { 435 mtx_unlock(&Giant); 436 return (EINVAL); 437 } 438 rv = vm_map_find(map, 0, 0, 439 &start, end - start, FALSE, 440 prot, VM_PROT_ALL, 0); 441 mtx_unlock(&Giant); 442 if (rv != KERN_SUCCESS) 443 return (EINVAL); 444 r.fd = fd; 445 r.buf = (void *) start; 446 r.nbyte = end - start; 447 r.offset = pos; 448 error = pread(td, &r); 449 if (error) 450 return (error); 451 452 td->td_retval[0] = addr; 453 return (0); 454 } 455 mtx_unlock(&Giant); 456 if (end == start) { 457 /* 458 * After dealing with the ragged ends, there 459 * might be none left. 460 */ 461 td->td_retval[0] = addr; 462 return (0); 463 } 464 addr = start; 465 len = end - start; 466 } 467#endif 468 469 ap.addr = (void *) addr; 470 ap.len = len; 471 ap.prot = prot; 472 ap.flags = flags; 473 ap.fd = fd; 474 ap.pos = pos; 475 476 return (mmap(td, &ap)); 477} 478 479struct itimerval32 { 480 struct timeval32 it_interval; 481 struct timeval32 it_value; 482}; 483 484CTASSERT(sizeof(struct itimerval32) == 16); 485 486int 487freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 488{ 489 struct itimerval itv, oitv, *itvp; 490 struct itimerval32 i32; 491 int error; 492 493 if (uap->itv != NULL) { 494 error = copyin(uap->itv, &i32, sizeof(i32)); 495 if (error) 496 return (error); 497 TV_CP(i32, itv, it_interval); 498 TV_CP(i32, itv, it_value); 499 itvp = &itv; 500 } else 501 itvp = NULL; 502 error = kern_setitimer(td, uap->which, itvp, &oitv); 503 if (error || uap->oitv == NULL) 504 return (error); 505 TV_CP(oitv, i32, it_interval); 506 TV_CP(oitv, i32, it_value); 507 return (copyout(&i32, uap->oitv, sizeof(i32))); 508} 509 510int 511freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 512{ 513 struct itimerval itv; 514 struct itimerval32 i32; 515 int error; 516 517 error = kern_getitimer(td, uap->which, &itv); 518 if (error || uap->itv == NULL) 519 return (error); 520 TV_CP(itv, i32, it_interval); 521 TV_CP(itv, i32, it_value); 522 return (copyout(&i32, uap->itv, sizeof(i32))); 523} 524 525int 526freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 527{ 528 struct timeval32 tv32; 529 struct timeval tv, *tvp; 530 int error; 531 532 if (uap->tv != NULL) { 533 error = copyin(uap->tv, &tv32, sizeof(tv32)); 534 if (error) 535 return (error); 536 CP(tv32, tv, tv_sec); 537 CP(tv32, tv, tv_usec); 538 tvp = &tv; 539 } else 540 tvp = NULL; 541 /* 542 * XXX big-endian needs to convert the fd_sets too. 543 * XXX Do pointers need PTRIN()? 544 */ 545 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); 546} 547 548struct kevent32 { 549 u_int32_t ident; /* identifier for this event */ 550 short filter; /* filter for event */ 551 u_short flags; 552 u_int fflags; 553 int32_t data; 554 u_int32_t udata; /* opaque user data identifier */ 555}; 556 557CTASSERT(sizeof(struct kevent32) == 20); 558static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 559static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 560 561/* 562 * Copy 'count' items into the destination list pointed to by uap->eventlist. 563 */ 564static int 565freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 566{ 567 struct freebsd32_kevent_args *uap; 568 struct kevent32 ks32[KQ_NEVENTS]; 569 int i, error = 0; 570 571 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 572 uap = (struct freebsd32_kevent_args *)arg; 573 574 for (i = 0; i < count; i++) { 575 CP(kevp[i], ks32[i], ident); 576 CP(kevp[i], ks32[i], filter); 577 CP(kevp[i], ks32[i], flags); 578 CP(kevp[i], ks32[i], fflags); 579 CP(kevp[i], ks32[i], data); 580 PTROUT_CP(kevp[i], ks32[i], udata); 581 } 582 error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 583 if (error == 0) 584 uap->eventlist += count; 585 return (error); 586} 587 588/* 589 * Copy 'count' items from the list pointed to by uap->changelist. 590 */ 591static int 592freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 593{ 594 struct freebsd32_kevent_args *uap; 595 struct kevent32 ks32[KQ_NEVENTS]; 596 int i, error = 0; 597 598 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 599 uap = (struct freebsd32_kevent_args *)arg; 600 601 error = copyin(uap->changelist, ks32, count * sizeof *ks32); 602 if (error) 603 goto done; 604 uap->changelist += count; 605 606 for (i = 0; i < count; i++) { 607 CP(ks32[i], kevp[i], ident); 608 CP(ks32[i], kevp[i], filter); 609 CP(ks32[i], kevp[i], flags); 610 CP(ks32[i], kevp[i], fflags); 611 CP(ks32[i], kevp[i], data); 612 PTRIN_CP(ks32[i], kevp[i], udata); 613 } 614done: 615 return (error); 616} 617 618int 619freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 620{ 621 struct timespec32 ts32; 622 struct timespec ts, *tsp; 623 struct kevent_copyops k_ops = { uap, 624 freebsd32_kevent_copyout, 625 freebsd32_kevent_copyin}; 626 int error; 627 628 629 if (uap->timeout) { 630 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 631 if (error) 632 return (error); 633 CP(ts32, ts, tv_sec); 634 CP(ts32, ts, tv_nsec); 635 tsp = &ts; 636 } else 637 tsp = NULL; 638 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 639 &k_ops, tsp); 640 return (error); 641} 642 643int 644freebsd32_gettimeofday(struct thread *td, 645 struct freebsd32_gettimeofday_args *uap) 646{ 647 struct timeval atv; 648 struct timeval32 atv32; 649 struct timezone rtz; 650 int error = 0; 651 652 if (uap->tp) { 653 microtime(&atv); 654 CP(atv, atv32, tv_sec); 655 CP(atv, atv32, tv_usec); 656 error = copyout(&atv32, uap->tp, sizeof (atv32)); 657 } 658 if (error == 0 && uap->tzp != NULL) { 659 rtz.tz_minuteswest = tz_minuteswest; 660 rtz.tz_dsttime = tz_dsttime; 661 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 662 } 663 return (error); 664} 665 666int 667freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 668{ 669 struct rusage32 s32; 670 struct rusage s; 671 int error; 672 673 error = kern_getrusage(td, uap->who, &s); 674 if (error) 675 return (error); 676 if (uap->rusage != NULL) { 677 TV_CP(s, s32, ru_utime); 678 TV_CP(s, s32, ru_stime); 679 CP(s, s32, ru_maxrss); 680 CP(s, s32, ru_ixrss); 681 CP(s, s32, ru_idrss); 682 CP(s, s32, ru_isrss); 683 CP(s, s32, ru_minflt); 684 CP(s, s32, ru_majflt); 685 CP(s, s32, ru_nswap); 686 CP(s, s32, ru_inblock); 687 CP(s, s32, ru_oublock); 688 CP(s, s32, ru_msgsnd); 689 CP(s, s32, ru_msgrcv); 690 CP(s, s32, ru_nsignals); 691 CP(s, s32, ru_nvcsw); 692 CP(s, s32, ru_nivcsw); 693 error = copyout(&s32, uap->rusage, sizeof(s32)); 694 } 695 return (error); 696} 697 698struct iovec32 { 699 u_int32_t iov_base; 700 int iov_len; 701}; 702 703CTASSERT(sizeof(struct iovec32) == 8); 704 705static int 706freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 707{ 708 struct iovec32 iov32; 709 struct iovec *iov; 710 struct uio *uio; 711 u_int iovlen; 712 int error, i; 713 714 *uiop = NULL; 715 if (iovcnt > UIO_MAXIOV) 716 return (EINVAL); 717 iovlen = iovcnt * sizeof(struct iovec); 718 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 719 iov = (struct iovec *)(uio + 1); 720 for (i = 0; i < iovcnt; i++) { 721 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 722 if (error) { 723 free(uio, M_IOV); 724 return (error); 725 } 726 iov[i].iov_base = PTRIN(iov32.iov_base); 727 iov[i].iov_len = iov32.iov_len; 728 } 729 uio->uio_iov = iov; 730 uio->uio_iovcnt = iovcnt; 731 uio->uio_segflg = UIO_USERSPACE; 732 uio->uio_offset = -1; 733 uio->uio_resid = 0; 734 for (i = 0; i < iovcnt; i++) { 735 if (iov->iov_len > INT_MAX - uio->uio_resid) { 736 free(uio, M_IOV); 737 return (EINVAL); 738 } 739 uio->uio_resid += iov->iov_len; 740 iov++; 741 } 742 *uiop = uio; 743 return (0); 744} 745 746int 747freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 748{ 749 struct uio *auio; 750 int error; 751 752 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 753 if (error) 754 return (error); 755 error = kern_readv(td, uap->fd, auio); 756 free(auio, M_IOV); 757 return (error); 758} 759 760int 761freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 762{ 763 struct uio *auio; 764 int error; 765 766 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 767 if (error) 768 return (error); 769 error = kern_writev(td, uap->fd, auio); 770 free(auio, M_IOV); 771 return (error); 772} 773 774int 775freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap) 776{ 777 struct uio *auio; 778 int error; 779 780 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 781 if (error) 782 return (error); 783 error = kern_preadv(td, uap->fd, auio, uap->offset); 784 free(auio, M_IOV); 785 return (error); 786} 787 788int 789freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) 790{ 791 struct uio *auio; 792 int error; 793 794 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 795 if (error) 796 return (error); 797 error = kern_pwritev(td, uap->fd, auio, uap->offset); 798 free(auio, M_IOV); 799 return (error); 800} 801 802static int 803freebsd32_copyiniov(struct iovec32 *iovp, u_int iovcnt, struct iovec **iov, 804 int error) 805{ 806 struct iovec32 iov32; 807 int i; 808 809 u_int iovlen; 810 811 *iov = NULL; 812 if (iovcnt > UIO_MAXIOV) 813 return (error); 814 iovlen = iovcnt * sizeof(struct iovec); 815 *iov = malloc(iovlen, M_IOV, M_WAITOK); 816 for (i = 0; i < iovcnt; i++) { 817 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 818 if (error) { 819 free(*iov, M_IOV); 820 *iov = NULL; 821 return (error); 822 } 823 iov[i]->iov_base = PTRIN(iov32.iov_base); 824 iov[i]->iov_len = iov32.iov_len; 825 } 826 return (0); 827} 828 829struct msghdr32 { 830 u_int32_t msg_name; 831 socklen_t msg_namelen; 832 u_int32_t msg_iov; 833 int msg_iovlen; 834 u_int32_t msg_control; 835 socklen_t msg_controllen; 836 int msg_flags; 837}; 838CTASSERT(sizeof(struct msghdr32) == 28); 839 840static int 841freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg) 842{ 843 struct msghdr32 m32; 844 int error; 845 846 error = copyin(msg32, &m32, sizeof(m32)); 847 if (error) 848 return (error); 849 msg->msg_name = PTRIN(m32.msg_name); 850 msg->msg_namelen = m32.msg_namelen; 851 msg->msg_iov = PTRIN(m32.msg_iov); 852 msg->msg_iovlen = m32.msg_iovlen; 853 msg->msg_control = PTRIN(m32.msg_control); 854 msg->msg_controllen = m32.msg_controllen; 855 msg->msg_flags = m32.msg_flags; 856 return (freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, m32.msg_iovlen, &msg->msg_iov, 857 EMSGSIZE)); 858} 859 860static int 861freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32) 862{ 863 struct msghdr32 m32; 864 int error; 865 866 m32.msg_name = PTROUT(msg->msg_name); 867 m32.msg_namelen = msg->msg_namelen; 868 m32.msg_iov = PTROUT(msg->msg_iov); 869 m32.msg_iovlen = msg->msg_iovlen; 870 m32.msg_control = PTROUT(msg->msg_control); 871 m32.msg_controllen = msg->msg_controllen; 872 m32.msg_flags = msg->msg_flags; 873 error = copyout(&m32, msg32, sizeof(m32)); 874 return (error); 875} 876 877int 878freebsd32_recvmsg(td, uap) 879 struct thread *td; 880 struct freebsd32_recvmsg_args /* { 881 int s; 882 struct msghdr32 *msg; 883 int flags; 884 } */ *uap; 885{ 886 struct msghdr msg; 887 struct msghdr32 m32; 888 struct iovec *uiov, *iov; 889 int error; 890 891 error = copyin(uap->msg, &m32, sizeof(m32)); 892 if (error) 893 return (error); 894 error = freebsd32_copyinmsghdr(uap->msg, &msg); 895 if (error) 896 return (error); 897 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 898 m32.msg_iovlen, &iov, EMSGSIZE); 899 if (error) 900 return (error); 901 msg.msg_flags = uap->flags; 902 uiov = msg.msg_iov; 903 msg.msg_iov = iov; 904 error = kern_recvit(td, uap->s, &msg, NULL, UIO_SYSSPACE); 905 if (error == 0) { 906 msg.msg_iov = uiov; 907 error = freebsd32_copyoutmsghdr(&msg, uap->msg); 908 } 909 free(iov, M_IOV); 910 free(uiov, M_IOV); 911 return (error); 912} 913 914int 915freebsd32_sendmsg(struct thread *td, 916 struct freebsd32_sendmsg_args *uap) 917{ 918 struct msghdr msg; 919 struct msghdr32 m32; 920 struct iovec *iov; 921 int error; 922 923 error = copyin(uap->msg, &m32, sizeof(m32)); 924 if (error) 925 return (error); 926 error = freebsd32_copyinmsghdr(uap->msg, &msg); 927 if (error) 928 return (error); 929 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 930 m32.msg_iovlen, &iov, EMSGSIZE); 931 if (error) 932 return (error); 933 msg.msg_iov = iov; 934 error = kern_sendit(td, uap->s, &msg, uap->flags, NULL, UIO_SYSSPACE); 935 free(iov, M_IOV); 936 return (error); 937} 938 939int 940freebsd32_recvfrom(struct thread *td, 941 struct freebsd32_recvfrom_args *uap) 942{ 943 struct msghdr msg; 944 struct iovec aiov; 945 int error; 946 947 if (uap->fromlenaddr) { 948 error = copyin((void *)(uintptr_t)uap->fromlenaddr, 949 &msg.msg_namelen, sizeof(msg.msg_namelen)); 950 if (error) 951 return (error); 952 } else { 953 msg.msg_namelen = 0; 954 } 955 956 msg.msg_name = (void *)(uintptr_t)uap->from; 957 msg.msg_iov = &aiov; 958 msg.msg_iovlen = 1; 959 aiov.iov_base = (void *)(uintptr_t)uap->buf; 960 aiov.iov_len = uap->len; 961 msg.msg_control = 0; 962 msg.msg_flags = uap->flags; 963 error = kern_recvit(td, uap->s, &msg, (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE); 964 return (error); 965} 966 967int 968freebsd32_settimeofday(struct thread *td, 969 struct freebsd32_settimeofday_args *uap) 970{ 971 struct timeval32 tv32; 972 struct timeval tv, *tvp; 973 struct timezone tz, *tzp; 974 int error; 975 976 if (uap->tv) { 977 error = copyin(uap->tv, &tv32, sizeof(tv32)); 978 if (error) 979 return (error); 980 CP(tv32, tv, tv_sec); 981 CP(tv32, tv, tv_usec); 982 tvp = &tv; 983 } else 984 tvp = NULL; 985 if (uap->tzp) { 986 error = copyin(uap->tzp, &tz, sizeof(tz)); 987 if (error) 988 return (error); 989 tzp = &tz; 990 } else 991 tzp = NULL; 992 return (kern_settimeofday(td, tvp, tzp)); 993} 994 995int 996freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 997{ 998 struct timeval32 s32[2]; 999 struct timeval s[2], *sp; 1000 int error; 1001 1002 if (uap->tptr != NULL) { 1003 error = copyin(uap->tptr, s32, sizeof(s32)); 1004 if (error) 1005 return (error); 1006 CP(s32[0], s[0], tv_sec); 1007 CP(s32[0], s[0], tv_usec); 1008 CP(s32[1], s[1], tv_sec); 1009 CP(s32[1], s[1], tv_usec); 1010 sp = s; 1011 } else 1012 sp = NULL; 1013 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1014} 1015 1016int 1017freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 1018{ 1019 struct timeval32 tv32; 1020 struct timeval delta, olddelta, *deltap; 1021 int error; 1022 1023 if (uap->delta) { 1024 error = copyin(uap->delta, &tv32, sizeof(tv32)); 1025 if (error) 1026 return (error); 1027 CP(tv32, delta, tv_sec); 1028 CP(tv32, delta, tv_usec); 1029 deltap = δ 1030 } else 1031 deltap = NULL; 1032 error = kern_adjtime(td, deltap, &olddelta); 1033 if (uap->olddelta && error == 0) { 1034 CP(olddelta, tv32, tv_sec); 1035 CP(olddelta, tv32, tv_usec); 1036 error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 1037 } 1038 return (error); 1039} 1040 1041#ifdef COMPAT_FREEBSD4 1042int 1043freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 1044{ 1045 struct statfs32 s32; 1046 struct statfs s; 1047 int error; 1048 1049 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 1050 if (error) 1051 return (error); 1052 copy_statfs(&s, &s32); 1053 return (copyout(&s32, uap->buf, sizeof(s32))); 1054} 1055#endif 1056 1057#ifdef COMPAT_FREEBSD4 1058int 1059freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 1060{ 1061 struct statfs32 s32; 1062 struct statfs s; 1063 int error; 1064 1065 error = kern_fstatfs(td, uap->fd, &s); 1066 if (error) 1067 return (error); 1068 copy_statfs(&s, &s32); 1069 return (copyout(&s32, uap->buf, sizeof(s32))); 1070} 1071#endif 1072 1073#ifdef COMPAT_FREEBSD4 1074int 1075freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 1076{ 1077 struct statfs32 s32; 1078 struct statfs s; 1079 fhandle_t fh; 1080 int error; 1081 1082 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 1083 return (error); 1084 error = kern_fhstatfs(td, fh, &s); 1085 if (error) 1086 return (error); 1087 copy_statfs(&s, &s32); 1088 return (copyout(&s32, uap->buf, sizeof(s32))); 1089} 1090#endif 1091 1092int 1093freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1094{ 1095 /* 1096 * Vector through to semsys if it is loaded. 1097 */ 1098 return sysent[SYS_semsys].sy_call(td, uap); 1099} 1100 1101int 1102freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1103{ 1104 /* 1105 * Vector through to msgsys if it is loaded. 1106 */ 1107 return sysent[SYS_msgsys].sy_call(td, uap); 1108} 1109 1110int 1111freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1112{ 1113 /* 1114 * Vector through to shmsys if it is loaded. 1115 */ 1116 return sysent[SYS_shmsys].sy_call(td, uap); 1117} 1118 1119int 1120freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1121{ 1122 struct pread_args ap; 1123 1124 ap.fd = uap->fd; 1125 ap.buf = uap->buf; 1126 ap.nbyte = uap->nbyte; 1127 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1128 return (pread(td, &ap)); 1129} 1130 1131int 1132freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1133{ 1134 struct pwrite_args ap; 1135 1136 ap.fd = uap->fd; 1137 ap.buf = uap->buf; 1138 ap.nbyte = uap->nbyte; 1139 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1140 return (pwrite(td, &ap)); 1141} 1142 1143int 1144freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1145{ 1146 int error; 1147 struct lseek_args ap; 1148 off_t pos; 1149 1150 ap.fd = uap->fd; 1151 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1152 ap.whence = uap->whence; 1153 error = lseek(td, &ap); 1154 /* Expand the quad return into two parts for eax and edx */ 1155 pos = *(off_t *)(td->td_retval); 1156 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1157 td->td_retval[1] = pos >> 32; /* %edx */ 1158 return error; 1159} 1160 1161int 1162freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1163{ 1164 struct truncate_args ap; 1165 1166 ap.path = uap->path; 1167 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1168 return (truncate(td, &ap)); 1169} 1170 1171int 1172freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1173{ 1174 struct ftruncate_args ap; 1175 1176 ap.fd = uap->fd; 1177 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1178 return (ftruncate(td, &ap)); 1179} 1180 1181#ifdef COMPAT_FREEBSD4 1182int 1183freebsd4_freebsd32_sendfile(struct thread *td, 1184 struct freebsd4_freebsd32_sendfile_args *uap) 1185{ 1186 struct freebsd4_sendfile_args ap; 1187 1188 ap.fd = uap->fd; 1189 ap.s = uap->s; 1190 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1191 ap.nbytes = uap->nbytes; /* XXX check */ 1192 ap.hdtr = uap->hdtr; /* XXX check */ 1193 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1194 ap.flags = uap->flags; 1195 return (freebsd4_sendfile(td, &ap)); 1196} 1197#endif 1198 1199int 1200freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1201{ 1202 struct sendfile_args ap; 1203 1204 ap.fd = uap->fd; 1205 ap.s = uap->s; 1206 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1207 ap.nbytes = uap->nbytes; /* XXX check */ 1208 ap.hdtr = uap->hdtr; /* XXX check */ 1209 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1210 ap.flags = uap->flags; 1211 return (sendfile(td, &ap)); 1212} 1213 1214struct stat32 { 1215 dev_t st_dev; 1216 ino_t st_ino; 1217 mode_t st_mode; 1218 nlink_t st_nlink; 1219 uid_t st_uid; 1220 gid_t st_gid; 1221 dev_t st_rdev; 1222 struct timespec32 st_atimespec; 1223 struct timespec32 st_mtimespec; 1224 struct timespec32 st_ctimespec; 1225 off_t st_size; 1226 int64_t st_blocks; 1227 u_int32_t st_blksize; 1228 u_int32_t st_flags; 1229 u_int32_t st_gen; 1230 struct timespec32 st_birthtimespec; 1231 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1232 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1233}; 1234 1235 1236CTASSERT(sizeof(struct stat32) == 96); 1237 1238static void 1239copy_stat( struct stat *in, struct stat32 *out) 1240{ 1241 CP(*in, *out, st_dev); 1242 CP(*in, *out, st_ino); 1243 CP(*in, *out, st_mode); 1244 CP(*in, *out, st_nlink); 1245 CP(*in, *out, st_uid); 1246 CP(*in, *out, st_gid); 1247 CP(*in, *out, st_rdev); 1248 TS_CP(*in, *out, st_atimespec); 1249 TS_CP(*in, *out, st_mtimespec); 1250 TS_CP(*in, *out, st_ctimespec); 1251 CP(*in, *out, st_size); 1252 CP(*in, *out, st_blocks); 1253 CP(*in, *out, st_blksize); 1254 CP(*in, *out, st_flags); 1255 CP(*in, *out, st_gen); 1256} 1257 1258int 1259freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1260{ 1261 struct stat sb; 1262 struct stat32 sb32; 1263 int error; 1264 1265 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1266 if (error) 1267 return (error); 1268 copy_stat(&sb, &sb32); 1269 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1270 return (error); 1271} 1272 1273int 1274freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1275{ 1276 struct stat ub; 1277 struct stat32 ub32; 1278 int error; 1279 1280 error = kern_fstat(td, uap->fd, &ub); 1281 if (error) 1282 return (error); 1283 copy_stat(&ub, &ub32); 1284 error = copyout(&ub32, uap->ub, sizeof(ub32)); 1285 return (error); 1286} 1287 1288int 1289freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1290{ 1291 struct stat sb; 1292 struct stat32 sb32; 1293 int error; 1294 1295 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1296 if (error) 1297 return (error); 1298 copy_stat(&sb, &sb32); 1299 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1300 return (error); 1301} 1302 1303/* 1304 * MPSAFE 1305 */ 1306int 1307freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1308{ 1309 int error, name[CTL_MAXNAME]; 1310 size_t j, oldlen; 1311 1312 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1313 return (EINVAL); 1314 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 1315 if (error) 1316 return (error); 1317 mtx_lock(&Giant); 1318 if (uap->oldlenp) 1319 oldlen = fuword32(uap->oldlenp); 1320 else 1321 oldlen = 0; 1322 error = userland_sysctl(td, name, uap->namelen, 1323 uap->old, &oldlen, 1, 1324 uap->new, uap->newlen, &j, SCTL_MASK32); 1325 if (error && error != ENOMEM) 1326 goto done2; 1327 if (uap->oldlenp) 1328 suword32(uap->oldlenp, j); 1329done2: 1330 mtx_unlock(&Giant); 1331 return (error); 1332} 1333 1334struct sigaction32 { 1335 u_int32_t sa_u; 1336 int sa_flags; 1337 sigset_t sa_mask; 1338}; 1339 1340CTASSERT(sizeof(struct sigaction32) == 24); 1341 1342int 1343freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1344{ 1345 struct sigaction32 s32; 1346 struct sigaction sa, osa, *sap; 1347 int error; 1348 1349 if (uap->act) { 1350 error = copyin(uap->act, &s32, sizeof(s32)); 1351 if (error) 1352 return (error); 1353 sa.sa_handler = PTRIN(s32.sa_u); 1354 CP(s32, sa, sa_flags); 1355 CP(s32, sa, sa_mask); 1356 sap = &sa; 1357 } else 1358 sap = NULL; 1359 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1360 if (error == 0 && uap->oact != NULL) { 1361 s32.sa_u = PTROUT(osa.sa_handler); 1362 CP(osa, s32, sa_flags); 1363 CP(osa, s32, sa_mask); 1364 error = copyout(&s32, uap->oact, sizeof(s32)); 1365 } 1366 return (error); 1367} 1368 1369#ifdef COMPAT_FREEBSD4 1370int 1371freebsd4_freebsd32_sigaction(struct thread *td, 1372 struct freebsd4_freebsd32_sigaction_args *uap) 1373{ 1374 struct sigaction32 s32; 1375 struct sigaction sa, osa, *sap; 1376 int error; 1377 1378 if (uap->act) { 1379 error = copyin(uap->act, &s32, sizeof(s32)); 1380 if (error) 1381 return (error); 1382 sa.sa_handler = PTRIN(s32.sa_u); 1383 CP(s32, sa, sa_flags); 1384 CP(s32, sa, sa_mask); 1385 sap = &sa; 1386 } else 1387 sap = NULL; 1388 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1389 if (error == 0 && uap->oact != NULL) { 1390 s32.sa_u = PTROUT(osa.sa_handler); 1391 CP(osa, s32, sa_flags); 1392 CP(osa, s32, sa_mask); 1393 error = copyout(&s32, uap->oact, sizeof(s32)); 1394 } 1395 return (error); 1396} 1397#endif 1398 1399#ifdef COMPAT_43 1400struct osigaction32 { 1401 u_int32_t sa_u; 1402 osigset_t sa_mask; 1403 int sa_flags; 1404}; 1405 1406#define ONSIG 32 1407 1408int 1409ofreebsd32_sigaction(struct thread *td, 1410 struct ofreebsd32_sigaction_args *uap) 1411{ 1412 struct osigaction32 s32; 1413 struct sigaction sa, osa, *sap; 1414 int error; 1415 1416 if (uap->signum <= 0 || uap->signum >= ONSIG) 1417 return (EINVAL); 1418 1419 if (uap->nsa) { 1420 error = copyin(uap->nsa, &s32, sizeof(s32)); 1421 if (error) 1422 return (error); 1423 sa.sa_handler = PTRIN(s32.sa_u); 1424 CP(s32, sa, sa_flags); 1425 OSIG2SIG(s32.sa_mask, sa.sa_mask); 1426 sap = &sa; 1427 } else 1428 sap = NULL; 1429 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1430 if (error == 0 && uap->osa != NULL) { 1431 s32.sa_u = PTROUT(osa.sa_handler); 1432 CP(osa, s32, sa_flags); 1433 SIG2OSIG(osa.sa_mask, s32.sa_mask); 1434 error = copyout(&s32, uap->osa, sizeof(s32)); 1435 } 1436 return (error); 1437} 1438 1439int 1440ofreebsd32_sigprocmask(struct thread *td, 1441 struct ofreebsd32_sigprocmask_args *uap) 1442{ 1443 sigset_t set, oset; 1444 int error; 1445 1446 OSIG2SIG(uap->mask, set); 1447 error = kern_sigprocmask(td, uap->how, &set, &oset, 1); 1448 SIG2OSIG(oset, td->td_retval[0]); 1449 return (error); 1450} 1451 1452int 1453ofreebsd32_sigpending(struct thread *td, 1454 struct ofreebsd32_sigpending_args *uap) 1455{ 1456 struct proc *p = td->td_proc; 1457 sigset_t siglist; 1458 1459 PROC_LOCK(p); 1460 siglist = p->p_siglist; 1461 SIGSETOR(siglist, td->td_siglist); 1462 PROC_UNLOCK(p); 1463 SIG2OSIG(siglist, td->td_retval[0]); 1464 return (0); 1465} 1466 1467struct sigvec32 { 1468 u_int32_t sv_handler; 1469 int sv_mask; 1470 int sv_flags; 1471}; 1472 1473int 1474ofreebsd32_sigvec(struct thread *td, 1475 struct ofreebsd32_sigvec_args *uap) 1476{ 1477 struct sigvec32 vec; 1478 struct sigaction sa, osa, *sap; 1479 int error; 1480 1481 if (uap->signum <= 0 || uap->signum >= ONSIG) 1482 return (EINVAL); 1483 1484 if (uap->nsv) { 1485 error = copyin(uap->nsv, &vec, sizeof(vec)); 1486 if (error) 1487 return (error); 1488 sa.sa_handler = PTRIN(vec.sv_handler); 1489 OSIG2SIG(vec.sv_mask, sa.sa_mask); 1490 sa.sa_flags = vec.sv_flags; 1491 sa.sa_flags ^= SA_RESTART; 1492 sap = &sa; 1493 } else 1494 sap = NULL; 1495 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1496 if (error == 0 && uap->osv != NULL) { 1497 vec.sv_handler = PTROUT(osa.sa_handler); 1498 SIG2OSIG(osa.sa_mask, vec.sv_mask); 1499 vec.sv_flags = osa.sa_flags; 1500 vec.sv_flags &= ~SA_NOCLDWAIT; 1501 vec.sv_flags ^= SA_RESTART; 1502 error = copyout(&vec, uap->osv, sizeof(vec)); 1503 } 1504 return (error); 1505} 1506 1507int 1508ofreebsd32_sigblock(struct thread *td, 1509 struct ofreebsd32_sigblock_args *uap) 1510{ 1511 struct proc *p = td->td_proc; 1512 sigset_t set; 1513 1514 OSIG2SIG(uap->mask, set); 1515 SIG_CANTMASK(set); 1516 PROC_LOCK(p); 1517 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 1518 SIGSETOR(td->td_sigmask, set); 1519 PROC_UNLOCK(p); 1520 return (0); 1521} 1522 1523int 1524ofreebsd32_sigsetmask(struct thread *td, 1525 struct ofreebsd32_sigsetmask_args *uap) 1526{ 1527 struct proc *p = td->td_proc; 1528 sigset_t set; 1529 1530 OSIG2SIG(uap->mask, set); 1531 SIG_CANTMASK(set); 1532 PROC_LOCK(p); 1533 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 1534 SIGSETLO(td->td_sigmask, set); 1535 signotify(td); 1536 PROC_UNLOCK(p); 1537 return (0); 1538} 1539 1540int 1541ofreebsd32_sigsuspend(struct thread *td, 1542 struct ofreebsd32_sigsuspend_args *uap) 1543{ 1544 struct proc *p = td->td_proc; 1545 sigset_t mask; 1546 1547 PROC_LOCK(p); 1548 td->td_oldsigmask = td->td_sigmask; 1549 td->td_pflags |= TDP_OLDMASK; 1550 OSIG2SIG(uap->mask, mask); 1551 SIG_CANTMASK(mask); 1552 SIGSETLO(td->td_sigmask, mask); 1553 signotify(td); 1554 while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) 1555 /* void */; 1556 PROC_UNLOCK(p); 1557 /* always return EINTR rather than ERESTART... */ 1558 return (EINTR); 1559} 1560 1561struct sigstack32 { 1562 u_int32_t ss_sp; 1563 int ss_onstack; 1564}; 1565 1566int 1567ofreebsd32_sigstack(struct thread *td, 1568 struct ofreebsd32_sigstack_args *uap) 1569{ 1570 struct sigstack32 s32; 1571 struct sigstack nss, oss; 1572 int error = 0; 1573 1574 if (uap->nss != NULL) { 1575 error = copyin(uap->nss, &s32, sizeof(s32)); 1576 if (error) 1577 return (error); 1578 nss.ss_sp = PTRIN(s32.ss_sp); 1579 CP(s32, nss, ss_onstack); 1580 } 1581 oss.ss_sp = td->td_sigstk.ss_sp; 1582 oss.ss_onstack = sigonstack(cpu_getstack(td)); 1583 if (uap->nss != NULL) { 1584 td->td_sigstk.ss_sp = nss.ss_sp; 1585 td->td_sigstk.ss_size = 0; 1586 td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK; 1587 td->td_pflags |= TDP_ALTSTACK; 1588 } 1589 if (uap->oss != NULL) { 1590 s32.ss_sp = PTROUT(oss.ss_sp); 1591 CP(oss, s32, ss_onstack); 1592 error = copyout(&s32, uap->oss, sizeof(s32)); 1593 } 1594 return (error); 1595} 1596#endif 1597 1598int 1599freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 1600{ 1601 struct timespec32 rmt32, rqt32; 1602 struct timespec rmt, rqt; 1603 int error; 1604 1605 error = copyin(uap->rqtp, &rqt32, sizeof(rqt32)); 1606 if (error) 1607 return (error); 1608 1609 CP(rqt32, rqt, tv_sec); 1610 CP(rqt32, rqt, tv_nsec); 1611 1612 if (uap->rmtp && 1613 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 1614 return (EFAULT); 1615 error = kern_nanosleep(td, &rqt, &rmt); 1616 if (error && uap->rmtp) { 1617 int error2; 1618 1619 CP(rmt, rmt32, tv_sec); 1620 CP(rmt, rmt32, tv_nsec); 1621 1622 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32)); 1623 if (error2) 1624 error = error2; 1625 } 1626 return (error); 1627} 1628 1629int 1630freebsd32_clock_gettime(struct thread *td, 1631 struct freebsd32_clock_gettime_args *uap) 1632{ 1633 struct timespec ats; 1634 struct timespec32 ats32; 1635 int error; 1636 1637 error = kern_clock_gettime(td, uap->clock_id, &ats); 1638 if (error == 0) { 1639 CP(ats, ats32, tv_sec); 1640 CP(ats, ats32, tv_nsec); 1641 error = copyout(&ats32, uap->tp, sizeof(ats32)); 1642 } 1643 return (error); 1644} 1645 1646int 1647freebsd32_clock_settime(struct thread *td, 1648 struct freebsd32_clock_settime_args *uap) 1649{ 1650 struct timespec ats; 1651 struct timespec32 ats32; 1652 int error; 1653 1654 error = copyin(uap->tp, &ats32, sizeof(ats32)); 1655 if (error) 1656 return (error); 1657 CP(ats32, ats, tv_sec); 1658 CP(ats32, ats, tv_nsec); 1659 1660 return (kern_clock_settime(td, uap->clock_id, &ats)); 1661} 1662 1663int 1664freebsd32_clock_getres(struct thread *td, 1665 struct freebsd32_clock_getres_args *uap) 1666{ 1667 struct timespec ts; 1668 struct timespec32 ts32; 1669 int error; 1670 1671 if (uap->tp == NULL) 1672 return (0); 1673 error = kern_clock_getres(td, uap->clock_id, &ts); 1674 if (error == 0) { 1675 CP(ts, ts32, tv_sec); 1676 CP(ts, ts32, tv_nsec); 1677 error = copyout(&ts32, uap->tp, sizeof(ts32)); 1678 } 1679 return (error); 1680} 1681 1682#if 0 1683 1684int 1685freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 1686{ 1687 int error; 1688 struct yyy32 *p32, s32; 1689 struct yyy *p = NULL, s; 1690 1691 if (uap->zzz) { 1692 error = copyin(uap->zzz, &s32, sizeof(s32)); 1693 if (error) 1694 return (error); 1695 /* translate in */ 1696 p = &s; 1697 } 1698 error = kern_xxx(td, p); 1699 if (error) 1700 return (error); 1701 if (uap->zzz) { 1702 /* translate out */ 1703 error = copyout(&s32, p32, sizeof(s32)); 1704 } 1705 return (error); 1706} 1707 1708#endif 1709