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