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