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