freebsd32_misc.c revision 121719
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 121719 2003-10-30 02:40:30Z 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; 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 *p++ = PTRIN(arg); 425 } while (arg != 0); 426 } 427 if (uap->envv) { 428 count = 0; 429 p32 = uap->envv; 430 do { 431 error = copyin(p32++, &arg, sizeof(arg)); 432 if (error) 433 return error; 434 count++; 435 } while (arg != 0); 436 p = stackgap_alloc(&sg, count * sizeof(char *)); 437 ap.envv = p; 438 p32 = uap->envv; 439 do { 440 error = copyin(p32++, &arg, sizeof(arg)); 441 if (error) 442 return error; 443 *p++ = PTRIN(arg); 444 } while (arg != 0); 445 } 446 447 return execve(td, &ap); 448} 449 450#ifdef __ia64__ 451static int 452freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 453 int prot, int fd, off_t pos) 454{ 455 vm_map_t map; 456 vm_map_entry_t entry; 457 int rv; 458 459 map = &td->td_proc->p_vmspace->vm_map; 460 if (fd != -1) 461 prot |= VM_PROT_WRITE; 462 463 if (vm_map_lookup_entry(map, start, &entry)) { 464 if ((entry->protection & prot) != prot) { 465 rv = vm_map_protect(map, 466 trunc_page(start), 467 round_page(end), 468 entry->protection | prot, 469 FALSE); 470 if (rv != KERN_SUCCESS) 471 return (EINVAL); 472 } 473 } else { 474 vm_offset_t addr = trunc_page(start); 475 rv = vm_map_find(map, 0, 0, 476 &addr, PAGE_SIZE, FALSE, prot, 477 VM_PROT_ALL, 0); 478 if (rv != KERN_SUCCESS) 479 return (EINVAL); 480 } 481 482 if (fd != -1) { 483 struct pread_args r; 484 r.fd = fd; 485 r.buf = (void *) start; 486 r.nbyte = end - start; 487 r.offset = pos; 488 return (pread(td, &r)); 489 } else { 490 while (start < end) { 491 subyte((void *) start, 0); 492 start++; 493 } 494 return (0); 495 } 496} 497#endif 498 499int 500freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 501{ 502 struct mmap_args ap; 503 vm_offset_t addr = (vm_offset_t) uap->addr; 504 vm_size_t len = uap->len; 505 int prot = uap->prot; 506 int flags = uap->flags; 507 int fd = uap->fd; 508 off_t pos = (uap->poslo 509 | ((off_t)uap->poshi << 32)); 510#ifdef __ia64__ 511 vm_size_t pageoff; 512 int error; 513 514 /* 515 * Attempt to handle page size hassles. 516 */ 517 pageoff = (pos & PAGE_MASK); 518 if (flags & MAP_FIXED) { 519 vm_offset_t start, end; 520 start = addr; 521 end = addr + len; 522 523 if (start != trunc_page(start)) { 524 error = freebsd32_mmap_partial(td, start, 525 round_page(start), prot, 526 fd, pos); 527 if (fd != -1) 528 pos += round_page(start) - start; 529 start = round_page(start); 530 } 531 if (end != round_page(end)) { 532 vm_offset_t t = trunc_page(end); 533 error = freebsd32_mmap_partial(td, t, end, 534 prot, fd, 535 pos + t - start); 536 end = trunc_page(end); 537 } 538 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 539 /* 540 * We can't map this region at all. The specified 541 * address doesn't have the same alignment as the file 542 * position. Fake the mapping by simply reading the 543 * entire region into memory. First we need to make 544 * sure the region exists. 545 */ 546 vm_map_t map; 547 struct pread_args r; 548 int rv; 549 550 prot |= VM_PROT_WRITE; 551 map = &td->td_proc->p_vmspace->vm_map; 552 rv = vm_map_remove(map, start, end); 553 if (rv != KERN_SUCCESS) 554 return (EINVAL); 555 rv = vm_map_find(map, 0, 0, 556 &start, end - start, FALSE, 557 prot, VM_PROT_ALL, 0); 558 if (rv != KERN_SUCCESS) 559 return (EINVAL); 560 r.fd = fd; 561 r.buf = (void *) start; 562 r.nbyte = end - start; 563 r.offset = pos; 564 error = pread(td, &r); 565 if (error) 566 return (error); 567 568 td->td_retval[0] = addr; 569 return (0); 570 } 571 if (end == start) { 572 /* 573 * After dealing with the ragged ends, there 574 * might be none left. 575 */ 576 td->td_retval[0] = addr; 577 return (0); 578 } 579 addr = start; 580 len = end - start; 581 } 582#endif 583 584 ap.addr = (void *) addr; 585 ap.len = len; 586 ap.prot = prot; 587 ap.flags = flags; 588 ap.fd = fd; 589 ap.pos = pos; 590 591 return (mmap(td, &ap)); 592} 593 594struct itimerval32 { 595 struct timeval32 it_interval; 596 struct timeval32 it_value; 597}; 598 599CTASSERT(sizeof(struct itimerval32) == 16); 600 601int 602freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 603{ 604 int error; 605 caddr_t sg; 606 struct itimerval32 *p32, *op32, s32; 607 struct itimerval *p = NULL, *op = NULL, s; 608 609 p32 = uap->itv; 610 if (p32) { 611 sg = stackgap_init(); 612 p = stackgap_alloc(&sg, sizeof(struct itimerval)); 613 uap->itv = (struct itimerval32 *)p; 614 error = copyin(p32, &s32, sizeof(s32)); 615 if (error) 616 return (error); 617 TV_CP(s32, s, it_interval); 618 TV_CP(s32, s, it_value); 619 error = copyout(&s, p, sizeof(s)); 620 if (error) 621 return (error); 622 } 623 op32 = uap->oitv; 624 if (op32) { 625 sg = stackgap_init(); 626 op = stackgap_alloc(&sg, sizeof(struct itimerval)); 627 uap->oitv = (struct itimerval32 *)op; 628 } 629 error = setitimer(td, (struct setitimer_args *) uap); 630 if (error) 631 return (error); 632 if (op32) { 633 error = copyin(op, &s, sizeof(s)); 634 if (error) 635 return (error); 636 TV_CP(s, s32, it_interval); 637 TV_CP(s, s32, it_value); 638 error = copyout(&s32, op32, sizeof(s32)); 639 } 640 return (error); 641} 642 643int 644freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 645{ 646 int error; 647 caddr_t sg; 648 struct timeval32 *p32, s32; 649 struct timeval *p = NULL, s; 650 651 p32 = uap->tv; 652 if (p32) { 653 sg = stackgap_init(); 654 p = stackgap_alloc(&sg, sizeof(struct timeval)); 655 uap->tv = (struct timeval32 *)p; 656 error = copyin(p32, &s32, sizeof(s32)); 657 if (error) 658 return (error); 659 CP(s32, s, tv_sec); 660 CP(s32, s, tv_usec); 661 error = copyout(&s, p, sizeof(s)); 662 if (error) 663 return (error); 664 } 665 /* 666 * XXX big-endian needs to convert the fd_sets too. 667 */ 668 return (select(td, (struct select_args *) uap)); 669} 670 671struct kevent32 { 672 u_int32_t ident; /* identifier for this event */ 673 short filter; /* filter for event */ 674 u_short flags; 675 u_int fflags; 676 int32_t data; 677 u_int32_t udata; /* opaque user data identifier */ 678}; 679 680CTASSERT(sizeof(struct kevent32) == 20); 681 682int 683freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 684{ 685 int error; 686 caddr_t sg; 687 struct timespec32 ts32; 688 struct timespec ts; 689 struct kevent32 ks32; 690 struct kevent *ks; 691 struct kevent_args a; 692 int i; 693 694 sg = stackgap_init(); 695 696 a.fd = uap->fd; 697 a.changelist = uap->changelist; 698 a.nchanges = uap->nchanges; 699 a.eventlist = uap->eventlist; 700 a.nevents = uap->nevents; 701 a.timeout = NULL; 702 703 if (uap->timeout) { 704 a.timeout = stackgap_alloc(&sg, sizeof(struct timespec)); 705 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 706 if (error) 707 return (error); 708 CP(ts32, ts, tv_sec); 709 CP(ts32, ts, tv_nsec); 710 error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts)); 711 if (error) 712 return (error); 713 } 714 if (uap->changelist) { 715 a.changelist = (struct kevent *)stackgap_alloc(&sg, 716 uap->nchanges * sizeof(struct kevent)); 717 for (i = 0; i < uap->nchanges; i++) { 718 error = copyin(&uap->changelist[i], &ks32, 719 sizeof(ks32)); 720 if (error) 721 return (error); 722 ks = (struct kevent *)(uintptr_t)&a.changelist[i]; 723 CP(ks32, *ks, ident); 724 CP(ks32, *ks, filter); 725 CP(ks32, *ks, flags); 726 CP(ks32, *ks, fflags); 727 CP(ks32, *ks, data); 728 PTRIN_CP(ks32, *ks, udata); 729 } 730 } 731 if (uap->eventlist) { 732 a.eventlist = stackgap_alloc(&sg, 733 uap->nevents * sizeof(struct kevent)); 734 } 735 error = kevent(td, &a); 736 if (uap->eventlist && error > 0) { 737 for (i = 0; i < error; i++) { 738 ks = &a.eventlist[i]; 739 CP(*ks, ks32, ident); 740 CP(*ks, ks32, filter); 741 CP(*ks, ks32, flags); 742 CP(*ks, ks32, fflags); 743 CP(*ks, ks32, data); 744 PTROUT_CP(*ks, ks32, udata); 745 error = copyout(&ks32, &uap->eventlist[i], 746 sizeof(ks32)); 747 if (error) 748 return (error); 749 } 750 } 751 return error; 752} 753 754int 755freebsd32_gettimeofday(struct thread *td, 756 struct freebsd32_gettimeofday_args *uap) 757{ 758 int error; 759 caddr_t sg; 760 struct timeval32 *p32, s32; 761 struct timeval *p = NULL, s; 762 763 p32 = uap->tp; 764 if (p32) { 765 sg = stackgap_init(); 766 p = stackgap_alloc(&sg, sizeof(struct timeval)); 767 uap->tp = (struct timeval32 *)p; 768 } 769 error = gettimeofday(td, (struct gettimeofday_args *) uap); 770 if (error) 771 return (error); 772 if (p32) { 773 error = copyin(p, &s, sizeof(s)); 774 if (error) 775 return (error); 776 CP(s, s32, tv_sec); 777 CP(s, s32, tv_usec); 778 error = copyout(&s32, p32, sizeof(s32)); 779 if (error) 780 return (error); 781 } 782 return (error); 783} 784 785int 786freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 787{ 788 int error; 789 caddr_t sg; 790 struct rusage32 *p32, s32; 791 struct rusage *p = NULL, s; 792 793 p32 = uap->rusage; 794 if (p32) { 795 sg = stackgap_init(); 796 p = stackgap_alloc(&sg, sizeof(struct rusage)); 797 uap->rusage = (struct rusage32 *)p; 798 } 799 error = getrusage(td, (struct getrusage_args *) uap); 800 if (error) 801 return (error); 802 if (p32) { 803 error = copyin(p, &s, sizeof(s)); 804 if (error) 805 return (error); 806 TV_CP(s, s32, ru_utime); 807 TV_CP(s, s32, ru_stime); 808 CP(s, s32, ru_maxrss); 809 CP(s, s32, ru_ixrss); 810 CP(s, s32, ru_idrss); 811 CP(s, s32, ru_isrss); 812 CP(s, s32, ru_minflt); 813 CP(s, s32, ru_majflt); 814 CP(s, s32, ru_nswap); 815 CP(s, s32, ru_inblock); 816 CP(s, s32, ru_oublock); 817 CP(s, s32, ru_msgsnd); 818 CP(s, s32, ru_msgrcv); 819 CP(s, s32, ru_nsignals); 820 CP(s, s32, ru_nvcsw); 821 CP(s, s32, ru_nivcsw); 822 error = copyout(&s32, p32, sizeof(s32)); 823 } 824 return (error); 825} 826 827struct iovec32 { 828 u_int32_t iov_base; 829 int iov_len; 830}; 831#define STACKGAPLEN 400 832 833CTASSERT(sizeof(struct iovec32) == 8); 834 835int 836freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 837{ 838 int error, osize, nsize, i; 839 caddr_t sg; 840 struct readv_args /* { 841 syscallarg(int) fd; 842 syscallarg(struct iovec *) iovp; 843 syscallarg(u_int) iovcnt; 844 } */ a; 845 struct iovec32 *oio; 846 struct iovec *nio; 847 848 sg = stackgap_init(); 849 850 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 851 return (EINVAL); 852 853 osize = uap->iovcnt * sizeof (struct iovec32); 854 nsize = uap->iovcnt * sizeof (struct iovec); 855 856 oio = malloc(osize, M_TEMP, M_WAITOK); 857 nio = malloc(nsize, M_TEMP, M_WAITOK); 858 859 error = 0; 860 if ((error = copyin(uap->iovp, oio, osize))) 861 goto punt; 862 for (i = 0; i < uap->iovcnt; i++) { 863 nio[i].iov_base = PTRIN(oio[i].iov_base); 864 nio[i].iov_len = oio[i].iov_len; 865 } 866 867 a.fd = uap->fd; 868 a.iovp = stackgap_alloc(&sg, nsize); 869 a.iovcnt = uap->iovcnt; 870 871 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 872 goto punt; 873 error = readv(td, &a); 874 875punt: 876 free(oio, M_TEMP); 877 free(nio, M_TEMP); 878 return (error); 879} 880 881int 882freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 883{ 884 int error, i, nsize, osize; 885 caddr_t sg; 886 struct writev_args /* { 887 syscallarg(int) fd; 888 syscallarg(struct iovec *) iovp; 889 syscallarg(u_int) iovcnt; 890 } */ a; 891 struct iovec32 *oio; 892 struct iovec *nio; 893 894 sg = stackgap_init(); 895 896 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 897 return (EINVAL); 898 899 osize = uap->iovcnt * sizeof (struct iovec32); 900 nsize = uap->iovcnt * sizeof (struct iovec); 901 902 oio = malloc(osize, M_TEMP, M_WAITOK); 903 nio = malloc(nsize, M_TEMP, M_WAITOK); 904 905 error = 0; 906 if ((error = copyin(uap->iovp, oio, osize))) 907 goto punt; 908 for (i = 0; i < uap->iovcnt; i++) { 909 nio[i].iov_base = PTRIN(oio[i].iov_base); 910 nio[i].iov_len = oio[i].iov_len; 911 } 912 913 a.fd = uap->fd; 914 a.iovp = stackgap_alloc(&sg, nsize); 915 a.iovcnt = uap->iovcnt; 916 917 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 918 goto punt; 919 error = writev(td, &a); 920 921punt: 922 free(oio, M_TEMP); 923 free(nio, M_TEMP); 924 return (error); 925} 926 927int 928freebsd32_settimeofday(struct thread *td, 929 struct freebsd32_settimeofday_args *uap) 930{ 931 int error; 932 caddr_t sg; 933 struct timeval32 *p32, s32; 934 struct timeval *p = NULL, s; 935 936 p32 = uap->tv; 937 if (p32) { 938 sg = stackgap_init(); 939 p = stackgap_alloc(&sg, sizeof(struct timeval)); 940 uap->tv = (struct timeval32 *)p; 941 error = copyin(p32, &s32, sizeof(s32)); 942 if (error) 943 return (error); 944 CP(s32, s, tv_sec); 945 CP(s32, s, tv_usec); 946 error = copyout(&s, p, sizeof(s)); 947 if (error) 948 return (error); 949 } 950 return (settimeofday(td, (struct settimeofday_args *) uap)); 951} 952 953int 954freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 955{ 956 int error; 957 caddr_t sg; 958 struct timeval32 *p32, s32[2]; 959 struct timeval *p = NULL, s[2]; 960 961 p32 = uap->tptr; 962 if (p32) { 963 sg = stackgap_init(); 964 p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); 965 uap->tptr = (struct timeval32 *)p; 966 error = copyin(p32, s32, sizeof(s32)); 967 if (error) 968 return (error); 969 CP(s32[0], s[0], tv_sec); 970 CP(s32[0], s[0], tv_usec); 971 CP(s32[1], s[1], tv_sec); 972 CP(s32[1], s[1], tv_usec); 973 error = copyout(s, p, sizeof(s)); 974 if (error) 975 return (error); 976 } 977 return (utimes(td, (struct utimes_args *) uap)); 978} 979 980int 981freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 982{ 983 int error; 984 caddr_t sg; 985 struct timeval32 *p32, *op32, s32; 986 struct timeval *p = NULL, *op = NULL, s; 987 988 p32 = uap->delta; 989 if (p32) { 990 sg = stackgap_init(); 991 p = stackgap_alloc(&sg, sizeof(struct timeval)); 992 uap->delta = (struct timeval32 *)p; 993 error = copyin(p32, &s32, sizeof(s32)); 994 if (error) 995 return (error); 996 CP(s32, s, tv_sec); 997 CP(s32, s, tv_usec); 998 error = copyout(&s, p, sizeof(s)); 999 if (error) 1000 return (error); 1001 } 1002 op32 = uap->olddelta; 1003 if (op32) { 1004 sg = stackgap_init(); 1005 op = stackgap_alloc(&sg, sizeof(struct timeval)); 1006 uap->olddelta = (struct timeval32 *)op; 1007 } 1008 error = utimes(td, (struct utimes_args *) uap); 1009 if (error) 1010 return error; 1011 if (op32) { 1012 error = copyin(op, &s, sizeof(s)); 1013 if (error) 1014 return (error); 1015 CP(s, s32, tv_sec); 1016 CP(s, s32, tv_usec); 1017 error = copyout(&s32, op32, sizeof(s32)); 1018 } 1019 return (error); 1020} 1021 1022int 1023freebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap) 1024{ 1025 int error; 1026 caddr_t sg; 1027 struct statfs32 *p32, s32; 1028 struct statfs *p = NULL, s; 1029 1030 p32 = uap->buf; 1031 if (p32) { 1032 sg = stackgap_init(); 1033 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1034 uap->buf = (struct statfs32 *)p; 1035 } 1036 error = statfs(td, (struct statfs_args *) uap); 1037 if (error) 1038 return (error); 1039 if (p32) { 1040 error = copyin(p, &s, sizeof(s)); 1041 if (error) 1042 return (error); 1043 copy_statfs(&s, &s32); 1044 error = copyout(&s32, p32, sizeof(s32)); 1045 } 1046 return (error); 1047} 1048 1049int 1050freebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap) 1051{ 1052 int error; 1053 caddr_t sg; 1054 struct statfs32 *p32, s32; 1055 struct statfs *p = NULL, s; 1056 1057 p32 = uap->buf; 1058 if (p32) { 1059 sg = stackgap_init(); 1060 p = stackgap_alloc(&sg, sizeof(struct statfs)); 1061 uap->buf = (struct statfs32 *)p; 1062 } 1063 error = fstatfs(td, (struct fstatfs_args *) uap); 1064 if (error) 1065 return (error); 1066 if (p32) { 1067 error = copyin(p, &s, sizeof(s)); 1068 if (error) 1069 return (error); 1070 copy_statfs(&s, &s32); 1071 error = copyout(&s32, p32, sizeof(s32)); 1072 } 1073 return (error); 1074} 1075 1076int 1077freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1078{ 1079 /* 1080 * Vector through to semsys if it is loaded. 1081 */ 1082 return sysent[169].sy_call(td, uap); 1083} 1084 1085int 1086freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1087{ 1088 /* 1089 * Vector through to msgsys if it is loaded. 1090 */ 1091 return sysent[170].sy_call(td, uap); 1092} 1093 1094int 1095freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1096{ 1097 /* 1098 * Vector through to shmsys if it is loaded. 1099 */ 1100 return sysent[171].sy_call(td, uap); 1101} 1102 1103int 1104freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1105{ 1106 struct pread_args ap; 1107 1108 ap.fd = uap->fd; 1109 ap.buf = uap->buf; 1110 ap.nbyte = uap->nbyte; 1111 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1112 return (pread(td, &ap)); 1113} 1114 1115int 1116freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1117{ 1118 struct pwrite_args ap; 1119 1120 ap.fd = uap->fd; 1121 ap.buf = uap->buf; 1122 ap.nbyte = uap->nbyte; 1123 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1124 return (pwrite(td, &ap)); 1125} 1126 1127int 1128freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1129{ 1130 int error; 1131 struct lseek_args ap; 1132 off_t pos; 1133 1134 ap.fd = uap->fd; 1135 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1136 ap.whence = uap->whence; 1137 error = lseek(td, &ap); 1138 /* Expand the quad return into two parts for eax and edx */ 1139 pos = *(off_t *)(td->td_retval); 1140 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1141 td->td_retval[1] = pos >> 32; /* %edx */ 1142 return error; 1143} 1144 1145int 1146freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1147{ 1148 struct truncate_args ap; 1149 1150 ap.path = uap->path; 1151 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1152 return (truncate(td, &ap)); 1153} 1154 1155int 1156freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1157{ 1158 struct ftruncate_args ap; 1159 1160 ap.fd = uap->fd; 1161 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1162 return (ftruncate(td, &ap)); 1163} 1164 1165#ifdef COMPAT_FREEBSD4 1166int 1167freebsd4_freebsd32_sendfile(struct thread *td, 1168 struct freebsd4_freebsd32_sendfile_args *uap) 1169{ 1170 struct freebsd4_sendfile_args ap; 1171 1172 ap.fd = uap->fd; 1173 ap.s = uap->s; 1174 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1175 ap.nbytes = uap->nbytes; /* XXX check */ 1176 ap.hdtr = uap->hdtr; /* XXX check */ 1177 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1178 ap.flags = uap->flags; 1179 return (freebsd4_sendfile(td, &ap)); 1180} 1181#endif 1182 1183int 1184freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1185{ 1186 struct 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 (sendfile(td, &ap)); 1196} 1197 1198struct stat32 { 1199 udev_t st_dev; 1200 ino_t st_ino; 1201 mode_t st_mode; 1202 nlink_t st_nlink; 1203 uid_t st_uid; 1204 gid_t st_gid; 1205 udev_t st_rdev; 1206 struct timespec32 st_atimespec; 1207 struct timespec32 st_mtimespec; 1208 struct timespec32 st_ctimespec; 1209 off_t st_size; 1210 int64_t st_blocks; 1211 u_int32_t st_blksize; 1212 u_int32_t st_flags; 1213 u_int32_t st_gen; 1214 struct timespec32 st_birthtimespec; 1215 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1216 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1217}; 1218 1219 1220CTASSERT(sizeof(struct stat32) == 96); 1221 1222static void 1223copy_stat( struct stat *in, struct stat32 *out) 1224{ 1225 CP(*in, *out, st_dev); 1226 CP(*in, *out, st_ino); 1227 CP(*in, *out, st_mode); 1228 CP(*in, *out, st_nlink); 1229 CP(*in, *out, st_uid); 1230 CP(*in, *out, st_gid); 1231 CP(*in, *out, st_rdev); 1232 TS_CP(*in, *out, st_atimespec); 1233 TS_CP(*in, *out, st_mtimespec); 1234 TS_CP(*in, *out, st_ctimespec); 1235 CP(*in, *out, st_size); 1236 CP(*in, *out, st_blocks); 1237 CP(*in, *out, st_blksize); 1238 CP(*in, *out, st_flags); 1239 CP(*in, *out, st_gen); 1240} 1241 1242int 1243freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1244{ 1245 int error; 1246 caddr_t sg; 1247 struct stat32 *p32, s32; 1248 struct stat *p = NULL, s; 1249 1250 p32 = uap->ub; 1251 if (p32) { 1252 sg = stackgap_init(); 1253 p = stackgap_alloc(&sg, sizeof(struct stat)); 1254 uap->ub = (struct stat32 *)p; 1255 } 1256 error = stat(td, (struct stat_args *) uap); 1257 if (error) 1258 return (error); 1259 if (p32) { 1260 error = copyin(p, &s, sizeof(s)); 1261 if (error) 1262 return (error); 1263 copy_stat(&s, &s32); 1264 error = copyout(&s32, p32, sizeof(s32)); 1265 } 1266 return (error); 1267} 1268 1269int 1270freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1271{ 1272 int error; 1273 caddr_t sg; 1274 struct stat32 *p32, s32; 1275 struct stat *p = NULL, s; 1276 1277 p32 = uap->ub; 1278 if (p32) { 1279 sg = stackgap_init(); 1280 p = stackgap_alloc(&sg, sizeof(struct stat)); 1281 uap->ub = (struct stat32 *)p; 1282 } 1283 error = fstat(td, (struct fstat_args *) uap); 1284 if (error) 1285 return (error); 1286 if (p32) { 1287 error = copyin(p, &s, sizeof(s)); 1288 if (error) 1289 return (error); 1290 copy_stat(&s, &s32); 1291 error = copyout(&s32, p32, sizeof(s32)); 1292 } 1293 return (error); 1294} 1295 1296int 1297freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1298{ 1299 int error; 1300 caddr_t sg; 1301 struct stat32 *p32, s32; 1302 struct stat *p = NULL, s; 1303 1304 p32 = uap->ub; 1305 if (p32) { 1306 sg = stackgap_init(); 1307 p = stackgap_alloc(&sg, sizeof(struct stat)); 1308 uap->ub = (struct stat32 *)p; 1309 } 1310 error = lstat(td, (struct lstat_args *) uap); 1311 if (error) 1312 return (error); 1313 if (p32) { 1314 error = copyin(p, &s, sizeof(s)); 1315 if (error) 1316 return (error); 1317 copy_stat(&s, &s32); 1318 error = copyout(&s32, p32, sizeof(s32)); 1319 } 1320 return (error); 1321} 1322 1323/* 1324 * MPSAFE 1325 */ 1326int 1327freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1328{ 1329 int error, name[CTL_MAXNAME]; 1330 size_t j, oldlen; 1331 1332 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1333 return (EINVAL); 1334 1335 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 1336 if (error) 1337 return (error); 1338 1339 mtx_lock(&Giant); 1340 1341 if (uap->oldlenp) 1342 oldlen = fuword32(uap->oldlenp); 1343 else 1344 oldlen = 0; 1345 error = userland_sysctl(td, name, uap->namelen, 1346 uap->old, &oldlen, 1, 1347 uap->new, uap->newlen, &j); 1348 if (error && error != ENOMEM) 1349 goto done2; 1350 if (uap->oldlenp) { 1351 suword32(uap->oldlenp, j); 1352 } 1353done2: 1354 mtx_unlock(&Giant); 1355 return (error); 1356} 1357 1358struct sigaction32 { 1359 u_int32_t sa_u; 1360 int sa_flags; 1361 sigset_t sa_mask; 1362}; 1363 1364CTASSERT(sizeof(struct sigaction32) == 24); 1365 1366int 1367freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1368{ 1369 struct sigaction32 s32; 1370 struct sigaction sa, osa, *sap; 1371 int error; 1372 1373 if (uap->act) { 1374 error = copyin(uap->act, &s32, sizeof(s32)); 1375 if (error) 1376 return (error); 1377 sa.sa_handler = PTRIN(s32.sa_u); 1378 CP(s32, sa, sa_flags); 1379 CP(s32, sa, sa_mask); 1380 sap = &sa; 1381 } else 1382 sap = NULL; 1383 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1384 if (error != 0 && uap->oact != NULL) { 1385 s32.sa_u = PTROUT(osa.sa_handler); 1386 CP(osa, s32, sa_flags); 1387 CP(osa, s32, sa_mask); 1388 error = copyout(&s32, uap->oact, sizeof(s32)); 1389 } 1390 return (error); 1391} 1392 1393#ifdef COMPAT_FREEBSD4 1394int 1395freebsd4_freebsd32_sigaction(struct thread *td, 1396 struct freebsd4_freebsd32_sigaction_args *uap) 1397{ 1398 struct sigaction32 s32; 1399 struct sigaction sa, osa, *sap; 1400 int error; 1401 1402 if (uap->act) { 1403 error = copyin(uap->act, &s32, sizeof(s32)); 1404 if (error) 1405 return (error); 1406 sa.sa_handler = PTRIN(s32.sa_u); 1407 CP(s32, sa, sa_flags); 1408 CP(s32, sa, sa_mask); 1409 sap = &sa; 1410 } else 1411 sap = NULL; 1412 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1413 if (error != 0 && uap->oact != NULL) { 1414 s32.sa_u = PTROUT(osa.sa_handler); 1415 CP(osa, s32, sa_flags); 1416 CP(osa, s32, sa_mask); 1417 error = copyout(&s32, uap->oact, sizeof(s32)); 1418 } 1419 return (error); 1420} 1421#endif 1422 1423#if 0 1424 1425int 1426freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 1427{ 1428 int error; 1429 caddr_t sg; 1430 struct yyy32 *p32, s32; 1431 struct yyy *p = NULL, s; 1432 1433 p32 = uap->zzz; 1434 if (p32) { 1435 sg = stackgap_init(); 1436 p = stackgap_alloc(&sg, sizeof(struct yyy)); 1437 uap->zzz = (struct yyy32 *)p; 1438 error = copyin(p32, &s32, sizeof(s32)); 1439 if (error) 1440 return (error); 1441 /* translate in */ 1442 error = copyout(&s, p, sizeof(s)); 1443 if (error) 1444 return (error); 1445 } 1446 error = xxx(td, (struct xxx_args *) uap); 1447 if (error) 1448 return (error); 1449 if (p32) { 1450 error = copyin(p, &s, sizeof(s)); 1451 if (error) 1452 return (error); 1453 /* translate out */ 1454 error = copyout(&s32, p32, sizeof(s32)); 1455 } 1456 return (error); 1457} 1458 1459#endif 1460