freebsd32_misc.c revision 122253
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 122253 2003-11-07 21:27:13Z 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/imgact.h> 39#include <sys/kernel.h> 40#include <sys/lock.h> 41#include <sys/malloc.h> 42#include <sys/file.h> /* Must come after sys/malloc.h */ 43#include <sys/mman.h> 44#include <sys/module.h> 45#include <sys/mount.h> 46#include <sys/mutex.h> 47#include <sys/namei.h> 48#include <sys/param.h> 49#include <sys/proc.h> 50#include <sys/reboot.h> 51#include <sys/resource.h> 52#include <sys/resourcevar.h> 53#include <sys/selinfo.h> 54#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 55#include <sys/signal.h> 56#include <sys/signalvar.h> 57#include <sys/socket.h> 58#include <sys/socketvar.h> 59#include <sys/stat.h> 60#include <sys/syscallsubr.h> 61#include <sys/sysctl.h> 62#include <sys/sysent.h> 63#include <sys/sysproto.h> 64#include <sys/systm.h> 65#include <sys/unistd.h> 66#include <sys/user.h> 67#include <sys/utsname.h> 68#include <sys/vnode.h> 69 70#include <vm/vm.h> 71#include <vm/vm_kern.h> 72#include <vm/vm_param.h> 73#include <vm/pmap.h> 74#include <vm/vm_map.h> 75#include <vm/vm_object.h> 76#include <vm/vm_extern.h> 77 78#include <compat/freebsd32/freebsd32_util.h> 79#include <compat/freebsd32/freebsd32.h> 80#include <compat/freebsd32/freebsd32_proto.h> 81 82CTASSERT(sizeof(struct timeval32) == 8); 83CTASSERT(sizeof(struct timespec32) == 8); 84CTASSERT(sizeof(struct statfs32) == 256); 85CTASSERT(sizeof(struct rusage32) == 72); 86 87/* 88 * [ taken from the linux emulator ] 89 * Search an alternate path before passing pathname arguments on 90 * to system calls. Useful for keeping a separate 'emulation tree'. 91 * 92 * If cflag is set, we check if an attempt can be made to create 93 * the named file, i.e. we check if the directory it should 94 * be in exists. 95 */ 96int 97freebsd32_emul_find(td, sgp, prefix, path, pbuf, cflag) 98 struct thread *td; 99 caddr_t *sgp; /* Pointer to stackgap memory */ 100 const char *prefix; 101 char *path; 102 char **pbuf; 103 int cflag; 104{ 105 int error; 106 size_t len, sz; 107 char *buf, *cp, *ptr; 108 struct ucred *ucred; 109 struct nameidata nd; 110 struct nameidata ndroot; 111 struct vattr vat; 112 struct vattr vatroot; 113 114 buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 115 *pbuf = path; 116 117 for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 118 continue; 119 120 sz = MAXPATHLEN - (ptr - buf); 121 122 /* 123 * If sgp is not given then the path is already in kernel space 124 */ 125 if (sgp == NULL) 126 error = copystr(path, ptr, sz, &len); 127 else 128 error = copyinstr(path, ptr, sz, &len); 129 130 if (error) { 131 free(buf, M_TEMP); 132 return error; 133 } 134 135 if (*ptr != '/') { 136 free(buf, M_TEMP); 137 return EINVAL; 138 } 139 140 /* 141 * We know that there is a / somewhere in this pathname. 142 * Search backwards for it, to find the file's parent dir 143 * to see if it exists in the alternate tree. If it does, 144 * and we want to create a file (cflag is set). We don't 145 * need to worry about the root comparison in this case. 146 */ 147 148 if (cflag) { 149 for (cp = &ptr[len] - 1; *cp != '/'; cp--) 150 ; 151 *cp = '\0'; 152 153 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 154 155 if ((error = namei(&nd)) != 0) { 156 free(buf, M_TEMP); 157 return error; 158 } 159 160 *cp = '/'; 161 } else { 162 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 163 164 if ((error = namei(&nd)) != 0) { 165 free(buf, M_TEMP); 166 return error; 167 } 168 169 /* 170 * We now compare the vnode of the freebsd32_root to the one 171 * vnode asked. If they resolve to be the same, then we 172 * ignore the match so that the real root gets used. 173 * This avoids the problem of traversing "../.." to find the 174 * root directory and never finding it, because "/" resolves 175 * to the emulation root directory. This is expensive :-( 176 */ 177 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, 178 freebsd32_emul_path, td); 179 180 if ((error = namei(&ndroot)) != 0) { 181 /* Cannot happen! */ 182 free(buf, M_TEMP); 183 vrele(nd.ni_vp); 184 return error; 185 } 186 187 ucred = td->td_ucred; 188 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) { 189 goto bad; 190 } 191 192 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred, 193 td)) != 0) { 194 goto bad; 195 } 196 197 if (vat.va_fsid == vatroot.va_fsid && 198 vat.va_fileid == vatroot.va_fileid) { 199 error = ENOENT; 200 goto bad; 201 } 202 203 } 204 if (sgp == NULL) 205 *pbuf = buf; 206 else { 207 sz = &ptr[len] - buf; 208 *pbuf = stackgap_alloc(sgp, sz + 1); 209 error = copyout(buf, *pbuf, sz); 210 free(buf, M_TEMP); 211 } 212 213 vrele(nd.ni_vp); 214 if (!cflag) 215 vrele(ndroot.ni_vp); 216 217 return error; 218 219bad: 220 vrele(ndroot.ni_vp); 221 vrele(nd.ni_vp); 222 free(buf, M_TEMP); 223 return error; 224} 225 226int 227freebsd32_open(struct thread *td, struct freebsd32_open_args *uap) 228{ 229 caddr_t sg; 230 231 sg = stackgap_init(); 232 CHECKALTEXIST(td, &sg, uap->path); 233 234 return open(td, (struct open_args *) uap); 235} 236 237int 238freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 239{ 240 int error; 241 caddr_t sg; 242 struct rusage32 *rusage32, ru32; 243 struct rusage *rusage = NULL, ru; 244 245 rusage32 = uap->rusage; 246 if (rusage32) { 247 sg = stackgap_init(); 248 rusage = stackgap_alloc(&sg, sizeof(struct rusage)); 249 uap->rusage = (struct rusage32 *)rusage; 250 } 251 error = wait4(td, (struct wait_args *)uap); 252 if (error) 253 return (error); 254 if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) { 255 TV_CP(ru, ru32, ru_utime); 256 TV_CP(ru, ru32, ru_stime); 257 CP(ru, ru32, ru_maxrss); 258 CP(ru, ru32, ru_ixrss); 259 CP(ru, ru32, ru_idrss); 260 CP(ru, ru32, ru_isrss); 261 CP(ru, ru32, ru_minflt); 262 CP(ru, ru32, ru_majflt); 263 CP(ru, ru32, ru_nswap); 264 CP(ru, ru32, ru_inblock); 265 CP(ru, ru32, ru_oublock); 266 CP(ru, ru32, ru_msgsnd); 267 CP(ru, ru32, ru_msgrcv); 268 CP(ru, ru32, ru_nsignals); 269 CP(ru, ru32, ru_nvcsw); 270 CP(ru, ru32, ru_nivcsw); 271 error = copyout(&ru32, rusage32, sizeof(ru32)); 272 } 273 return (error); 274} 275 276static void 277copy_statfs(struct statfs *in, struct statfs32 *out) 278{ 279 CP(*in, *out, f_bsize); 280 CP(*in, *out, f_iosize); 281 CP(*in, *out, f_blocks); 282 CP(*in, *out, f_bfree); 283 CP(*in, *out, f_bavail); 284 CP(*in, *out, f_files); 285 CP(*in, *out, f_ffree); 286 CP(*in, *out, f_fsid); 287 CP(*in, *out, f_owner); 288 CP(*in, *out, f_type); 289 CP(*in, *out, f_flags); 290 CP(*in, *out, f_flags); 291 CP(*in, *out, f_syncwrites); 292 CP(*in, *out, f_asyncwrites); 293 bcopy(in->f_fstypename, 294 out->f_fstypename, MFSNAMELEN); 295 bcopy(in->f_mntonname, 296 out->f_mntonname, MNAMELEN); 297 CP(*in, *out, f_syncreads); 298 CP(*in, *out, f_asyncreads); 299 bcopy(in->f_mntfromname, 300 out->f_mntfromname, MNAMELEN); 301} 302 303int 304freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap) 305{ 306 int error; 307 caddr_t sg; 308 struct statfs32 *sp32, stat32; 309 struct statfs *sp = NULL, stat; 310 int maxcount, count, i; 311 312 sp32 = uap->buf; 313 maxcount = uap->bufsize / sizeof(struct statfs32); 314 315 if (sp32) { 316 sg = stackgap_init(); 317 sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); 318 uap->buf = (struct statfs32 *)sp; 319 } 320 error = getfsstat(td, (struct getfsstat_args *) uap); 321 if (sp32 && !error) { 322 count = td->td_retval[0]; 323 for (i = 0; i < count; i++) { 324 error = copyin(&sp[i], &stat, sizeof(stat)); 325 if (error) 326 return (error); 327 copy_statfs(&stat, &stat32); 328 error = copyout(&stat32, &sp32[i], sizeof(stat32)); 329 if (error) 330 return (error); 331 } 332 } 333 return (error); 334} 335 336int 337freebsd32_access(struct thread *td, struct freebsd32_access_args *uap) 338{ 339 caddr_t sg; 340 341 sg = stackgap_init(); 342 CHECKALTEXIST(td, &sg, uap->path); 343 344 return access(td, (struct access_args *)uap); 345} 346 347int 348freebsd32_chflags(struct thread *td, struct freebsd32_chflags_args *uap) 349{ 350 caddr_t sg; 351 352 sg = stackgap_init(); 353 CHECKALTEXIST(td, &sg, uap->path); 354 355 return chflags(td, (struct chflags_args *)uap); 356} 357 358struct sigaltstack32 { 359 u_int32_t ss_sp; 360 u_int32_t ss_size; 361 int ss_flags; 362}; 363 364CTASSERT(sizeof(struct sigaltstack32) == 12); 365 366int 367freebsd32_sigaltstack(struct thread *td, 368 struct freebsd32_sigaltstack_args *uap) 369{ 370 struct sigaltstack32 s32; 371 struct sigaltstack ss, oss, *ssp; 372 int error; 373 374 if (uap->ss != NULL) { 375 error = copyin(uap->ss, &s32, sizeof(s32)); 376 if (error) 377 return (error); 378 PTRIN_CP(s32, ss, ss_sp); 379 CP(s32, ss, ss_size); 380 CP(s32, ss, ss_flags); 381 ssp = &ss; 382 } else 383 ssp = NULL; 384 error = kern_sigaltstack(td, ssp, &oss); 385 if (error == 0 && uap->oss != NULL) { 386 PTROUT_CP(oss, s32, ss_sp); 387 CP(oss, s32, ss_size); 388 CP(oss, s32, ss_flags); 389 error = copyout(&s32, uap->oss, sizeof(s32)); 390 } 391 return (error); 392} 393 394int 395freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 396{ 397 int error; 398 caddr_t sg; 399 struct execve_args ap; 400 u_int32_t *p32, arg; 401 char **p, *p64; 402 int count; 403 404 sg = stackgap_init(); 405 CHECKALTEXIST(td, &sg, uap->fname); 406 ap.fname = uap->fname; 407 408 if (uap->argv) { 409 count = 0; 410 p32 = uap->argv; 411 do { 412 error = copyin(p32++, &arg, sizeof(arg)); 413 if (error) 414 return error; 415 count++; 416 } while (arg != 0); 417 p = stackgap_alloc(&sg, count * sizeof(char *)); 418 ap.argv = p; 419 p32 = uap->argv; 420 do { 421 error = copyin(p32++, &arg, sizeof(arg)); 422 if (error) 423 return error; 424 p64 = PTRIN(arg); 425 error = copyout(&p64, p++, sizeof(p64)); 426 if (error) 427 return error; 428 } while (arg != 0); 429 } 430 if (uap->envv) { 431 count = 0; 432 p32 = uap->envv; 433 do { 434 error = copyin(p32++, &arg, sizeof(arg)); 435 if (error) 436 return error; 437 count++; 438 } while (arg != 0); 439 p = stackgap_alloc(&sg, count * sizeof(char *)); 440 ap.envv = p; 441 p32 = uap->envv; 442 do { 443 error = copyin(p32++, &arg, sizeof(arg)); 444 if (error) 445 return error; 446 p64 = PTRIN(arg); 447 error = copyout(&p64, p++, sizeof(p64)); 448 if (error) 449 return error; 450 } while (arg != 0); 451 } 452 453 return execve(td, &ap); 454} 455 456#ifdef __ia64__ 457static int 458freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 459 int prot, int fd, off_t pos) 460{ 461 vm_map_t map; 462 vm_map_entry_t entry; 463 int rv; 464 465 map = &td->td_proc->p_vmspace->vm_map; 466 if (fd != -1) 467 prot |= VM_PROT_WRITE; 468 469 if (vm_map_lookup_entry(map, start, &entry)) { 470 if ((entry->protection & prot) != prot) { 471 rv = vm_map_protect(map, 472 trunc_page(start), 473 round_page(end), 474 entry->protection | prot, 475 FALSE); 476 if (rv != KERN_SUCCESS) 477 return (EINVAL); 478 } 479 } else { 480 vm_offset_t addr = trunc_page(start); 481 rv = vm_map_find(map, 0, 0, 482 &addr, PAGE_SIZE, FALSE, prot, 483 VM_PROT_ALL, 0); 484 if (rv != KERN_SUCCESS) 485 return (EINVAL); 486 } 487 488 if (fd != -1) { 489 struct pread_args r; 490 r.fd = fd; 491 r.buf = (void *) start; 492 r.nbyte = end - start; 493 r.offset = pos; 494 return (pread(td, &r)); 495 } else { 496 while (start < end) { 497 subyte((void *) start, 0); 498 start++; 499 } 500 return (0); 501 } 502} 503#endif 504 505int 506freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 507{ 508 struct mmap_args ap; 509 vm_offset_t addr = (vm_offset_t) uap->addr; 510 vm_size_t len = uap->len; 511 int prot = uap->prot; 512 int flags = uap->flags; 513 int fd = uap->fd; 514 off_t pos = (uap->poslo 515 | ((off_t)uap->poshi << 32)); 516#ifdef __ia64__ 517 vm_size_t pageoff; 518 int error; 519 520 /* 521 * Attempt to handle page size hassles. 522 */ 523 pageoff = (pos & PAGE_MASK); 524 if (flags & MAP_FIXED) { 525 vm_offset_t start, end; 526 start = addr; 527 end = addr + len; 528 529 if (start != trunc_page(start)) { 530 error = freebsd32_mmap_partial(td, start, 531 round_page(start), prot, 532 fd, pos); 533 if (fd != -1) 534 pos += round_page(start) - start; 535 start = round_page(start); 536 } 537 if (end != round_page(end)) { 538 vm_offset_t t = trunc_page(end); 539 error = freebsd32_mmap_partial(td, t, end, 540 prot, fd, 541 pos + t - start); 542 end = trunc_page(end); 543 } 544 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 545 /* 546 * We can't map this region at all. The specified 547 * address doesn't have the same alignment as the file 548 * position. Fake the mapping by simply reading the 549 * entire region into memory. First we need to make 550 * sure the region exists. 551 */ 552 vm_map_t map; 553 struct pread_args r; 554 int rv; 555 556 prot |= VM_PROT_WRITE; 557 map = &td->td_proc->p_vmspace->vm_map; 558 rv = vm_map_remove(map, start, end); 559 if (rv != KERN_SUCCESS) 560 return (EINVAL); 561 rv = vm_map_find(map, 0, 0, 562 &start, end - start, FALSE, 563 prot, VM_PROT_ALL, 0); 564 if (rv != KERN_SUCCESS) 565 return (EINVAL); 566 r.fd = fd; 567 r.buf = (void *) start; 568 r.nbyte = end - start; 569 r.offset = pos; 570 error = pread(td, &r); 571 if (error) 572 return (error); 573 574 td->td_retval[0] = addr; 575 return (0); 576 } 577 if (end == start) { 578 /* 579 * After dealing with the ragged ends, there 580 * might be none left. 581 */ 582 td->td_retval[0] = addr; 583 return (0); 584 } 585 addr = start; 586 len = end - start; 587 } 588#endif 589 590 ap.addr = (void *) addr; 591 ap.len = len; 592 ap.prot = prot; 593 ap.flags = flags; 594 ap.fd = fd; 595 ap.pos = pos; 596 597 return (mmap(td, &ap)); 598} 599 600struct itimerval32 { 601 struct timeval32 it_interval; 602 struct timeval32 it_value; 603}; 604 605CTASSERT(sizeof(struct itimerval32) == 16); 606 607int 608freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 609{ 610 int error; 611 caddr_t sg; 612 struct itimerval32 *p32, *op32, s32; 613 struct itimerval *p = NULL, *op = NULL, s; 614 615 p32 = uap->itv; 616 if (p32) { 617 sg = stackgap_init(); 618 p = stackgap_alloc(&sg, sizeof(struct itimerval)); 619 uap->itv = (struct itimerval32 *)p; 620 error = copyin(p32, &s32, sizeof(s32)); 621 if (error) 622 return (error); 623 TV_CP(s32, s, it_interval); 624 TV_CP(s32, s, it_value); 625 error = copyout(&s, p, sizeof(s)); 626 if (error) 627 return (error); 628 } 629 op32 = uap->oitv; 630 if (op32) { 631 sg = stackgap_init(); 632 op = stackgap_alloc(&sg, sizeof(struct itimerval)); 633 uap->oitv = (struct itimerval32 *)op; 634 } 635 error = setitimer(td, (struct setitimer_args *) uap); 636 if (error) 637 return (error); 638 if (op32) { 639 error = copyin(op, &s, sizeof(s)); 640 if (error) 641 return (error); 642 TV_CP(s, s32, it_interval); 643 TV_CP(s, s32, it_value); 644 error = copyout(&s32, op32, sizeof(s32)); 645 } 646 return (error); 647} 648 649int 650freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 651{ 652 int error; 653 caddr_t sg; 654 struct timeval32 *p32, s32; 655 struct timeval *p = NULL, s; 656 657 p32 = uap->tv; 658 if (p32) { 659 sg = stackgap_init(); 660 p = stackgap_alloc(&sg, sizeof(struct timeval)); 661 uap->tv = (struct timeval32 *)p; 662 error = copyin(p32, &s32, sizeof(s32)); 663 if (error) 664 return (error); 665 CP(s32, s, tv_sec); 666 CP(s32, s, tv_usec); 667 error = copyout(&s, p, sizeof(s)); 668 if (error) 669 return (error); 670 } 671 /* 672 * XXX big-endian needs to convert the fd_sets too. 673 */ 674 return (select(td, (struct select_args *) uap)); 675} 676 677struct kevent32 { 678 u_int32_t ident; /* identifier for this event */ 679 short filter; /* filter for event */ 680 u_short flags; 681 u_int fflags; 682 int32_t data; 683 u_int32_t udata; /* opaque user data identifier */ 684}; 685 686CTASSERT(sizeof(struct kevent32) == 20); 687 688int 689freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 690{ 691 int error; 692 caddr_t sg; 693 struct timespec32 ts32; 694 struct timespec ts; 695 struct kevent32 ks32; 696 struct kevent *ks; 697 struct kevent_args a; 698 int i; 699 700 sg = stackgap_init(); 701 702 a.fd = uap->fd; 703 a.changelist = uap->changelist; 704 a.nchanges = uap->nchanges; 705 a.eventlist = uap->eventlist; 706 a.nevents = uap->nevents; 707 a.timeout = NULL; 708 709 if (uap->timeout) { 710 a.timeout = stackgap_alloc(&sg, sizeof(struct timespec)); 711 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 712 if (error) 713 return (error); 714 CP(ts32, ts, tv_sec); 715 CP(ts32, ts, tv_nsec); 716 error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts)); 717 if (error) 718 return (error); 719 } 720 if (uap->changelist) { 721 a.changelist = (struct kevent *)stackgap_alloc(&sg, 722 uap->nchanges * sizeof(struct kevent)); 723 for (i = 0; i < uap->nchanges; i++) { 724 error = copyin(&uap->changelist[i], &ks32, 725 sizeof(ks32)); 726 if (error) 727 return (error); 728 ks = (struct kevent *)(uintptr_t)&a.changelist[i]; 729 CP(ks32, *ks, ident); 730 CP(ks32, *ks, filter); 731 CP(ks32, *ks, flags); 732 CP(ks32, *ks, fflags); 733 CP(ks32, *ks, data); 734 PTRIN_CP(ks32, *ks, udata); 735 } 736 } 737 if (uap->eventlist) { 738 a.eventlist = stackgap_alloc(&sg, 739 uap->nevents * sizeof(struct kevent)); 740 } 741 error = kevent(td, &a); 742 if (uap->eventlist && error > 0) { 743 for (i = 0; i < error; i++) { 744 ks = &a.eventlist[i]; 745 CP(*ks, ks32, ident); 746 CP(*ks, ks32, filter); 747 CP(*ks, ks32, flags); 748 CP(*ks, ks32, fflags); 749 CP(*ks, ks32, data); 750 PTROUT_CP(*ks, ks32, udata); 751 error = copyout(&ks32, &uap->eventlist[i], 752 sizeof(ks32)); 753 if (error) 754 return (error); 755 } 756 } 757 return error; 758} 759 760int 761freebsd32_gettimeofday(struct thread *td, 762 struct freebsd32_gettimeofday_args *uap) 763{ 764 int error; 765 caddr_t sg; 766 struct timeval32 *p32, s32; 767 struct timeval *p = NULL, s; 768 769 p32 = uap->tp; 770 if (p32) { 771 sg = stackgap_init(); 772 p = stackgap_alloc(&sg, sizeof(struct timeval)); 773 uap->tp = (struct timeval32 *)p; 774 } 775 error = gettimeofday(td, (struct gettimeofday_args *) uap); 776 if (error) 777 return (error); 778 if (p32) { 779 error = copyin(p, &s, sizeof(s)); 780 if (error) 781 return (error); 782 CP(s, s32, tv_sec); 783 CP(s, s32, tv_usec); 784 error = copyout(&s32, p32, sizeof(s32)); 785 if (error) 786 return (error); 787 } 788 return (error); 789} 790 791int 792freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 793{ 794 int error; 795 caddr_t sg; 796 struct rusage32 *p32, s32; 797 struct rusage *p = NULL, s; 798 799 p32 = uap->rusage; 800 if (p32) { 801 sg = stackgap_init(); 802 p = stackgap_alloc(&sg, sizeof(struct rusage)); 803 uap->rusage = (struct rusage32 *)p; 804 } 805 error = getrusage(td, (struct getrusage_args *) uap); 806 if (error) 807 return (error); 808 if (p32) { 809 error = copyin(p, &s, sizeof(s)); 810 if (error) 811 return (error); 812 TV_CP(s, s32, ru_utime); 813 TV_CP(s, s32, ru_stime); 814 CP(s, s32, ru_maxrss); 815 CP(s, s32, ru_ixrss); 816 CP(s, s32, ru_idrss); 817 CP(s, s32, ru_isrss); 818 CP(s, s32, ru_minflt); 819 CP(s, s32, ru_majflt); 820 CP(s, s32, ru_nswap); 821 CP(s, s32, ru_inblock); 822 CP(s, s32, ru_oublock); 823 CP(s, s32, ru_msgsnd); 824 CP(s, s32, ru_msgrcv); 825 CP(s, s32, ru_nsignals); 826 CP(s, s32, ru_nvcsw); 827 CP(s, s32, ru_nivcsw); 828 error = copyout(&s32, p32, sizeof(s32)); 829 } 830 return (error); 831} 832 833struct iovec32 { 834 u_int32_t iov_base; 835 int iov_len; 836}; 837#define STACKGAPLEN 400 838 839CTASSERT(sizeof(struct iovec32) == 8); 840 841int 842freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 843{ 844 int error, osize, nsize, i; 845 caddr_t sg; 846 struct readv_args /* { 847 syscallarg(int) fd; 848 syscallarg(struct iovec *) iovp; 849 syscallarg(u_int) iovcnt; 850 } */ a; 851 struct iovec32 *oio; 852 struct iovec *nio; 853 854 sg = stackgap_init(); 855 856 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 857 return (EINVAL); 858 859 osize = uap->iovcnt * sizeof (struct iovec32); 860 nsize = uap->iovcnt * sizeof (struct iovec); 861 862 oio = malloc(osize, M_TEMP, M_WAITOK); 863 nio = malloc(nsize, M_TEMP, M_WAITOK); 864 865 error = 0; 866 if ((error = copyin(uap->iovp, oio, osize))) 867 goto punt; 868 for (i = 0; i < uap->iovcnt; i++) { 869 nio[i].iov_base = PTRIN(oio[i].iov_base); 870 nio[i].iov_len = oio[i].iov_len; 871 } 872 873 a.fd = uap->fd; 874 a.iovp = stackgap_alloc(&sg, nsize); 875 a.iovcnt = uap->iovcnt; 876 877 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 878 goto punt; 879 error = readv(td, &a); 880 881punt: 882 free(oio, M_TEMP); 883 free(nio, M_TEMP); 884 return (error); 885} 886 887int 888freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 889{ 890 int error, i, nsize, osize; 891 caddr_t sg; 892 struct writev_args /* { 893 syscallarg(int) fd; 894 syscallarg(struct iovec *) iovp; 895 syscallarg(u_int) iovcnt; 896 } */ a; 897 struct iovec32 *oio; 898 struct iovec *nio; 899 900 sg = stackgap_init(); 901 902 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 903 return (EINVAL); 904 905 osize = uap->iovcnt * sizeof (struct iovec32); 906 nsize = uap->iovcnt * sizeof (struct iovec); 907 908 oio = malloc(osize, M_TEMP, M_WAITOK); 909 nio = malloc(nsize, M_TEMP, M_WAITOK); 910 911 error = 0; 912 if ((error = copyin(uap->iovp, oio, osize))) 913 goto punt; 914 for (i = 0; i < uap->iovcnt; i++) { 915 nio[i].iov_base = PTRIN(oio[i].iov_base); 916 nio[i].iov_len = oio[i].iov_len; 917 } 918 919 a.fd = uap->fd; 920 a.iovp = stackgap_alloc(&sg, nsize); 921 a.iovcnt = uap->iovcnt; 922 923 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 924 goto punt; 925 error = writev(td, &a); 926 927punt: 928 free(oio, M_TEMP); 929 free(nio, M_TEMP); 930 return (error); 931} 932 933int 934freebsd32_settimeofday(struct thread *td, 935 struct freebsd32_settimeofday_args *uap) 936{ 937 int error; 938 caddr_t sg; 939 struct timeval32 *p32, s32; 940 struct timeval *p = NULL, s; 941 942 p32 = uap->tv; 943 if (p32) { 944 sg = stackgap_init(); 945 p = stackgap_alloc(&sg, sizeof(struct timeval)); 946 uap->tv = (struct timeval32 *)p; 947 error = copyin(p32, &s32, sizeof(s32)); 948 if (error) 949 return (error); 950 CP(s32, s, tv_sec); 951 CP(s32, s, tv_usec); 952 error = copyout(&s, p, sizeof(s)); 953 if (error) 954 return (error); 955 } 956 return (settimeofday(td, (struct settimeofday_args *) uap)); 957} 958 959int 960freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 961{ 962 int error; 963 caddr_t sg; 964 struct timeval32 *p32, s32[2]; 965 struct timeval *p = NULL, s[2]; 966 967 p32 = uap->tptr; 968 if (p32) { 969 sg = stackgap_init(); 970 p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); 971 uap->tptr = (struct timeval32 *)p; 972 error = copyin(p32, s32, sizeof(s32)); 973 if (error) 974 return (error); 975 CP(s32[0], s[0], tv_sec); 976 CP(s32[0], s[0], tv_usec); 977 CP(s32[1], s[1], tv_sec); 978 CP(s32[1], s[1], tv_usec); 979 error = copyout(s, p, sizeof(s)); 980 if (error) 981 return (error); 982 } 983 return (utimes(td, (struct utimes_args *) uap)); 984} 985 986int 987freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 988{ 989 int error; 990 caddr_t sg; 991 struct timeval32 *p32, *op32, s32; 992 struct timeval *p = NULL, *op = NULL, s; 993 994 p32 = uap->delta; 995 if (p32) { 996 sg = stackgap_init(); 997 p = stackgap_alloc(&sg, sizeof(struct timeval)); 998 uap->delta = (struct timeval32 *)p; 999 error = copyin(p32, &s32, sizeof(s32)); 1000 if (error) 1001 return (error); 1002 CP(s32, s, tv_sec); 1003 CP(s32, s, tv_usec); 1004 error = copyout(&s, p, sizeof(s)); 1005 if (error) 1006 return (error); 1007 } 1008 op32 = uap->olddelta; 1009 if (op32) { 1010 sg = stackgap_init(); 1011 op = stackgap_alloc(&sg, sizeof(struct timeval)); 1012 uap->olddelta = (struct timeval32 *)op; 1013 } 1014 error = utimes(td, (struct utimes_args *) uap); 1015 if (error) 1016 return error; 1017 if (op32) { 1018 error = copyin(op, &s, sizeof(s)); 1019 if (error) 1020 return (error); 1021 CP(s, s32, tv_sec); 1022 CP(s, s32, tv_usec); 1023 error = copyout(&s32, op32, sizeof(s32)); 1024 } 1025 return (error); 1026} 1027 1028int 1029freebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap) 1030{ 1031 int error; 1032 caddr_t sg; 1033 struct statfs32 *p32, s32; 1034 struct statfs *p = NULL, s; 1035 1036 p32 = uap->buf; 1037 if (p32) { 1038 sg = stackgap_init(); 1039 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1040 uap->buf = (struct statfs32 *)p; 1041 } 1042 error = statfs(td, (struct statfs_args *) uap); 1043 if (error) 1044 return (error); 1045 if (p32) { 1046 error = copyin(p, &s, sizeof(s)); 1047 if (error) 1048 return (error); 1049 copy_statfs(&s, &s32); 1050 error = copyout(&s32, p32, sizeof(s32)); 1051 } 1052 return (error); 1053} 1054 1055int 1056freebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap) 1057{ 1058 int error; 1059 caddr_t sg; 1060 struct statfs32 *p32, s32; 1061 struct statfs *p = NULL, s; 1062 1063 p32 = uap->buf; 1064 if (p32) { 1065 sg = stackgap_init(); 1066 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1067 uap->buf = (struct statfs32 *)p; 1068 } 1069 error = fstatfs(td, (struct fstatfs_args *) uap); 1070 if (error) 1071 return (error); 1072 if (p32) { 1073 error = copyin(p, &s, sizeof(s)); 1074 if (error) 1075 return (error); 1076 copy_statfs(&s, &s32); 1077 error = copyout(&s32, p32, sizeof(s32)); 1078 } 1079 return (error); 1080} 1081 1082int 1083freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1084{ 1085 /* 1086 * Vector through to semsys if it is loaded. 1087 */ 1088 return sysent[169].sy_call(td, uap); 1089} 1090 1091int 1092freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1093{ 1094 /* 1095 * Vector through to msgsys if it is loaded. 1096 */ 1097 return sysent[170].sy_call(td, uap); 1098} 1099 1100int 1101freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1102{ 1103 /* 1104 * Vector through to shmsys if it is loaded. 1105 */ 1106 return sysent[171].sy_call(td, uap); 1107} 1108 1109int 1110freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1111{ 1112 struct pread_args ap; 1113 1114 ap.fd = uap->fd; 1115 ap.buf = uap->buf; 1116 ap.nbyte = uap->nbyte; 1117 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1118 return (pread(td, &ap)); 1119} 1120 1121int 1122freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1123{ 1124 struct pwrite_args ap; 1125 1126 ap.fd = uap->fd; 1127 ap.buf = uap->buf; 1128 ap.nbyte = uap->nbyte; 1129 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1130 return (pwrite(td, &ap)); 1131} 1132 1133int 1134freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1135{ 1136 int error; 1137 struct lseek_args ap; 1138 off_t pos; 1139 1140 ap.fd = uap->fd; 1141 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1142 ap.whence = uap->whence; 1143 error = lseek(td, &ap); 1144 /* Expand the quad return into two parts for eax and edx */ 1145 pos = *(off_t *)(td->td_retval); 1146 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1147 td->td_retval[1] = pos >> 32; /* %edx */ 1148 return error; 1149} 1150 1151int 1152freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1153{ 1154 struct truncate_args ap; 1155 1156 ap.path = uap->path; 1157 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1158 return (truncate(td, &ap)); 1159} 1160 1161int 1162freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1163{ 1164 struct ftruncate_args ap; 1165 1166 ap.fd = uap->fd; 1167 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1168 return (ftruncate(td, &ap)); 1169} 1170 1171#ifdef COMPAT_FREEBSD4 1172int 1173freebsd4_freebsd32_sendfile(struct thread *td, 1174 struct freebsd4_freebsd32_sendfile_args *uap) 1175{ 1176 struct freebsd4_sendfile_args ap; 1177 1178 ap.fd = uap->fd; 1179 ap.s = uap->s; 1180 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1181 ap.nbytes = uap->nbytes; /* XXX check */ 1182 ap.hdtr = uap->hdtr; /* XXX check */ 1183 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1184 ap.flags = uap->flags; 1185 return (freebsd4_sendfile(td, &ap)); 1186} 1187#endif 1188 1189int 1190freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1191{ 1192 struct sendfile_args ap; 1193 1194 ap.fd = uap->fd; 1195 ap.s = uap->s; 1196 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1197 ap.nbytes = uap->nbytes; /* XXX check */ 1198 ap.hdtr = uap->hdtr; /* XXX check */ 1199 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1200 ap.flags = uap->flags; 1201 return (sendfile(td, &ap)); 1202} 1203 1204struct stat32 { 1205 udev_t st_dev; 1206 ino_t st_ino; 1207 mode_t st_mode; 1208 nlink_t st_nlink; 1209 uid_t st_uid; 1210 gid_t st_gid; 1211 udev_t st_rdev; 1212 struct timespec32 st_atimespec; 1213 struct timespec32 st_mtimespec; 1214 struct timespec32 st_ctimespec; 1215 off_t st_size; 1216 int64_t st_blocks; 1217 u_int32_t st_blksize; 1218 u_int32_t st_flags; 1219 u_int32_t st_gen; 1220 struct timespec32 st_birthtimespec; 1221 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1222 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1223}; 1224 1225 1226CTASSERT(sizeof(struct stat32) == 96); 1227 1228static void 1229copy_stat( struct stat *in, struct stat32 *out) 1230{ 1231 CP(*in, *out, st_dev); 1232 CP(*in, *out, st_ino); 1233 CP(*in, *out, st_mode); 1234 CP(*in, *out, st_nlink); 1235 CP(*in, *out, st_uid); 1236 CP(*in, *out, st_gid); 1237 CP(*in, *out, st_rdev); 1238 TS_CP(*in, *out, st_atimespec); 1239 TS_CP(*in, *out, st_mtimespec); 1240 TS_CP(*in, *out, st_ctimespec); 1241 CP(*in, *out, st_size); 1242 CP(*in, *out, st_blocks); 1243 CP(*in, *out, st_blksize); 1244 CP(*in, *out, st_flags); 1245 CP(*in, *out, st_gen); 1246} 1247 1248int 1249freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1250{ 1251 int error; 1252 caddr_t sg; 1253 struct stat32 *p32, s32; 1254 struct stat *p = NULL, s; 1255 1256 p32 = uap->ub; 1257 if (p32) { 1258 sg = stackgap_init(); 1259 p = stackgap_alloc(&sg, sizeof(struct stat)); 1260 uap->ub = (struct stat32 *)p; 1261 } 1262 error = stat(td, (struct stat_args *) uap); 1263 if (error) 1264 return (error); 1265 if (p32) { 1266 error = copyin(p, &s, sizeof(s)); 1267 if (error) 1268 return (error); 1269 copy_stat(&s, &s32); 1270 error = copyout(&s32, p32, sizeof(s32)); 1271 } 1272 return (error); 1273} 1274 1275int 1276freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1277{ 1278 int error; 1279 caddr_t sg; 1280 struct stat32 *p32, s32; 1281 struct stat *p = NULL, s; 1282 1283 p32 = uap->ub; 1284 if (p32) { 1285 sg = stackgap_init(); 1286 p = stackgap_alloc(&sg, sizeof(struct stat)); 1287 uap->ub = (struct stat32 *)p; 1288 } 1289 error = fstat(td, (struct fstat_args *) uap); 1290 if (error) 1291 return (error); 1292 if (p32) { 1293 error = copyin(p, &s, sizeof(s)); 1294 if (error) 1295 return (error); 1296 copy_stat(&s, &s32); 1297 error = copyout(&s32, p32, sizeof(s32)); 1298 } 1299 return (error); 1300} 1301 1302int 1303freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1304{ 1305 int error; 1306 caddr_t sg; 1307 struct stat32 *p32, s32; 1308 struct stat *p = NULL, s; 1309 1310 p32 = uap->ub; 1311 if (p32) { 1312 sg = stackgap_init(); 1313 p = stackgap_alloc(&sg, sizeof(struct stat)); 1314 uap->ub = (struct stat32 *)p; 1315 } 1316 error = lstat(td, (struct lstat_args *) uap); 1317 if (error) 1318 return (error); 1319 if (p32) { 1320 error = copyin(p, &s, sizeof(s)); 1321 if (error) 1322 return (error); 1323 copy_stat(&s, &s32); 1324 error = copyout(&s32, p32, sizeof(s32)); 1325 } 1326 return (error); 1327} 1328 1329/* 1330 * MPSAFE 1331 */ 1332int 1333freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1334{ 1335 int error, name[CTL_MAXNAME]; 1336 size_t j, oldlen; 1337 1338 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1339 return (EINVAL); 1340 1341 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 1342 if (error) 1343 return (error); 1344 1345 mtx_lock(&Giant); 1346 1347 if (uap->oldlenp) 1348 oldlen = fuword32(uap->oldlenp); 1349 else 1350 oldlen = 0; 1351 error = userland_sysctl(td, name, uap->namelen, 1352 uap->old, &oldlen, 1, 1353 uap->new, uap->newlen, &j); 1354 if (error && error != ENOMEM) 1355 goto done2; 1356 if (uap->oldlenp) { 1357 suword32(uap->oldlenp, j); 1358 } 1359done2: 1360 mtx_unlock(&Giant); 1361 return (error); 1362} 1363 1364struct sigaction32 { 1365 u_int32_t sa_u; 1366 int sa_flags; 1367 sigset_t sa_mask; 1368}; 1369 1370CTASSERT(sizeof(struct sigaction32) == 24); 1371 1372int 1373freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1374{ 1375 struct sigaction32 s32; 1376 struct sigaction sa, osa, *sap; 1377 int error; 1378 1379 if (uap->act) { 1380 error = copyin(uap->act, &s32, sizeof(s32)); 1381 if (error) 1382 return (error); 1383 sa.sa_handler = PTRIN(s32.sa_u); 1384 CP(s32, sa, sa_flags); 1385 CP(s32, sa, sa_mask); 1386 sap = &sa; 1387 } else 1388 sap = NULL; 1389 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1390 if (error != 0 && uap->oact != NULL) { 1391 s32.sa_u = PTROUT(osa.sa_handler); 1392 CP(osa, s32, sa_flags); 1393 CP(osa, s32, sa_mask); 1394 error = copyout(&s32, uap->oact, sizeof(s32)); 1395 } 1396 return (error); 1397} 1398 1399#ifdef COMPAT_FREEBSD4 1400int 1401freebsd4_freebsd32_sigaction(struct thread *td, 1402 struct freebsd4_freebsd32_sigaction_args *uap) 1403{ 1404 struct sigaction32 s32; 1405 struct sigaction sa, osa, *sap; 1406 int error; 1407 1408 if (uap->act) { 1409 error = copyin(uap->act, &s32, sizeof(s32)); 1410 if (error) 1411 return (error); 1412 sa.sa_handler = PTRIN(s32.sa_u); 1413 CP(s32, sa, sa_flags); 1414 CP(s32, sa, sa_mask); 1415 sap = &sa; 1416 } else 1417 sap = NULL; 1418 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1419 if (error != 0 && uap->oact != NULL) { 1420 s32.sa_u = PTROUT(osa.sa_handler); 1421 CP(osa, s32, sa_flags); 1422 CP(osa, s32, sa_mask); 1423 error = copyout(&s32, uap->oact, sizeof(s32)); 1424 } 1425 return (error); 1426} 1427#endif 1428 1429#if 0 1430 1431int 1432freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 1433{ 1434 int error; 1435 caddr_t sg; 1436 struct yyy32 *p32, s32; 1437 struct yyy *p = NULL, s; 1438 1439 p32 = uap->zzz; 1440 if (p32) { 1441 sg = stackgap_init(); 1442 p = stackgap_alloc(&sg, sizeof(struct yyy)); 1443 uap->zzz = (struct yyy32 *)p; 1444 error = copyin(p32, &s32, sizeof(s32)); 1445 if (error) 1446 return (error); 1447 /* translate in */ 1448 error = copyout(&s, p, sizeof(s)); 1449 if (error) 1450 return (error); 1451 } 1452 error = xxx(td, (struct xxx_args *) uap); 1453 if (error) 1454 return (error); 1455 if (p32) { 1456 error = copyin(p, &s, sizeof(s)); 1457 if (error) 1458 return (error); 1459 /* translate out */ 1460 error = copyout(&s32, p32, sizeof(s32)); 1461 } 1462 return (error); 1463} 1464 1465#endif 1466