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