freebsd32_misc.c revision 198507
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 198507 2009-10-27 10:47:58Z kib $"); 29 30#include "opt_compat.h" 31#include "opt_inet.h" 32#include "opt_inet6.h" 33 34#include <sys/param.h> 35#include <sys/bus.h> 36#include <sys/clock.h> 37#include <sys/exec.h> 38#include <sys/fcntl.h> 39#include <sys/filedesc.h> 40#include <sys/imgact.h> 41#include <sys/jail.h> 42#include <sys/kernel.h> 43#include <sys/limits.h> 44#include <sys/lock.h> 45#include <sys/malloc.h> 46#include <sys/file.h> /* Must come after sys/malloc.h */ 47#include <sys/mbuf.h> 48#include <sys/mman.h> 49#include <sys/module.h> 50#include <sys/mount.h> 51#include <sys/mutex.h> 52#include <sys/namei.h> 53#include <sys/proc.h> 54#include <sys/reboot.h> 55#include <sys/resource.h> 56#include <sys/resourcevar.h> 57#include <sys/selinfo.h> 58#include <sys/eventvar.h> /* Must come after sys/selinfo.h */ 59#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 60#include <sys/signal.h> 61#include <sys/signalvar.h> 62#include <sys/socket.h> 63#include <sys/socketvar.h> 64#include <sys/stat.h> 65#include <sys/syscall.h> 66#include <sys/syscallsubr.h> 67#include <sys/sysctl.h> 68#include <sys/sysent.h> 69#include <sys/sysproto.h> 70#include <sys/systm.h> 71#include <sys/thr.h> 72#include <sys/unistd.h> 73#include <sys/ucontext.h> 74#include <sys/vnode.h> 75#include <sys/wait.h> 76#include <sys/ipc.h> 77#include <sys/msg.h> 78#include <sys/sem.h> 79#include <sys/shm.h> 80 81#ifdef INET 82#include <netinet/in.h> 83#endif 84 85#include <vm/vm.h> 86#include <vm/vm_kern.h> 87#include <vm/vm_param.h> 88#include <vm/pmap.h> 89#include <vm/vm_map.h> 90#include <vm/vm_object.h> 91#include <vm/vm_extern.h> 92 93#include <machine/cpu.h> 94 95#include <security/audit/audit.h> 96 97#include <compat/freebsd32/freebsd32_util.h> 98#include <compat/freebsd32/freebsd32.h> 99#include <compat/freebsd32/freebsd32_ipc.h> 100#include <compat/freebsd32/freebsd32_signal.h> 101#include <compat/freebsd32/freebsd32_proto.h> 102 103CTASSERT(sizeof(struct timeval32) == 8); 104CTASSERT(sizeof(struct timespec32) == 8); 105CTASSERT(sizeof(struct itimerval32) == 16); 106CTASSERT(sizeof(struct statfs32) == 256); 107CTASSERT(sizeof(struct rusage32) == 72); 108CTASSERT(sizeof(struct sigaltstack32) == 12); 109CTASSERT(sizeof(struct kevent32) == 20); 110CTASSERT(sizeof(struct iovec32) == 8); 111CTASSERT(sizeof(struct msghdr32) == 28); 112CTASSERT(sizeof(struct stat32) == 96); 113CTASSERT(sizeof(struct sigaction32) == 24); 114 115static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 116static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 117 118int 119freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 120{ 121 int error, status; 122 struct rusage32 ru32; 123 struct rusage ru, *rup; 124 125 if (uap->rusage != NULL) 126 rup = &ru; 127 else 128 rup = NULL; 129 error = kern_wait(td, uap->pid, &status, uap->options, rup); 130 if (error) 131 return (error); 132 if (uap->status != NULL) 133 error = copyout(&status, uap->status, sizeof(status)); 134 if (uap->rusage != NULL && error == 0) { 135 TV_CP(ru, ru32, ru_utime); 136 TV_CP(ru, ru32, ru_stime); 137 CP(ru, ru32, ru_maxrss); 138 CP(ru, ru32, ru_ixrss); 139 CP(ru, ru32, ru_idrss); 140 CP(ru, ru32, ru_isrss); 141 CP(ru, ru32, ru_minflt); 142 CP(ru, ru32, ru_majflt); 143 CP(ru, ru32, ru_nswap); 144 CP(ru, ru32, ru_inblock); 145 CP(ru, ru32, ru_oublock); 146 CP(ru, ru32, ru_msgsnd); 147 CP(ru, ru32, ru_msgrcv); 148 CP(ru, ru32, ru_nsignals); 149 CP(ru, ru32, ru_nvcsw); 150 CP(ru, ru32, ru_nivcsw); 151 error = copyout(&ru32, uap->rusage, sizeof(ru32)); 152 } 153 return (error); 154} 155 156#ifdef COMPAT_FREEBSD4 157static void 158copy_statfs(struct statfs *in, struct statfs32 *out) 159{ 160 161 statfs_scale_blocks(in, INT32_MAX); 162 bzero(out, sizeof(*out)); 163 CP(*in, *out, f_bsize); 164 out->f_iosize = MIN(in->f_iosize, INT32_MAX); 165 CP(*in, *out, f_blocks); 166 CP(*in, *out, f_bfree); 167 CP(*in, *out, f_bavail); 168 out->f_files = MIN(in->f_files, INT32_MAX); 169 out->f_ffree = MIN(in->f_ffree, INT32_MAX); 170 CP(*in, *out, f_fsid); 171 CP(*in, *out, f_owner); 172 CP(*in, *out, f_type); 173 CP(*in, *out, f_flags); 174 out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX); 175 out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX); 176 strlcpy(out->f_fstypename, 177 in->f_fstypename, MFSNAMELEN); 178 strlcpy(out->f_mntonname, 179 in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 180 out->f_syncreads = MIN(in->f_syncreads, INT32_MAX); 181 out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX); 182 strlcpy(out->f_mntfromname, 183 in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 184} 185#endif 186 187#ifdef COMPAT_FREEBSD4 188int 189freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 190{ 191 struct statfs *buf, *sp; 192 struct statfs32 stat32; 193 size_t count, size; 194 int error; 195 196 count = uap->bufsize / sizeof(struct statfs32); 197 size = count * sizeof(struct statfs); 198 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 199 if (size > 0) { 200 count = td->td_retval[0]; 201 sp = buf; 202 while (count > 0 && error == 0) { 203 copy_statfs(sp, &stat32); 204 error = copyout(&stat32, uap->buf, sizeof(stat32)); 205 sp++; 206 uap->buf++; 207 count--; 208 } 209 free(buf, M_TEMP); 210 } 211 return (error); 212} 213#endif 214 215int 216freebsd32_sigaltstack(struct thread *td, 217 struct freebsd32_sigaltstack_args *uap) 218{ 219 struct sigaltstack32 s32; 220 struct sigaltstack ss, oss, *ssp; 221 int error; 222 223 if (uap->ss != NULL) { 224 error = copyin(uap->ss, &s32, sizeof(s32)); 225 if (error) 226 return (error); 227 PTRIN_CP(s32, ss, ss_sp); 228 CP(s32, ss, ss_size); 229 CP(s32, ss, ss_flags); 230 ssp = &ss; 231 } else 232 ssp = NULL; 233 error = kern_sigaltstack(td, ssp, &oss); 234 if (error == 0 && uap->oss != NULL) { 235 PTROUT_CP(oss, s32, ss_sp); 236 CP(oss, s32, ss_size); 237 CP(oss, s32, ss_flags); 238 error = copyout(&s32, uap->oss, sizeof(s32)); 239 } 240 return (error); 241} 242 243/* 244 * Custom version of exec_copyin_args() so that we can translate 245 * the pointers. 246 */ 247static int 248freebsd32_exec_copyin_args(struct image_args *args, char *fname, 249 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 250{ 251 char *argp, *envp; 252 u_int32_t *p32, arg; 253 size_t length; 254 int error; 255 256 bzero(args, sizeof(*args)); 257 if (argv == NULL) 258 return (EFAULT); 259 260 /* 261 * Allocate temporary demand zeroed space for argument and 262 * environment strings 263 */ 264 args->buf = (char *) kmem_alloc_wait(exec_map, 265 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 266 if (args->buf == NULL) 267 return (ENOMEM); 268 args->begin_argv = args->buf; 269 args->endp = args->begin_argv; 270 args->stringspace = ARG_MAX; 271 272 /* 273 * Copy the file name. 274 */ 275 if (fname != NULL) { 276 args->fname = args->buf + ARG_MAX; 277 error = (segflg == UIO_SYSSPACE) ? 278 copystr(fname, args->fname, PATH_MAX, &length) : 279 copyinstr(fname, args->fname, PATH_MAX, &length); 280 if (error != 0) 281 goto err_exit; 282 } else 283 args->fname = NULL; 284 285 /* 286 * extract arguments first 287 */ 288 p32 = argv; 289 for (;;) { 290 error = copyin(p32++, &arg, sizeof(arg)); 291 if (error) 292 goto err_exit; 293 if (arg == 0) 294 break; 295 argp = PTRIN(arg); 296 error = copyinstr(argp, args->endp, args->stringspace, &length); 297 if (error) { 298 if (error == ENAMETOOLONG) 299 error = E2BIG; 300 goto err_exit; 301 } 302 args->stringspace -= length; 303 args->endp += length; 304 args->argc++; 305 } 306 307 args->begin_envv = args->endp; 308 309 /* 310 * extract environment strings 311 */ 312 if (envv) { 313 p32 = envv; 314 for (;;) { 315 error = copyin(p32++, &arg, sizeof(arg)); 316 if (error) 317 goto err_exit; 318 if (arg == 0) 319 break; 320 envp = PTRIN(arg); 321 error = copyinstr(envp, args->endp, args->stringspace, 322 &length); 323 if (error) { 324 if (error == ENAMETOOLONG) 325 error = E2BIG; 326 goto err_exit; 327 } 328 args->stringspace -= length; 329 args->endp += length; 330 args->envc++; 331 } 332 } 333 334 return (0); 335 336err_exit: 337 kmem_free_wakeup(exec_map, (vm_offset_t)args->buf, 338 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 339 args->buf = NULL; 340 return (error); 341} 342 343int 344freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 345{ 346 struct image_args eargs; 347 int error; 348 349 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 350 uap->argv, uap->envv); 351 if (error == 0) 352 error = kern_execve(td, &eargs, NULL); 353 return (error); 354} 355 356int 357freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap) 358{ 359 struct image_args eargs; 360 int error; 361 362 error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE, 363 uap->argv, uap->envv); 364 if (error == 0) { 365 eargs.fd = uap->fd; 366 error = kern_execve(td, &eargs, NULL); 367 } 368 return (error); 369} 370 371#ifdef __ia64__ 372static int 373freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 374 int prot, int fd, off_t pos) 375{ 376 vm_map_t map; 377 vm_map_entry_t entry; 378 int rv; 379 380 map = &td->td_proc->p_vmspace->vm_map; 381 if (fd != -1) 382 prot |= VM_PROT_WRITE; 383 384 if (vm_map_lookup_entry(map, start, &entry)) { 385 if ((entry->protection & prot) != prot) { 386 rv = vm_map_protect(map, 387 trunc_page(start), 388 round_page(end), 389 entry->protection | prot, 390 FALSE); 391 if (rv != KERN_SUCCESS) 392 return (EINVAL); 393 } 394 } else { 395 vm_offset_t addr = trunc_page(start); 396 rv = vm_map_find(map, 0, 0, 397 &addr, PAGE_SIZE, FALSE, prot, 398 VM_PROT_ALL, 0); 399 if (rv != KERN_SUCCESS) 400 return (EINVAL); 401 } 402 403 if (fd != -1) { 404 struct pread_args r; 405 r.fd = fd; 406 r.buf = (void *) start; 407 r.nbyte = end - start; 408 r.offset = pos; 409 return (pread(td, &r)); 410 } else { 411 while (start < end) { 412 subyte((void *) start, 0); 413 start++; 414 } 415 return (0); 416 } 417} 418#endif 419 420int 421freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 422{ 423 struct mmap_args ap; 424 vm_offset_t addr = (vm_offset_t) uap->addr; 425 vm_size_t len = uap->len; 426 int prot = uap->prot; 427 int flags = uap->flags; 428 int fd = uap->fd; 429 off_t pos = (uap->poslo 430 | ((off_t)uap->poshi << 32)); 431#ifdef __ia64__ 432 vm_size_t pageoff; 433 int error; 434 435 /* 436 * Attempt to handle page size hassles. 437 */ 438 pageoff = (pos & PAGE_MASK); 439 if (flags & MAP_FIXED) { 440 vm_offset_t start, end; 441 start = addr; 442 end = addr + len; 443 444 if (start != trunc_page(start)) { 445 error = freebsd32_mmap_partial(td, start, 446 round_page(start), prot, 447 fd, pos); 448 if (fd != -1) 449 pos += round_page(start) - start; 450 start = round_page(start); 451 } 452 if (end != round_page(end)) { 453 vm_offset_t t = trunc_page(end); 454 error = freebsd32_mmap_partial(td, t, end, 455 prot, fd, 456 pos + t - start); 457 end = trunc_page(end); 458 } 459 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 460 /* 461 * We can't map this region at all. The specified 462 * address doesn't have the same alignment as the file 463 * position. Fake the mapping by simply reading the 464 * entire region into memory. First we need to make 465 * sure the region exists. 466 */ 467 vm_map_t map; 468 struct pread_args r; 469 int rv; 470 471 prot |= VM_PROT_WRITE; 472 map = &td->td_proc->p_vmspace->vm_map; 473 rv = vm_map_remove(map, start, end); 474 if (rv != KERN_SUCCESS) 475 return (EINVAL); 476 rv = vm_map_find(map, 0, 0, 477 &start, end - start, FALSE, 478 prot, VM_PROT_ALL, 0); 479 if (rv != KERN_SUCCESS) 480 return (EINVAL); 481 r.fd = fd; 482 r.buf = (void *) start; 483 r.nbyte = end - start; 484 r.offset = pos; 485 error = pread(td, &r); 486 if (error) 487 return (error); 488 489 td->td_retval[0] = addr; 490 return (0); 491 } 492 if (end == start) { 493 /* 494 * After dealing with the ragged ends, there 495 * might be none left. 496 */ 497 td->td_retval[0] = addr; 498 return (0); 499 } 500 addr = start; 501 len = end - start; 502 } 503#endif 504 505 ap.addr = (void *) addr; 506 ap.len = len; 507 ap.prot = prot; 508 ap.flags = flags; 509 ap.fd = fd; 510 ap.pos = pos; 511 512 return (mmap(td, &ap)); 513} 514 515#ifdef COMPAT_FREEBSD6 516int 517freebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap) 518{ 519 struct freebsd32_mmap_args ap; 520 521 ap.addr = uap->addr; 522 ap.len = uap->len; 523 ap.prot = uap->prot; 524 ap.flags = uap->flags; 525 ap.fd = uap->fd; 526 ap.poslo = uap->poslo; 527 ap.poshi = uap->poshi; 528 529 return (freebsd32_mmap(td, &ap)); 530} 531#endif 532 533int 534freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 535{ 536 struct itimerval itv, oitv, *itvp; 537 struct itimerval32 i32; 538 int error; 539 540 if (uap->itv != NULL) { 541 error = copyin(uap->itv, &i32, sizeof(i32)); 542 if (error) 543 return (error); 544 TV_CP(i32, itv, it_interval); 545 TV_CP(i32, itv, it_value); 546 itvp = &itv; 547 } else 548 itvp = NULL; 549 error = kern_setitimer(td, uap->which, itvp, &oitv); 550 if (error || uap->oitv == NULL) 551 return (error); 552 TV_CP(oitv, i32, it_interval); 553 TV_CP(oitv, i32, it_value); 554 return (copyout(&i32, uap->oitv, sizeof(i32))); 555} 556 557int 558freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 559{ 560 struct itimerval itv; 561 struct itimerval32 i32; 562 int error; 563 564 error = kern_getitimer(td, uap->which, &itv); 565 if (error || uap->itv == NULL) 566 return (error); 567 TV_CP(itv, i32, it_interval); 568 TV_CP(itv, i32, it_value); 569 return (copyout(&i32, uap->itv, sizeof(i32))); 570} 571 572int 573freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 574{ 575 struct timeval32 tv32; 576 struct timeval tv, *tvp; 577 int error; 578 579 if (uap->tv != NULL) { 580 error = copyin(uap->tv, &tv32, sizeof(tv32)); 581 if (error) 582 return (error); 583 CP(tv32, tv, tv_sec); 584 CP(tv32, tv, tv_usec); 585 tvp = &tv; 586 } else 587 tvp = NULL; 588 /* 589 * XXX big-endian needs to convert the fd_sets too. 590 * XXX Do pointers need PTRIN()? 591 */ 592 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp, 593 sizeof(int32_t) * 8)); 594} 595 596/* 597 * Copy 'count' items into the destination list pointed to by uap->eventlist. 598 */ 599static int 600freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 601{ 602 struct freebsd32_kevent_args *uap; 603 struct kevent32 ks32[KQ_NEVENTS]; 604 int i, error = 0; 605 606 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 607 uap = (struct freebsd32_kevent_args *)arg; 608 609 for (i = 0; i < count; i++) { 610 CP(kevp[i], ks32[i], ident); 611 CP(kevp[i], ks32[i], filter); 612 CP(kevp[i], ks32[i], flags); 613 CP(kevp[i], ks32[i], fflags); 614 CP(kevp[i], ks32[i], data); 615 PTROUT_CP(kevp[i], ks32[i], udata); 616 } 617 error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 618 if (error == 0) 619 uap->eventlist += count; 620 return (error); 621} 622 623/* 624 * Copy 'count' items from the list pointed to by uap->changelist. 625 */ 626static int 627freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 628{ 629 struct freebsd32_kevent_args *uap; 630 struct kevent32 ks32[KQ_NEVENTS]; 631 int i, error = 0; 632 633 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 634 uap = (struct freebsd32_kevent_args *)arg; 635 636 error = copyin(uap->changelist, ks32, count * sizeof *ks32); 637 if (error) 638 goto done; 639 uap->changelist += count; 640 641 for (i = 0; i < count; i++) { 642 CP(ks32[i], kevp[i], ident); 643 CP(ks32[i], kevp[i], filter); 644 CP(ks32[i], kevp[i], flags); 645 CP(ks32[i], kevp[i], fflags); 646 CP(ks32[i], kevp[i], data); 647 PTRIN_CP(ks32[i], kevp[i], udata); 648 } 649done: 650 return (error); 651} 652 653int 654freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 655{ 656 struct timespec32 ts32; 657 struct timespec ts, *tsp; 658 struct kevent_copyops k_ops = { uap, 659 freebsd32_kevent_copyout, 660 freebsd32_kevent_copyin}; 661 int error; 662 663 664 if (uap->timeout) { 665 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 666 if (error) 667 return (error); 668 CP(ts32, ts, tv_sec); 669 CP(ts32, ts, tv_nsec); 670 tsp = &ts; 671 } else 672 tsp = NULL; 673 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 674 &k_ops, tsp); 675 return (error); 676} 677 678int 679freebsd32_gettimeofday(struct thread *td, 680 struct freebsd32_gettimeofday_args *uap) 681{ 682 struct timeval atv; 683 struct timeval32 atv32; 684 struct timezone rtz; 685 int error = 0; 686 687 if (uap->tp) { 688 microtime(&atv); 689 CP(atv, atv32, tv_sec); 690 CP(atv, atv32, tv_usec); 691 error = copyout(&atv32, uap->tp, sizeof (atv32)); 692 } 693 if (error == 0 && uap->tzp != NULL) { 694 rtz.tz_minuteswest = tz_minuteswest; 695 rtz.tz_dsttime = tz_dsttime; 696 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 697 } 698 return (error); 699} 700 701int 702freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 703{ 704 struct rusage32 s32; 705 struct rusage s; 706 int error; 707 708 error = kern_getrusage(td, uap->who, &s); 709 if (error) 710 return (error); 711 if (uap->rusage != NULL) { 712 TV_CP(s, s32, ru_utime); 713 TV_CP(s, s32, ru_stime); 714 CP(s, s32, ru_maxrss); 715 CP(s, s32, ru_ixrss); 716 CP(s, s32, ru_idrss); 717 CP(s, s32, ru_isrss); 718 CP(s, s32, ru_minflt); 719 CP(s, s32, ru_majflt); 720 CP(s, s32, ru_nswap); 721 CP(s, s32, ru_inblock); 722 CP(s, s32, ru_oublock); 723 CP(s, s32, ru_msgsnd); 724 CP(s, s32, ru_msgrcv); 725 CP(s, s32, ru_nsignals); 726 CP(s, s32, ru_nvcsw); 727 CP(s, s32, ru_nivcsw); 728 error = copyout(&s32, uap->rusage, sizeof(s32)); 729 } 730 return (error); 731} 732 733static int 734freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 735{ 736 struct iovec32 iov32; 737 struct iovec *iov; 738 struct uio *uio; 739 u_int iovlen; 740 int error, i; 741 742 *uiop = NULL; 743 if (iovcnt > UIO_MAXIOV) 744 return (EINVAL); 745 iovlen = iovcnt * sizeof(struct iovec); 746 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 747 iov = (struct iovec *)(uio + 1); 748 for (i = 0; i < iovcnt; i++) { 749 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 750 if (error) { 751 free(uio, M_IOV); 752 return (error); 753 } 754 iov[i].iov_base = PTRIN(iov32.iov_base); 755 iov[i].iov_len = iov32.iov_len; 756 } 757 uio->uio_iov = iov; 758 uio->uio_iovcnt = iovcnt; 759 uio->uio_segflg = UIO_USERSPACE; 760 uio->uio_offset = -1; 761 uio->uio_resid = 0; 762 for (i = 0; i < iovcnt; i++) { 763 if (iov->iov_len > INT_MAX - uio->uio_resid) { 764 free(uio, M_IOV); 765 return (EINVAL); 766 } 767 uio->uio_resid += iov->iov_len; 768 iov++; 769 } 770 *uiop = uio; 771 return (0); 772} 773 774int 775freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 776{ 777 struct uio *auio; 778 int error; 779 780 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 781 if (error) 782 return (error); 783 error = kern_readv(td, uap->fd, auio); 784 free(auio, M_IOV); 785 return (error); 786} 787 788int 789freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 790{ 791 struct uio *auio; 792 int error; 793 794 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 795 if (error) 796 return (error); 797 error = kern_writev(td, uap->fd, auio); 798 free(auio, M_IOV); 799 return (error); 800} 801 802int 803freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap) 804{ 805 struct uio *auio; 806 int error; 807 808 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 809 if (error) 810 return (error); 811 error = kern_preadv(td, uap->fd, auio, uap->offset); 812 free(auio, M_IOV); 813 return (error); 814} 815 816int 817freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) 818{ 819 struct uio *auio; 820 int error; 821 822 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 823 if (error) 824 return (error); 825 error = kern_pwritev(td, uap->fd, auio, uap->offset); 826 free(auio, M_IOV); 827 return (error); 828} 829 830static int 831freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp, 832 int error) 833{ 834 struct iovec32 iov32; 835 struct iovec *iov; 836 u_int iovlen; 837 int i; 838 839 *iovp = NULL; 840 if (iovcnt > UIO_MAXIOV) 841 return (error); 842 iovlen = iovcnt * sizeof(struct iovec); 843 iov = malloc(iovlen, M_IOV, M_WAITOK); 844 for (i = 0; i < iovcnt; i++) { 845 error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32)); 846 if (error) { 847 free(iov, M_IOV); 848 return (error); 849 } 850 iov[i].iov_base = PTRIN(iov32.iov_base); 851 iov[i].iov_len = iov32.iov_len; 852 } 853 *iovp = iov; 854 return (0); 855} 856 857static int 858freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg) 859{ 860 struct msghdr32 m32; 861 int error; 862 863 error = copyin(msg32, &m32, sizeof(m32)); 864 if (error) 865 return (error); 866 msg->msg_name = PTRIN(m32.msg_name); 867 msg->msg_namelen = m32.msg_namelen; 868 msg->msg_iov = PTRIN(m32.msg_iov); 869 msg->msg_iovlen = m32.msg_iovlen; 870 msg->msg_control = PTRIN(m32.msg_control); 871 msg->msg_controllen = m32.msg_controllen; 872 msg->msg_flags = m32.msg_flags; 873 return (0); 874} 875 876static int 877freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32) 878{ 879 struct msghdr32 m32; 880 int error; 881 882 m32.msg_name = PTROUT(msg->msg_name); 883 m32.msg_namelen = msg->msg_namelen; 884 m32.msg_iov = PTROUT(msg->msg_iov); 885 m32.msg_iovlen = msg->msg_iovlen; 886 m32.msg_control = PTROUT(msg->msg_control); 887 m32.msg_controllen = msg->msg_controllen; 888 m32.msg_flags = msg->msg_flags; 889 error = copyout(&m32, msg32, sizeof(m32)); 890 return (error); 891} 892 893#define FREEBSD32_ALIGNBYTES (sizeof(int) - 1) 894#define FREEBSD32_ALIGN(p) \ 895 (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES) 896#define FREEBSD32_CMSG_SPACE(l) \ 897 (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l)) 898 899#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ 900 FREEBSD32_ALIGN(sizeof(struct cmsghdr))) 901static int 902freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) 903{ 904 struct cmsghdr *cm; 905 void *data; 906 socklen_t clen, datalen; 907 int error; 908 caddr_t ctlbuf; 909 int len, maxlen, copylen; 910 struct mbuf *m; 911 error = 0; 912 913 len = msg->msg_controllen; 914 maxlen = msg->msg_controllen; 915 msg->msg_controllen = 0; 916 917 m = control; 918 ctlbuf = msg->msg_control; 919 920 while (m && len > 0) { 921 cm = mtod(m, struct cmsghdr *); 922 clen = m->m_len; 923 924 while (cm != NULL) { 925 926 if (sizeof(struct cmsghdr) > clen || 927 cm->cmsg_len > clen) { 928 error = EINVAL; 929 break; 930 } 931 932 data = CMSG_DATA(cm); 933 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 934 935 /* Adjust message length */ 936 cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + 937 datalen; 938 939 940 /* Copy cmsghdr */ 941 copylen = sizeof(struct cmsghdr); 942 if (len < copylen) { 943 msg->msg_flags |= MSG_CTRUNC; 944 copylen = len; 945 } 946 947 error = copyout(cm,ctlbuf,copylen); 948 if (error) 949 goto exit; 950 951 ctlbuf += FREEBSD32_ALIGN(copylen); 952 len -= FREEBSD32_ALIGN(copylen); 953 954 if (len <= 0) 955 break; 956 957 /* Copy data */ 958 copylen = datalen; 959 if (len < copylen) { 960 msg->msg_flags |= MSG_CTRUNC; 961 copylen = len; 962 } 963 964 error = copyout(data,ctlbuf,copylen); 965 if (error) 966 goto exit; 967 968 ctlbuf += FREEBSD32_ALIGN(copylen); 969 len -= FREEBSD32_ALIGN(copylen); 970 971 if (CMSG_SPACE(datalen) < clen) { 972 clen -= CMSG_SPACE(datalen); 973 cm = (struct cmsghdr *) 974 ((caddr_t)cm + CMSG_SPACE(datalen)); 975 } else { 976 clen = 0; 977 cm = NULL; 978 } 979 } 980 m = m->m_next; 981 } 982 983 msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control; 984 985exit: 986 return (error); 987 988} 989 990int 991freebsd32_recvmsg(td, uap) 992 struct thread *td; 993 struct freebsd32_recvmsg_args /* { 994 int s; 995 struct msghdr32 *msg; 996 int flags; 997 } */ *uap; 998{ 999 struct msghdr msg; 1000 struct msghdr32 m32; 1001 struct iovec *uiov, *iov; 1002 struct mbuf *control = NULL; 1003 struct mbuf **controlp; 1004 1005 int error; 1006 error = copyin(uap->msg, &m32, sizeof(m32)); 1007 if (error) 1008 return (error); 1009 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1010 if (error) 1011 return (error); 1012 error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov, 1013 EMSGSIZE); 1014 if (error) 1015 return (error); 1016 msg.msg_flags = uap->flags; 1017 uiov = msg.msg_iov; 1018 msg.msg_iov = iov; 1019 1020 controlp = (msg.msg_control != NULL) ? &control : NULL; 1021 error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp); 1022 if (error == 0) { 1023 msg.msg_iov = uiov; 1024 1025 if (control != NULL) 1026 error = freebsd32_copy_msg_out(&msg, control); 1027 1028 if (error == 0) 1029 error = freebsd32_copyoutmsghdr(&msg, uap->msg); 1030 } 1031 free(iov, M_IOV); 1032 1033 if (control != NULL) 1034 m_freem(control); 1035 1036 return (error); 1037} 1038 1039 1040static int 1041freebsd32_convert_msg_in(struct mbuf **controlp) 1042{ 1043 struct mbuf *control = *controlp; 1044 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 1045 void *data; 1046 socklen_t clen = control->m_len, datalen; 1047 int error; 1048 1049 error = 0; 1050 *controlp = NULL; 1051 1052 while (cm != NULL) { 1053 if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) { 1054 error = EINVAL; 1055 break; 1056 } 1057 1058 data = FREEBSD32_CMSG_DATA(cm); 1059 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1060 1061 *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type, 1062 cm->cmsg_level); 1063 controlp = &(*controlp)->m_next; 1064 1065 if (FREEBSD32_CMSG_SPACE(datalen) < clen) { 1066 clen -= FREEBSD32_CMSG_SPACE(datalen); 1067 cm = (struct cmsghdr *) 1068 ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen)); 1069 } else { 1070 clen = 0; 1071 cm = NULL; 1072 } 1073 } 1074 1075 m_freem(control); 1076 return (error); 1077} 1078 1079 1080int 1081freebsd32_sendmsg(struct thread *td, 1082 struct freebsd32_sendmsg_args *uap) 1083{ 1084 struct msghdr msg; 1085 struct msghdr32 m32; 1086 struct iovec *iov; 1087 struct mbuf *control = NULL; 1088 struct sockaddr *to = NULL; 1089 int error; 1090 1091 error = copyin(uap->msg, &m32, sizeof(m32)); 1092 if (error) 1093 return (error); 1094 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1095 if (error) 1096 return (error); 1097 error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov, 1098 EMSGSIZE); 1099 if (error) 1100 return (error); 1101 msg.msg_iov = iov; 1102 if (msg.msg_name != NULL) { 1103 error = getsockaddr(&to, msg.msg_name, msg.msg_namelen); 1104 if (error) { 1105 to = NULL; 1106 goto out; 1107 } 1108 msg.msg_name = to; 1109 } 1110 1111 if (msg.msg_control) { 1112 if (msg.msg_controllen < sizeof(struct cmsghdr)) { 1113 error = EINVAL; 1114 goto out; 1115 } 1116 1117 error = sockargs(&control, msg.msg_control, 1118 msg.msg_controllen, MT_CONTROL); 1119 if (error) 1120 goto out; 1121 1122 error = freebsd32_convert_msg_in(&control); 1123 if (error) 1124 goto out; 1125 } 1126 1127 error = kern_sendit(td, uap->s, &msg, uap->flags, control, 1128 UIO_USERSPACE); 1129 1130out: 1131 free(iov, M_IOV); 1132 if (to) 1133 free(to, M_SONAME); 1134 return (error); 1135} 1136 1137int 1138freebsd32_recvfrom(struct thread *td, 1139 struct freebsd32_recvfrom_args *uap) 1140{ 1141 struct msghdr msg; 1142 struct iovec aiov; 1143 int error; 1144 1145 if (uap->fromlenaddr) { 1146 error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen, 1147 sizeof(msg.msg_namelen)); 1148 if (error) 1149 return (error); 1150 } else { 1151 msg.msg_namelen = 0; 1152 } 1153 1154 msg.msg_name = PTRIN(uap->from); 1155 msg.msg_iov = &aiov; 1156 msg.msg_iovlen = 1; 1157 aiov.iov_base = PTRIN(uap->buf); 1158 aiov.iov_len = uap->len; 1159 msg.msg_control = NULL; 1160 msg.msg_flags = uap->flags; 1161 error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL); 1162 if (error == 0 && uap->fromlenaddr) 1163 error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr), 1164 sizeof (msg.msg_namelen)); 1165 return (error); 1166} 1167 1168int 1169freebsd32_settimeofday(struct thread *td, 1170 struct freebsd32_settimeofday_args *uap) 1171{ 1172 struct timeval32 tv32; 1173 struct timeval tv, *tvp; 1174 struct timezone tz, *tzp; 1175 int error; 1176 1177 if (uap->tv) { 1178 error = copyin(uap->tv, &tv32, sizeof(tv32)); 1179 if (error) 1180 return (error); 1181 CP(tv32, tv, tv_sec); 1182 CP(tv32, tv, tv_usec); 1183 tvp = &tv; 1184 } else 1185 tvp = NULL; 1186 if (uap->tzp) { 1187 error = copyin(uap->tzp, &tz, sizeof(tz)); 1188 if (error) 1189 return (error); 1190 tzp = &tz; 1191 } else 1192 tzp = NULL; 1193 return (kern_settimeofday(td, tvp, tzp)); 1194} 1195 1196int 1197freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 1198{ 1199 struct timeval32 s32[2]; 1200 struct timeval s[2], *sp; 1201 int error; 1202 1203 if (uap->tptr != NULL) { 1204 error = copyin(uap->tptr, s32, sizeof(s32)); 1205 if (error) 1206 return (error); 1207 CP(s32[0], s[0], tv_sec); 1208 CP(s32[0], s[0], tv_usec); 1209 CP(s32[1], s[1], tv_sec); 1210 CP(s32[1], s[1], tv_usec); 1211 sp = s; 1212 } else 1213 sp = NULL; 1214 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1215} 1216 1217int 1218freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap) 1219{ 1220 struct timeval32 s32[2]; 1221 struct timeval s[2], *sp; 1222 int error; 1223 1224 if (uap->tptr != NULL) { 1225 error = copyin(uap->tptr, s32, sizeof(s32)); 1226 if (error) 1227 return (error); 1228 CP(s32[0], s[0], tv_sec); 1229 CP(s32[0], s[0], tv_usec); 1230 CP(s32[1], s[1], tv_sec); 1231 CP(s32[1], s[1], tv_usec); 1232 sp = s; 1233 } else 1234 sp = NULL; 1235 return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1236} 1237 1238int 1239freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap) 1240{ 1241 struct timeval32 s32[2]; 1242 struct timeval s[2], *sp; 1243 int error; 1244 1245 if (uap->tptr != NULL) { 1246 error = copyin(uap->tptr, s32, sizeof(s32)); 1247 if (error) 1248 return (error); 1249 CP(s32[0], s[0], tv_sec); 1250 CP(s32[0], s[0], tv_usec); 1251 CP(s32[1], s[1], tv_sec); 1252 CP(s32[1], s[1], tv_usec); 1253 sp = s; 1254 } else 1255 sp = NULL; 1256 return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE)); 1257} 1258 1259int 1260freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap) 1261{ 1262 struct timeval32 s32[2]; 1263 struct timeval s[2], *sp; 1264 int error; 1265 1266 if (uap->times != NULL) { 1267 error = copyin(uap->times, s32, sizeof(s32)); 1268 if (error) 1269 return (error); 1270 CP(s32[0], s[0], tv_sec); 1271 CP(s32[0], s[0], tv_usec); 1272 CP(s32[1], s[1], tv_sec); 1273 CP(s32[1], s[1], tv_usec); 1274 sp = s; 1275 } else 1276 sp = NULL; 1277 return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE, 1278 sp, UIO_SYSSPACE)); 1279} 1280 1281int 1282freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 1283{ 1284 struct timeval32 tv32; 1285 struct timeval delta, olddelta, *deltap; 1286 int error; 1287 1288 if (uap->delta) { 1289 error = copyin(uap->delta, &tv32, sizeof(tv32)); 1290 if (error) 1291 return (error); 1292 CP(tv32, delta, tv_sec); 1293 CP(tv32, delta, tv_usec); 1294 deltap = δ 1295 } else 1296 deltap = NULL; 1297 error = kern_adjtime(td, deltap, &olddelta); 1298 if (uap->olddelta && error == 0) { 1299 CP(olddelta, tv32, tv_sec); 1300 CP(olddelta, tv32, tv_usec); 1301 error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 1302 } 1303 return (error); 1304} 1305 1306#ifdef COMPAT_FREEBSD4 1307int 1308freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 1309{ 1310 struct statfs32 s32; 1311 struct statfs s; 1312 int error; 1313 1314 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 1315 if (error) 1316 return (error); 1317 copy_statfs(&s, &s32); 1318 return (copyout(&s32, uap->buf, sizeof(s32))); 1319} 1320#endif 1321 1322#ifdef COMPAT_FREEBSD4 1323int 1324freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 1325{ 1326 struct statfs32 s32; 1327 struct statfs s; 1328 int error; 1329 1330 error = kern_fstatfs(td, uap->fd, &s); 1331 if (error) 1332 return (error); 1333 copy_statfs(&s, &s32); 1334 return (copyout(&s32, uap->buf, sizeof(s32))); 1335} 1336#endif 1337 1338#ifdef COMPAT_FREEBSD4 1339int 1340freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 1341{ 1342 struct statfs32 s32; 1343 struct statfs s; 1344 fhandle_t fh; 1345 int error; 1346 1347 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 1348 return (error); 1349 error = kern_fhstatfs(td, fh, &s); 1350 if (error) 1351 return (error); 1352 copy_statfs(&s, &s32); 1353 return (copyout(&s32, uap->buf, sizeof(s32))); 1354} 1355#endif 1356 1357#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1358 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1359static void 1360freebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, struct ipc_perm *ip) 1361{ 1362 1363 CP(*ip32, *ip, cuid); 1364 CP(*ip32, *ip, cgid); 1365 CP(*ip32, *ip, uid); 1366 CP(*ip32, *ip, gid); 1367 CP(*ip32, *ip, mode); 1368 CP(*ip32, *ip, seq); 1369 CP(*ip32, *ip, key); 1370} 1371 1372static void 1373freebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm32_old *ip32) 1374{ 1375 1376 CP(*ip, *ip32, cuid); 1377 CP(*ip, *ip32, cgid); 1378 CP(*ip, *ip32, uid); 1379 CP(*ip, *ip32, gid); 1380 CP(*ip, *ip32, mode); 1381 CP(*ip, *ip32, seq); 1382 CP(*ip, *ip32, key); 1383} 1384#endif 1385 1386static void 1387freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip) 1388{ 1389 1390 CP(*ip32, *ip, cuid); 1391 CP(*ip32, *ip, cgid); 1392 CP(*ip32, *ip, uid); 1393 CP(*ip32, *ip, gid); 1394 CP(*ip32, *ip, mode); 1395 CP(*ip32, *ip, seq); 1396 CP(*ip32, *ip, key); 1397} 1398 1399static void 1400freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32) 1401{ 1402 1403 CP(*ip, *ip32, cuid); 1404 CP(*ip, *ip32, cgid); 1405 CP(*ip, *ip32, uid); 1406 CP(*ip, *ip32, gid); 1407 CP(*ip, *ip32, mode); 1408 CP(*ip, *ip32, seq); 1409 CP(*ip, *ip32, key); 1410} 1411 1412int 1413freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1414{ 1415 1416#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1417 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1418 switch (uap->which) { 1419 case 0: 1420 return (freebsd7_freebsd32_semctl(td, 1421 (struct freebsd7_freebsd32_semctl_args *)&uap->a2)); 1422 default: 1423 return (semsys(td, (struct semsys_args *)uap)); 1424 } 1425#else 1426 return (nosys(td, NULL)); 1427#endif 1428} 1429 1430#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1431 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1432int 1433freebsd7_freebsd32_semctl(struct thread *td, 1434 struct freebsd7_freebsd32_semctl_args *uap) 1435{ 1436 struct semid_ds32_old dsbuf32; 1437 struct semid_ds dsbuf; 1438 union semun semun; 1439 union semun32 arg; 1440 register_t rval; 1441 int error; 1442 1443 switch (uap->cmd) { 1444 case SEM_STAT: 1445 case IPC_SET: 1446 case IPC_STAT: 1447 case GETALL: 1448 case SETVAL: 1449 case SETALL: 1450 error = copyin(uap->arg, &arg, sizeof(arg)); 1451 if (error) 1452 return (error); 1453 break; 1454 } 1455 1456 switch (uap->cmd) { 1457 case SEM_STAT: 1458 case IPC_STAT: 1459 semun.buf = &dsbuf; 1460 break; 1461 case IPC_SET: 1462 error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32)); 1463 if (error) 1464 return (error); 1465 freebsd32_ipcperm_old_in(&dsbuf32.sem_perm, &dsbuf.sem_perm); 1466 PTRIN_CP(dsbuf32, dsbuf, sem_base); 1467 CP(dsbuf32, dsbuf, sem_nsems); 1468 CP(dsbuf32, dsbuf, sem_otime); 1469 CP(dsbuf32, dsbuf, sem_ctime); 1470 semun.buf = &dsbuf; 1471 break; 1472 case GETALL: 1473 case SETALL: 1474 semun.array = PTRIN(arg.array); 1475 break; 1476 case SETVAL: 1477 semun.val = arg.val; 1478 break; 1479 } 1480 1481 error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun, 1482 &rval); 1483 if (error) 1484 return (error); 1485 1486 switch (uap->cmd) { 1487 case SEM_STAT: 1488 case IPC_STAT: 1489 bzero(&dsbuf32, sizeof(dsbuf32)); 1490 freebsd32_ipcperm_old_out(&dsbuf.sem_perm, &dsbuf32.sem_perm); 1491 PTROUT_CP(dsbuf, dsbuf32, sem_base); 1492 CP(dsbuf, dsbuf32, sem_nsems); 1493 CP(dsbuf, dsbuf32, sem_otime); 1494 CP(dsbuf, dsbuf32, sem_ctime); 1495 error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32)); 1496 break; 1497 } 1498 1499 if (error == 0) 1500 td->td_retval[0] = rval; 1501 return (error); 1502} 1503#endif 1504 1505int 1506freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap) 1507{ 1508 struct semid_ds32 dsbuf32; 1509 struct semid_ds dsbuf; 1510 union semun semun; 1511 union semun32 arg; 1512 register_t rval; 1513 int error; 1514 1515 switch (uap->cmd) { 1516 case SEM_STAT: 1517 case IPC_SET: 1518 case IPC_STAT: 1519 case GETALL: 1520 case SETVAL: 1521 case SETALL: 1522 error = copyin(uap->arg, &arg, sizeof(arg)); 1523 if (error) 1524 return (error); 1525 break; 1526 } 1527 1528 switch (uap->cmd) { 1529 case SEM_STAT: 1530 case IPC_STAT: 1531 semun.buf = &dsbuf; 1532 break; 1533 case IPC_SET: 1534 error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32)); 1535 if (error) 1536 return (error); 1537 freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm); 1538 PTRIN_CP(dsbuf32, dsbuf, sem_base); 1539 CP(dsbuf32, dsbuf, sem_nsems); 1540 CP(dsbuf32, dsbuf, sem_otime); 1541 CP(dsbuf32, dsbuf, sem_ctime); 1542 semun.buf = &dsbuf; 1543 break; 1544 case GETALL: 1545 case SETALL: 1546 semun.array = PTRIN(arg.array); 1547 break; 1548 case SETVAL: 1549 semun.val = arg.val; 1550 break; 1551 } 1552 1553 error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun, 1554 &rval); 1555 if (error) 1556 return (error); 1557 1558 switch (uap->cmd) { 1559 case SEM_STAT: 1560 case IPC_STAT: 1561 bzero(&dsbuf32, sizeof(dsbuf32)); 1562 freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm); 1563 PTROUT_CP(dsbuf, dsbuf32, sem_base); 1564 CP(dsbuf, dsbuf32, sem_nsems); 1565 CP(dsbuf, dsbuf32, sem_otime); 1566 CP(dsbuf, dsbuf32, sem_ctime); 1567 error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32)); 1568 break; 1569 } 1570 1571 if (error == 0) 1572 td->td_retval[0] = rval; 1573 return (error); 1574} 1575 1576int 1577freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1578{ 1579 1580#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1581 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1582 switch (uap->which) { 1583 case 0: 1584 return (freebsd7_freebsd32_msgctl(td, 1585 (struct freebsd7_freebsd32_msgctl_args *)&uap->a2)); 1586 case 2: 1587 return (freebsd32_msgsnd(td, 1588 (struct freebsd32_msgsnd_args *)&uap->a2)); 1589 case 3: 1590 return (freebsd32_msgrcv(td, 1591 (struct freebsd32_msgrcv_args *)&uap->a2)); 1592 default: 1593 return (msgsys(td, (struct msgsys_args *)uap)); 1594 } 1595#else 1596 return (nosys(td, NULL)); 1597#endif 1598} 1599 1600#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1601 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1602int 1603freebsd7_freebsd32_msgctl(struct thread *td, 1604 struct freebsd7_freebsd32_msgctl_args *uap) 1605{ 1606 struct msqid_ds msqbuf; 1607 struct msqid_ds32_old msqbuf32; 1608 int error; 1609 1610 if (uap->cmd == IPC_SET) { 1611 error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32)); 1612 if (error) 1613 return (error); 1614 freebsd32_ipcperm_old_in(&msqbuf32.msg_perm, &msqbuf.msg_perm); 1615 PTRIN_CP(msqbuf32, msqbuf, msg_first); 1616 PTRIN_CP(msqbuf32, msqbuf, msg_last); 1617 CP(msqbuf32, msqbuf, msg_cbytes); 1618 CP(msqbuf32, msqbuf, msg_qnum); 1619 CP(msqbuf32, msqbuf, msg_qbytes); 1620 CP(msqbuf32, msqbuf, msg_lspid); 1621 CP(msqbuf32, msqbuf, msg_lrpid); 1622 CP(msqbuf32, msqbuf, msg_stime); 1623 CP(msqbuf32, msqbuf, msg_rtime); 1624 CP(msqbuf32, msqbuf, msg_ctime); 1625 } 1626 error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf); 1627 if (error) 1628 return (error); 1629 if (uap->cmd == IPC_STAT) { 1630 bzero(&msqbuf32, sizeof(msqbuf32)); 1631 freebsd32_ipcperm_old_out(&msqbuf.msg_perm, &msqbuf32.msg_perm); 1632 PTROUT_CP(msqbuf, msqbuf32, msg_first); 1633 PTROUT_CP(msqbuf, msqbuf32, msg_last); 1634 CP(msqbuf, msqbuf32, msg_cbytes); 1635 CP(msqbuf, msqbuf32, msg_qnum); 1636 CP(msqbuf, msqbuf32, msg_qbytes); 1637 CP(msqbuf, msqbuf32, msg_lspid); 1638 CP(msqbuf, msqbuf32, msg_lrpid); 1639 CP(msqbuf, msqbuf32, msg_stime); 1640 CP(msqbuf, msqbuf32, msg_rtime); 1641 CP(msqbuf, msqbuf32, msg_ctime); 1642 error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32)); 1643 } 1644 return (error); 1645} 1646#endif 1647 1648int 1649freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap) 1650{ 1651 struct msqid_ds msqbuf; 1652 struct msqid_ds32 msqbuf32; 1653 int error; 1654 1655 if (uap->cmd == IPC_SET) { 1656 error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32)); 1657 if (error) 1658 return (error); 1659 freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm); 1660 PTRIN_CP(msqbuf32, msqbuf, msg_first); 1661 PTRIN_CP(msqbuf32, msqbuf, msg_last); 1662 CP(msqbuf32, msqbuf, msg_cbytes); 1663 CP(msqbuf32, msqbuf, msg_qnum); 1664 CP(msqbuf32, msqbuf, msg_qbytes); 1665 CP(msqbuf32, msqbuf, msg_lspid); 1666 CP(msqbuf32, msqbuf, msg_lrpid); 1667 CP(msqbuf32, msqbuf, msg_stime); 1668 CP(msqbuf32, msqbuf, msg_rtime); 1669 CP(msqbuf32, msqbuf, msg_ctime); 1670 } 1671 error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf); 1672 if (error) 1673 return (error); 1674 if (uap->cmd == IPC_STAT) { 1675 freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm); 1676 PTROUT_CP(msqbuf, msqbuf32, msg_first); 1677 PTROUT_CP(msqbuf, msqbuf32, msg_last); 1678 CP(msqbuf, msqbuf32, msg_cbytes); 1679 CP(msqbuf, msqbuf32, msg_qnum); 1680 CP(msqbuf, msqbuf32, msg_qbytes); 1681 CP(msqbuf, msqbuf32, msg_lspid); 1682 CP(msqbuf, msqbuf32, msg_lrpid); 1683 CP(msqbuf, msqbuf32, msg_stime); 1684 CP(msqbuf, msqbuf32, msg_rtime); 1685 CP(msqbuf, msqbuf32, msg_ctime); 1686 error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32)); 1687 } 1688 return (error); 1689} 1690 1691int 1692freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap) 1693{ 1694 const void *msgp; 1695 long mtype; 1696 int32_t mtype32; 1697 int error; 1698 1699 msgp = PTRIN(uap->msgp); 1700 if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0) 1701 return (error); 1702 mtype = mtype32; 1703 return (kern_msgsnd(td, uap->msqid, 1704 (const char *)msgp + sizeof(mtype32), 1705 uap->msgsz, uap->msgflg, mtype)); 1706} 1707 1708int 1709freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap) 1710{ 1711 void *msgp; 1712 long mtype; 1713 int32_t mtype32; 1714 int error; 1715 1716 msgp = PTRIN(uap->msgp); 1717 if ((error = kern_msgrcv(td, uap->msqid, 1718 (char *)msgp + sizeof(mtype32), uap->msgsz, 1719 uap->msgtyp, uap->msgflg, &mtype)) != 0) 1720 return (error); 1721 mtype32 = (int32_t)mtype; 1722 return (copyout(&mtype32, msgp, sizeof(mtype32))); 1723} 1724 1725int 1726freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1727{ 1728 1729#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1730 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1731 switch (uap->which) { 1732 case 0: { /* shmat */ 1733 struct shmat_args ap; 1734 1735 ap.shmid = uap->a2; 1736 ap.shmaddr = PTRIN(uap->a3); 1737 ap.shmflg = uap->a4; 1738 return (sysent[SYS_shmat].sy_call(td, &ap)); 1739 } 1740 case 2: { /* shmdt */ 1741 struct shmdt_args ap; 1742 1743 ap.shmaddr = PTRIN(uap->a2); 1744 return (sysent[SYS_shmdt].sy_call(td, &ap)); 1745 } 1746 case 3: { /* shmget */ 1747 struct shmget_args ap; 1748 1749 ap.key = uap->a2; 1750 ap.size = uap->a3; 1751 ap.shmflg = uap->a4; 1752 return (sysent[SYS_shmget].sy_call(td, &ap)); 1753 } 1754 case 4: { /* shmctl */ 1755 struct freebsd7_freebsd32_shmctl_args ap; 1756 1757 ap.shmid = uap->a2; 1758 ap.cmd = uap->a3; 1759 ap.buf = PTRIN(uap->a4); 1760 return (freebsd7_freebsd32_shmctl(td, &ap)); 1761 } 1762 case 1: /* oshmctl */ 1763 default: 1764 return (EINVAL); 1765 } 1766#else 1767 return (nosys(td, NULL)); 1768#endif 1769} 1770 1771#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1772 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1773int 1774freebsd7_freebsd32_shmctl(struct thread *td, 1775 struct freebsd7_freebsd32_shmctl_args *uap) 1776{ 1777 int error = 0; 1778 union { 1779 struct shmid_ds shmid_ds; 1780 struct shm_info shm_info; 1781 struct shminfo shminfo; 1782 } u; 1783 union { 1784 struct shmid_ds32_old shmid_ds32; 1785 struct shm_info32 shm_info32; 1786 struct shminfo32 shminfo32; 1787 } u32; 1788 size_t sz; 1789 1790 if (uap->cmd == IPC_SET) { 1791 if ((error = copyin(uap->buf, &u32.shmid_ds32, 1792 sizeof(u32.shmid_ds32)))) 1793 goto done; 1794 freebsd32_ipcperm_old_in(&u32.shmid_ds32.shm_perm, 1795 &u.shmid_ds.shm_perm); 1796 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz); 1797 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid); 1798 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid); 1799 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch); 1800 CP(u32.shmid_ds32, u.shmid_ds, shm_atime); 1801 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime); 1802 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime); 1803 } 1804 1805 error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz); 1806 if (error) 1807 goto done; 1808 1809 /* Cases in which we need to copyout */ 1810 switch (uap->cmd) { 1811 case IPC_INFO: 1812 CP(u.shminfo, u32.shminfo32, shmmax); 1813 CP(u.shminfo, u32.shminfo32, shmmin); 1814 CP(u.shminfo, u32.shminfo32, shmmni); 1815 CP(u.shminfo, u32.shminfo32, shmseg); 1816 CP(u.shminfo, u32.shminfo32, shmall); 1817 error = copyout(&u32.shminfo32, uap->buf, 1818 sizeof(u32.shminfo32)); 1819 break; 1820 case SHM_INFO: 1821 CP(u.shm_info, u32.shm_info32, used_ids); 1822 CP(u.shm_info, u32.shm_info32, shm_rss); 1823 CP(u.shm_info, u32.shm_info32, shm_tot); 1824 CP(u.shm_info, u32.shm_info32, shm_swp); 1825 CP(u.shm_info, u32.shm_info32, swap_attempts); 1826 CP(u.shm_info, u32.shm_info32, swap_successes); 1827 error = copyout(&u32.shm_info32, uap->buf, 1828 sizeof(u32.shm_info32)); 1829 break; 1830 case SHM_STAT: 1831 case IPC_STAT: 1832 freebsd32_ipcperm_old_out(&u.shmid_ds.shm_perm, 1833 &u32.shmid_ds32.shm_perm); 1834 if (u.shmid_ds.shm_segsz > INT32_MAX) 1835 u32.shmid_ds32.shm_segsz = INT32_MAX; 1836 else 1837 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); 1838 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid); 1839 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid); 1840 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch); 1841 CP(u.shmid_ds, u32.shmid_ds32, shm_atime); 1842 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime); 1843 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime); 1844 u32.shmid_ds32.shm_internal = 0; 1845 error = copyout(&u32.shmid_ds32, uap->buf, 1846 sizeof(u32.shmid_ds32)); 1847 break; 1848 } 1849 1850done: 1851 if (error) { 1852 /* Invalidate the return value */ 1853 td->td_retval[0] = -1; 1854 } 1855 return (error); 1856} 1857#endif 1858 1859int 1860freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap) 1861{ 1862 int error = 0; 1863 union { 1864 struct shmid_ds shmid_ds; 1865 struct shm_info shm_info; 1866 struct shminfo shminfo; 1867 } u; 1868 union { 1869 struct shmid_ds32 shmid_ds32; 1870 struct shm_info32 shm_info32; 1871 struct shminfo32 shminfo32; 1872 } u32; 1873 size_t sz; 1874 1875 if (uap->cmd == IPC_SET) { 1876 if ((error = copyin(uap->buf, &u32.shmid_ds32, 1877 sizeof(u32.shmid_ds32)))) 1878 goto done; 1879 freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm, 1880 &u.shmid_ds.shm_perm); 1881 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz); 1882 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid); 1883 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid); 1884 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch); 1885 CP(u32.shmid_ds32, u.shmid_ds, shm_atime); 1886 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime); 1887 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime); 1888 } 1889 1890 error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz); 1891 if (error) 1892 goto done; 1893 1894 /* Cases in which we need to copyout */ 1895 switch (uap->cmd) { 1896 case IPC_INFO: 1897 CP(u.shminfo, u32.shminfo32, shmmax); 1898 CP(u.shminfo, u32.shminfo32, shmmin); 1899 CP(u.shminfo, u32.shminfo32, shmmni); 1900 CP(u.shminfo, u32.shminfo32, shmseg); 1901 CP(u.shminfo, u32.shminfo32, shmall); 1902 error = copyout(&u32.shminfo32, uap->buf, 1903 sizeof(u32.shminfo32)); 1904 break; 1905 case SHM_INFO: 1906 CP(u.shm_info, u32.shm_info32, used_ids); 1907 CP(u.shm_info, u32.shm_info32, shm_rss); 1908 CP(u.shm_info, u32.shm_info32, shm_tot); 1909 CP(u.shm_info, u32.shm_info32, shm_swp); 1910 CP(u.shm_info, u32.shm_info32, swap_attempts); 1911 CP(u.shm_info, u32.shm_info32, swap_successes); 1912 error = copyout(&u32.shm_info32, uap->buf, 1913 sizeof(u32.shm_info32)); 1914 break; 1915 case SHM_STAT: 1916 case IPC_STAT: 1917 freebsd32_ipcperm_out(&u.shmid_ds.shm_perm, 1918 &u32.shmid_ds32.shm_perm); 1919 if (u.shmid_ds.shm_segsz > INT32_MAX) 1920 u32.shmid_ds32.shm_segsz = INT32_MAX; 1921 else 1922 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); 1923 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid); 1924 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid); 1925 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch); 1926 CP(u.shmid_ds, u32.shmid_ds32, shm_atime); 1927 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime); 1928 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime); 1929 error = copyout(&u32.shmid_ds32, uap->buf, 1930 sizeof(u32.shmid_ds32)); 1931 break; 1932 } 1933 1934done: 1935 if (error) { 1936 /* Invalidate the return value */ 1937 td->td_retval[0] = -1; 1938 } 1939 return (error); 1940} 1941 1942int 1943freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1944{ 1945 struct pread_args ap; 1946 1947 ap.fd = uap->fd; 1948 ap.buf = uap->buf; 1949 ap.nbyte = uap->nbyte; 1950 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1951 return (pread(td, &ap)); 1952} 1953 1954int 1955freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1956{ 1957 struct pwrite_args ap; 1958 1959 ap.fd = uap->fd; 1960 ap.buf = uap->buf; 1961 ap.nbyte = uap->nbyte; 1962 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1963 return (pwrite(td, &ap)); 1964} 1965 1966int 1967freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1968{ 1969 int error; 1970 struct lseek_args ap; 1971 off_t pos; 1972 1973 ap.fd = uap->fd; 1974 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1975 ap.whence = uap->whence; 1976 error = lseek(td, &ap); 1977 /* Expand the quad return into two parts for eax and edx */ 1978 pos = *(off_t *)(td->td_retval); 1979 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1980 td->td_retval[1] = pos >> 32; /* %edx */ 1981 return error; 1982} 1983 1984int 1985freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1986{ 1987 struct truncate_args ap; 1988 1989 ap.path = uap->path; 1990 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1991 return (truncate(td, &ap)); 1992} 1993 1994int 1995freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1996{ 1997 struct ftruncate_args ap; 1998 1999 ap.fd = uap->fd; 2000 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 2001 return (ftruncate(td, &ap)); 2002} 2003 2004int 2005freebsd32_getdirentries(struct thread *td, 2006 struct freebsd32_getdirentries_args *uap) 2007{ 2008 long base; 2009 int32_t base32; 2010 int error; 2011 2012 error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base); 2013 if (error) 2014 return (error); 2015 if (uap->basep != NULL) { 2016 base32 = base; 2017 error = copyout(&base32, uap->basep, sizeof(int32_t)); 2018 } 2019 return (error); 2020} 2021 2022#ifdef COMPAT_FREEBSD6 2023/* versions with the 'int pad' argument */ 2024int 2025freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap) 2026{ 2027 struct pread_args ap; 2028 2029 ap.fd = uap->fd; 2030 ap.buf = uap->buf; 2031 ap.nbyte = uap->nbyte; 2032 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 2033 return (pread(td, &ap)); 2034} 2035 2036int 2037freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap) 2038{ 2039 struct pwrite_args ap; 2040 2041 ap.fd = uap->fd; 2042 ap.buf = uap->buf; 2043 ap.nbyte = uap->nbyte; 2044 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 2045 return (pwrite(td, &ap)); 2046} 2047 2048int 2049freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap) 2050{ 2051 int error; 2052 struct lseek_args ap; 2053 off_t pos; 2054 2055 ap.fd = uap->fd; 2056 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 2057 ap.whence = uap->whence; 2058 error = lseek(td, &ap); 2059 /* Expand the quad return into two parts for eax and edx */ 2060 pos = *(off_t *)(td->td_retval); 2061 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 2062 td->td_retval[1] = pos >> 32; /* %edx */ 2063 return error; 2064} 2065 2066int 2067freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap) 2068{ 2069 struct truncate_args ap; 2070 2071 ap.path = uap->path; 2072 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 2073 return (truncate(td, &ap)); 2074} 2075 2076int 2077freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap) 2078{ 2079 struct ftruncate_args ap; 2080 2081 ap.fd = uap->fd; 2082 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 2083 return (ftruncate(td, &ap)); 2084} 2085#endif /* COMPAT_FREEBSD6 */ 2086 2087struct sf_hdtr32 { 2088 uint32_t headers; 2089 int hdr_cnt; 2090 uint32_t trailers; 2091 int trl_cnt; 2092}; 2093 2094static int 2095freebsd32_do_sendfile(struct thread *td, 2096 struct freebsd32_sendfile_args *uap, int compat) 2097{ 2098 struct sendfile_args ap; 2099 struct sf_hdtr32 hdtr32; 2100 struct sf_hdtr hdtr; 2101 struct uio *hdr_uio, *trl_uio; 2102 struct iovec32 *iov32; 2103 int error; 2104 2105 hdr_uio = trl_uio = NULL; 2106 2107 ap.fd = uap->fd; 2108 ap.s = uap->s; 2109 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 2110 ap.nbytes = uap->nbytes; 2111 ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */ 2112 ap.sbytes = uap->sbytes; 2113 ap.flags = uap->flags; 2114 2115 if (uap->hdtr != NULL) { 2116 error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32)); 2117 if (error) 2118 goto out; 2119 PTRIN_CP(hdtr32, hdtr, headers); 2120 CP(hdtr32, hdtr, hdr_cnt); 2121 PTRIN_CP(hdtr32, hdtr, trailers); 2122 CP(hdtr32, hdtr, trl_cnt); 2123 2124 if (hdtr.headers != NULL) { 2125 iov32 = PTRIN(hdtr32.headers); 2126 error = freebsd32_copyinuio(iov32, 2127 hdtr32.hdr_cnt, &hdr_uio); 2128 if (error) 2129 goto out; 2130 } 2131 if (hdtr.trailers != NULL) { 2132 iov32 = PTRIN(hdtr32.trailers); 2133 error = freebsd32_copyinuio(iov32, 2134 hdtr32.trl_cnt, &trl_uio); 2135 if (error) 2136 goto out; 2137 } 2138 } 2139 2140 error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat); 2141out: 2142 if (hdr_uio) 2143 free(hdr_uio, M_IOV); 2144 if (trl_uio) 2145 free(trl_uio, M_IOV); 2146 return (error); 2147} 2148 2149#ifdef COMPAT_FREEBSD4 2150int 2151freebsd4_freebsd32_sendfile(struct thread *td, 2152 struct freebsd4_freebsd32_sendfile_args *uap) 2153{ 2154 return (freebsd32_do_sendfile(td, 2155 (struct freebsd32_sendfile_args *)uap, 1)); 2156} 2157#endif 2158 2159int 2160freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 2161{ 2162 2163 return (freebsd32_do_sendfile(td, uap, 0)); 2164} 2165 2166static void 2167copy_stat( struct stat *in, struct stat32 *out) 2168{ 2169 CP(*in, *out, st_dev); 2170 CP(*in, *out, st_ino); 2171 CP(*in, *out, st_mode); 2172 CP(*in, *out, st_nlink); 2173 CP(*in, *out, st_uid); 2174 CP(*in, *out, st_gid); 2175 CP(*in, *out, st_rdev); 2176 TS_CP(*in, *out, st_atimespec); 2177 TS_CP(*in, *out, st_mtimespec); 2178 TS_CP(*in, *out, st_ctimespec); 2179 CP(*in, *out, st_size); 2180 CP(*in, *out, st_blocks); 2181 CP(*in, *out, st_blksize); 2182 CP(*in, *out, st_flags); 2183 CP(*in, *out, st_gen); 2184} 2185 2186int 2187freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 2188{ 2189 struct stat sb; 2190 struct stat32 sb32; 2191 int error; 2192 2193 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 2194 if (error) 2195 return (error); 2196 copy_stat(&sb, &sb32); 2197 error = copyout(&sb32, uap->ub, sizeof (sb32)); 2198 return (error); 2199} 2200 2201int 2202freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 2203{ 2204 struct stat ub; 2205 struct stat32 ub32; 2206 int error; 2207 2208 error = kern_fstat(td, uap->fd, &ub); 2209 if (error) 2210 return (error); 2211 copy_stat(&ub, &ub32); 2212 error = copyout(&ub32, uap->ub, sizeof(ub32)); 2213 return (error); 2214} 2215 2216int 2217freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap) 2218{ 2219 struct stat ub; 2220 struct stat32 ub32; 2221 int error; 2222 2223 error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub); 2224 if (error) 2225 return (error); 2226 copy_stat(&ub, &ub32); 2227 error = copyout(&ub32, uap->buf, sizeof(ub32)); 2228 return (error); 2229} 2230 2231int 2232freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 2233{ 2234 struct stat sb; 2235 struct stat32 sb32; 2236 int error; 2237 2238 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 2239 if (error) 2240 return (error); 2241 copy_stat(&sb, &sb32); 2242 error = copyout(&sb32, uap->ub, sizeof (sb32)); 2243 return (error); 2244} 2245 2246/* 2247 * MPSAFE 2248 */ 2249int 2250freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 2251{ 2252 int error, name[CTL_MAXNAME]; 2253 size_t j, oldlen; 2254 2255 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 2256 return (EINVAL); 2257 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 2258 if (error) 2259 return (error); 2260 if (uap->oldlenp) 2261 oldlen = fuword32(uap->oldlenp); 2262 else 2263 oldlen = 0; 2264 error = userland_sysctl(td, name, uap->namelen, 2265 uap->old, &oldlen, 1, 2266 uap->new, uap->newlen, &j, SCTL_MASK32); 2267 if (error && error != ENOMEM) 2268 return (error); 2269 if (uap->oldlenp) 2270 suword32(uap->oldlenp, j); 2271 return (0); 2272} 2273 2274int 2275freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap) 2276{ 2277 uint32_t version; 2278 int error; 2279 struct jail j; 2280 2281 error = copyin(uap->jail, &version, sizeof(uint32_t)); 2282 if (error) 2283 return (error); 2284 2285 switch (version) { 2286 case 0: 2287 { 2288 /* FreeBSD single IPv4 jails. */ 2289 struct jail32_v0 j32_v0; 2290 2291 bzero(&j, sizeof(struct jail)); 2292 error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0)); 2293 if (error) 2294 return (error); 2295 CP(j32_v0, j, version); 2296 PTRIN_CP(j32_v0, j, path); 2297 PTRIN_CP(j32_v0, j, hostname); 2298 j.ip4s = j32_v0.ip_number; 2299 break; 2300 } 2301 2302 case 1: 2303 /* 2304 * Version 1 was used by multi-IPv4 jail implementations 2305 * that never made it into the official kernel. 2306 */ 2307 return (EINVAL); 2308 2309 case 2: /* JAIL_API_VERSION */ 2310 { 2311 /* FreeBSD multi-IPv4/IPv6,noIP jails. */ 2312 struct jail32 j32; 2313 2314 error = copyin(uap->jail, &j32, sizeof(struct jail32)); 2315 if (error) 2316 return (error); 2317 CP(j32, j, version); 2318 PTRIN_CP(j32, j, path); 2319 PTRIN_CP(j32, j, hostname); 2320 PTRIN_CP(j32, j, jailname); 2321 CP(j32, j, ip4s); 2322 CP(j32, j, ip6s); 2323 PTRIN_CP(j32, j, ip4); 2324 PTRIN_CP(j32, j, ip6); 2325 break; 2326 } 2327 2328 default: 2329 /* Sci-Fi jails are not supported, sorry. */ 2330 return (EINVAL); 2331 } 2332 return (kern_jail(td, &j)); 2333} 2334 2335int 2336freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap) 2337{ 2338 struct uio *auio; 2339 int error; 2340 2341 /* Check that we have an even number of iovecs. */ 2342 if (uap->iovcnt & 1) 2343 return (EINVAL); 2344 2345 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 2346 if (error) 2347 return (error); 2348 error = kern_jail_set(td, auio, uap->flags); 2349 free(auio, M_IOV); 2350 return (error); 2351} 2352 2353int 2354freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap) 2355{ 2356 struct iovec32 iov32; 2357 struct uio *auio; 2358 int error, i; 2359 2360 /* Check that we have an even number of iovecs. */ 2361 if (uap->iovcnt & 1) 2362 return (EINVAL); 2363 2364 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 2365 if (error) 2366 return (error); 2367 error = kern_jail_get(td, auio, uap->flags); 2368 if (error == 0) 2369 for (i = 0; i < uap->iovcnt; i++) { 2370 PTROUT_CP(auio->uio_iov[i], iov32, iov_base); 2371 CP(auio->uio_iov[i], iov32, iov_len); 2372 error = copyout(&iov32, uap->iovp + i, sizeof(iov32)); 2373 if (error != 0) 2374 break; 2375 } 2376 free(auio, M_IOV); 2377 return (error); 2378} 2379 2380int 2381freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 2382{ 2383 struct sigaction32 s32; 2384 struct sigaction sa, osa, *sap; 2385 int error; 2386 2387 if (uap->act) { 2388 error = copyin(uap->act, &s32, sizeof(s32)); 2389 if (error) 2390 return (error); 2391 sa.sa_handler = PTRIN(s32.sa_u); 2392 CP(s32, sa, sa_flags); 2393 CP(s32, sa, sa_mask); 2394 sap = &sa; 2395 } else 2396 sap = NULL; 2397 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 2398 if (error == 0 && uap->oact != NULL) { 2399 s32.sa_u = PTROUT(osa.sa_handler); 2400 CP(osa, s32, sa_flags); 2401 CP(osa, s32, sa_mask); 2402 error = copyout(&s32, uap->oact, sizeof(s32)); 2403 } 2404 return (error); 2405} 2406 2407#ifdef COMPAT_FREEBSD4 2408int 2409freebsd4_freebsd32_sigaction(struct thread *td, 2410 struct freebsd4_freebsd32_sigaction_args *uap) 2411{ 2412 struct sigaction32 s32; 2413 struct sigaction sa, osa, *sap; 2414 int error; 2415 2416 if (uap->act) { 2417 error = copyin(uap->act, &s32, sizeof(s32)); 2418 if (error) 2419 return (error); 2420 sa.sa_handler = PTRIN(s32.sa_u); 2421 CP(s32, sa, sa_flags); 2422 CP(s32, sa, sa_mask); 2423 sap = &sa; 2424 } else 2425 sap = NULL; 2426 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 2427 if (error == 0 && uap->oact != NULL) { 2428 s32.sa_u = PTROUT(osa.sa_handler); 2429 CP(osa, s32, sa_flags); 2430 CP(osa, s32, sa_mask); 2431 error = copyout(&s32, uap->oact, sizeof(s32)); 2432 } 2433 return (error); 2434} 2435#endif 2436 2437#ifdef COMPAT_43 2438struct osigaction32 { 2439 u_int32_t sa_u; 2440 osigset_t sa_mask; 2441 int sa_flags; 2442}; 2443 2444#define ONSIG 32 2445 2446int 2447ofreebsd32_sigaction(struct thread *td, 2448 struct ofreebsd32_sigaction_args *uap) 2449{ 2450 struct osigaction32 s32; 2451 struct sigaction sa, osa, *sap; 2452 int error; 2453 2454 if (uap->signum <= 0 || uap->signum >= ONSIG) 2455 return (EINVAL); 2456 2457 if (uap->nsa) { 2458 error = copyin(uap->nsa, &s32, sizeof(s32)); 2459 if (error) 2460 return (error); 2461 sa.sa_handler = PTRIN(s32.sa_u); 2462 CP(s32, sa, sa_flags); 2463 OSIG2SIG(s32.sa_mask, sa.sa_mask); 2464 sap = &sa; 2465 } else 2466 sap = NULL; 2467 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 2468 if (error == 0 && uap->osa != NULL) { 2469 s32.sa_u = PTROUT(osa.sa_handler); 2470 CP(osa, s32, sa_flags); 2471 SIG2OSIG(osa.sa_mask, s32.sa_mask); 2472 error = copyout(&s32, uap->osa, sizeof(s32)); 2473 } 2474 return (error); 2475} 2476 2477int 2478ofreebsd32_sigprocmask(struct thread *td, 2479 struct ofreebsd32_sigprocmask_args *uap) 2480{ 2481 sigset_t set, oset; 2482 int error; 2483 2484 OSIG2SIG(uap->mask, set); 2485 error = kern_sigprocmask(td, uap->how, &set, &oset, SIGPROCMASK_OLD); 2486 SIG2OSIG(oset, td->td_retval[0]); 2487 return (error); 2488} 2489 2490int 2491ofreebsd32_sigpending(struct thread *td, 2492 struct ofreebsd32_sigpending_args *uap) 2493{ 2494 struct proc *p = td->td_proc; 2495 sigset_t siglist; 2496 2497 PROC_LOCK(p); 2498 siglist = p->p_siglist; 2499 SIGSETOR(siglist, td->td_siglist); 2500 PROC_UNLOCK(p); 2501 SIG2OSIG(siglist, td->td_retval[0]); 2502 return (0); 2503} 2504 2505struct sigvec32 { 2506 u_int32_t sv_handler; 2507 int sv_mask; 2508 int sv_flags; 2509}; 2510 2511int 2512ofreebsd32_sigvec(struct thread *td, 2513 struct ofreebsd32_sigvec_args *uap) 2514{ 2515 struct sigvec32 vec; 2516 struct sigaction sa, osa, *sap; 2517 int error; 2518 2519 if (uap->signum <= 0 || uap->signum >= ONSIG) 2520 return (EINVAL); 2521 2522 if (uap->nsv) { 2523 error = copyin(uap->nsv, &vec, sizeof(vec)); 2524 if (error) 2525 return (error); 2526 sa.sa_handler = PTRIN(vec.sv_handler); 2527 OSIG2SIG(vec.sv_mask, sa.sa_mask); 2528 sa.sa_flags = vec.sv_flags; 2529 sa.sa_flags ^= SA_RESTART; 2530 sap = &sa; 2531 } else 2532 sap = NULL; 2533 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 2534 if (error == 0 && uap->osv != NULL) { 2535 vec.sv_handler = PTROUT(osa.sa_handler); 2536 SIG2OSIG(osa.sa_mask, vec.sv_mask); 2537 vec.sv_flags = osa.sa_flags; 2538 vec.sv_flags &= ~SA_NOCLDWAIT; 2539 vec.sv_flags ^= SA_RESTART; 2540 error = copyout(&vec, uap->osv, sizeof(vec)); 2541 } 2542 return (error); 2543} 2544 2545int 2546ofreebsd32_sigblock(struct thread *td, 2547 struct ofreebsd32_sigblock_args *uap) 2548{ 2549 sigset_t set, oset; 2550 2551 OSIG2SIG(uap->mask, set); 2552 kern_sigprocmask(td, SIG_BLOCK, &set, &oset, 0); 2553 SIG2OSIG(oset, td->td_retval[0]); 2554 return (0); 2555} 2556 2557int 2558ofreebsd32_sigsetmask(struct thread *td, 2559 struct ofreebsd32_sigsetmask_args *uap) 2560{ 2561 sigset_t set, oset; 2562 2563 OSIG2SIG(uap->mask, set); 2564 kern_sigprocmask(td, SIG_SETMASK, &set, &oset, 0); 2565 SIG2OSIG(oset, td->td_retval[0]); 2566 return (0); 2567} 2568 2569int 2570ofreebsd32_sigsuspend(struct thread *td, 2571 struct ofreebsd32_sigsuspend_args *uap) 2572{ 2573 sigset_t mask; 2574 2575 OSIG2SIG(uap->mask, mask); 2576 return (kern_sigsuspend(td, mask)); 2577} 2578 2579struct sigstack32 { 2580 u_int32_t ss_sp; 2581 int ss_onstack; 2582}; 2583 2584int 2585ofreebsd32_sigstack(struct thread *td, 2586 struct ofreebsd32_sigstack_args *uap) 2587{ 2588 struct sigstack32 s32; 2589 struct sigstack nss, oss; 2590 int error = 0, unss; 2591 2592 if (uap->nss != NULL) { 2593 error = copyin(uap->nss, &s32, sizeof(s32)); 2594 if (error) 2595 return (error); 2596 nss.ss_sp = PTRIN(s32.ss_sp); 2597 CP(s32, nss, ss_onstack); 2598 unss = 1; 2599 } else { 2600 unss = 0; 2601 } 2602 oss.ss_sp = td->td_sigstk.ss_sp; 2603 oss.ss_onstack = sigonstack(cpu_getstack(td)); 2604 if (unss) { 2605 td->td_sigstk.ss_sp = nss.ss_sp; 2606 td->td_sigstk.ss_size = 0; 2607 td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK); 2608 td->td_pflags |= TDP_ALTSTACK; 2609 } 2610 if (uap->oss != NULL) { 2611 s32.ss_sp = PTROUT(oss.ss_sp); 2612 CP(oss, s32, ss_onstack); 2613 error = copyout(&s32, uap->oss, sizeof(s32)); 2614 } 2615 return (error); 2616} 2617#endif 2618 2619int 2620freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 2621{ 2622 struct timespec32 rmt32, rqt32; 2623 struct timespec rmt, rqt; 2624 int error; 2625 2626 error = copyin(uap->rqtp, &rqt32, sizeof(rqt32)); 2627 if (error) 2628 return (error); 2629 2630 CP(rqt32, rqt, tv_sec); 2631 CP(rqt32, rqt, tv_nsec); 2632 2633 if (uap->rmtp && 2634 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 2635 return (EFAULT); 2636 error = kern_nanosleep(td, &rqt, &rmt); 2637 if (error && uap->rmtp) { 2638 int error2; 2639 2640 CP(rmt, rmt32, tv_sec); 2641 CP(rmt, rmt32, tv_nsec); 2642 2643 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32)); 2644 if (error2) 2645 error = error2; 2646 } 2647 return (error); 2648} 2649 2650int 2651freebsd32_clock_gettime(struct thread *td, 2652 struct freebsd32_clock_gettime_args *uap) 2653{ 2654 struct timespec ats; 2655 struct timespec32 ats32; 2656 int error; 2657 2658 error = kern_clock_gettime(td, uap->clock_id, &ats); 2659 if (error == 0) { 2660 CP(ats, ats32, tv_sec); 2661 CP(ats, ats32, tv_nsec); 2662 error = copyout(&ats32, uap->tp, sizeof(ats32)); 2663 } 2664 return (error); 2665} 2666 2667int 2668freebsd32_clock_settime(struct thread *td, 2669 struct freebsd32_clock_settime_args *uap) 2670{ 2671 struct timespec ats; 2672 struct timespec32 ats32; 2673 int error; 2674 2675 error = copyin(uap->tp, &ats32, sizeof(ats32)); 2676 if (error) 2677 return (error); 2678 CP(ats32, ats, tv_sec); 2679 CP(ats32, ats, tv_nsec); 2680 2681 return (kern_clock_settime(td, uap->clock_id, &ats)); 2682} 2683 2684int 2685freebsd32_clock_getres(struct thread *td, 2686 struct freebsd32_clock_getres_args *uap) 2687{ 2688 struct timespec ts; 2689 struct timespec32 ts32; 2690 int error; 2691 2692 if (uap->tp == NULL) 2693 return (0); 2694 error = kern_clock_getres(td, uap->clock_id, &ts); 2695 if (error == 0) { 2696 CP(ts, ts32, tv_sec); 2697 CP(ts, ts32, tv_nsec); 2698 error = copyout(&ts32, uap->tp, sizeof(ts32)); 2699 } 2700 return (error); 2701} 2702 2703int 2704freebsd32_thr_new(struct thread *td, 2705 struct freebsd32_thr_new_args *uap) 2706{ 2707 struct thr_param32 param32; 2708 struct thr_param param; 2709 int error; 2710 2711 if (uap->param_size < 0 || 2712 uap->param_size > sizeof(struct thr_param32)) 2713 return (EINVAL); 2714 bzero(¶m, sizeof(struct thr_param)); 2715 bzero(¶m32, sizeof(struct thr_param32)); 2716 error = copyin(uap->param, ¶m32, uap->param_size); 2717 if (error != 0) 2718 return (error); 2719 param.start_func = PTRIN(param32.start_func); 2720 param.arg = PTRIN(param32.arg); 2721 param.stack_base = PTRIN(param32.stack_base); 2722 param.stack_size = param32.stack_size; 2723 param.tls_base = PTRIN(param32.tls_base); 2724 param.tls_size = param32.tls_size; 2725 param.child_tid = PTRIN(param32.child_tid); 2726 param.parent_tid = PTRIN(param32.parent_tid); 2727 param.flags = param32.flags; 2728 param.rtp = PTRIN(param32.rtp); 2729 param.spare[0] = PTRIN(param32.spare[0]); 2730 param.spare[1] = PTRIN(param32.spare[1]); 2731 param.spare[2] = PTRIN(param32.spare[2]); 2732 2733 return (kern_thr_new(td, ¶m)); 2734} 2735 2736int 2737freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap) 2738{ 2739 struct timespec32 ts32; 2740 struct timespec ts, *tsp; 2741 int error; 2742 2743 error = 0; 2744 tsp = NULL; 2745 if (uap->timeout != NULL) { 2746 error = copyin((const void *)uap->timeout, (void *)&ts32, 2747 sizeof(struct timespec32)); 2748 if (error != 0) 2749 return (error); 2750 ts.tv_sec = ts32.tv_sec; 2751 ts.tv_nsec = ts32.tv_nsec; 2752 tsp = &ts; 2753 } 2754 return (kern_thr_suspend(td, tsp)); 2755} 2756 2757void 2758siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst) 2759{ 2760 bzero(dst, sizeof(*dst)); 2761 dst->si_signo = src->si_signo; 2762 dst->si_errno = src->si_errno; 2763 dst->si_code = src->si_code; 2764 dst->si_pid = src->si_pid; 2765 dst->si_uid = src->si_uid; 2766 dst->si_status = src->si_status; 2767 dst->si_addr = (uintptr_t)src->si_addr; 2768 dst->si_value.sigval_int = src->si_value.sival_int; 2769 dst->si_timerid = src->si_timerid; 2770 dst->si_overrun = src->si_overrun; 2771} 2772 2773int 2774freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap) 2775{ 2776 struct timespec32 ts32; 2777 struct timespec ts; 2778 struct timespec *timeout; 2779 sigset_t set; 2780 ksiginfo_t ksi; 2781 struct siginfo32 si32; 2782 int error; 2783 2784 if (uap->timeout) { 2785 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 2786 if (error) 2787 return (error); 2788 ts.tv_sec = ts32.tv_sec; 2789 ts.tv_nsec = ts32.tv_nsec; 2790 timeout = &ts; 2791 } else 2792 timeout = NULL; 2793 2794 error = copyin(uap->set, &set, sizeof(set)); 2795 if (error) 2796 return (error); 2797 2798 error = kern_sigtimedwait(td, set, &ksi, timeout); 2799 if (error) 2800 return (error); 2801 2802 if (uap->info) { 2803 siginfo_to_siginfo32(&ksi.ksi_info, &si32); 2804 error = copyout(&si32, uap->info, sizeof(struct siginfo32)); 2805 } 2806 2807 if (error == 0) 2808 td->td_retval[0] = ksi.ksi_signo; 2809 return (error); 2810} 2811 2812/* 2813 * MPSAFE 2814 */ 2815int 2816freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap) 2817{ 2818 ksiginfo_t ksi; 2819 struct siginfo32 si32; 2820 sigset_t set; 2821 int error; 2822 2823 error = copyin(uap->set, &set, sizeof(set)); 2824 if (error) 2825 return (error); 2826 2827 error = kern_sigtimedwait(td, set, &ksi, NULL); 2828 if (error) 2829 return (error); 2830 2831 if (uap->info) { 2832 siginfo_to_siginfo32(&ksi.ksi_info, &si32); 2833 error = copyout(&si32, uap->info, sizeof(struct siginfo32)); 2834 } 2835 if (error == 0) 2836 td->td_retval[0] = ksi.ksi_signo; 2837 return (error); 2838} 2839 2840int 2841freebsd32_cpuset_setid(struct thread *td, 2842 struct freebsd32_cpuset_setid_args *uap) 2843{ 2844 struct cpuset_setid_args ap; 2845 2846 ap.which = uap->which; 2847 ap.id = (uap->idlo | ((id_t)uap->idhi << 32)); 2848 ap.setid = uap->setid; 2849 2850 return (cpuset_setid(td, &ap)); 2851} 2852 2853int 2854freebsd32_cpuset_getid(struct thread *td, 2855 struct freebsd32_cpuset_getid_args *uap) 2856{ 2857 struct cpuset_getid_args ap; 2858 2859 ap.level = uap->level; 2860 ap.which = uap->which; 2861 ap.id = (uap->idlo | ((id_t)uap->idhi << 32)); 2862 ap.setid = uap->setid; 2863 2864 return (cpuset_getid(td, &ap)); 2865} 2866 2867int 2868freebsd32_cpuset_getaffinity(struct thread *td, 2869 struct freebsd32_cpuset_getaffinity_args *uap) 2870{ 2871 struct cpuset_getaffinity_args ap; 2872 2873 ap.level = uap->level; 2874 ap.which = uap->which; 2875 ap.id = (uap->idlo | ((id_t)uap->idhi << 32)); 2876 ap.cpusetsize = uap->cpusetsize; 2877 ap.mask = uap->mask; 2878 2879 return (cpuset_getaffinity(td, &ap)); 2880} 2881 2882int 2883freebsd32_cpuset_setaffinity(struct thread *td, 2884 struct freebsd32_cpuset_setaffinity_args *uap) 2885{ 2886 struct cpuset_setaffinity_args ap; 2887 2888 ap.level = uap->level; 2889 ap.which = uap->which; 2890 ap.id = (uap->idlo | ((id_t)uap->idhi << 32)); 2891 ap.cpusetsize = uap->cpusetsize; 2892 ap.mask = uap->mask; 2893 2894 return (cpuset_setaffinity(td, &ap)); 2895} 2896 2897int 2898freebsd32_nmount(struct thread *td, 2899 struct freebsd32_nmount_args /* { 2900 struct iovec *iovp; 2901 unsigned int iovcnt; 2902 int flags; 2903 } */ *uap) 2904{ 2905 struct uio *auio; 2906 int error; 2907 2908 AUDIT_ARG_FFLAGS(uap->flags); 2909 2910 /* 2911 * Filter out MNT_ROOTFS. We do not want clients of nmount() in 2912 * userspace to set this flag, but we must filter it out if we want 2913 * MNT_UPDATE on the root file system to work. 2914 * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try(). 2915 */ 2916 uap->flags &= ~MNT_ROOTFS; 2917 2918 /* 2919 * check that we have an even number of iovec's 2920 * and that we have at least two options. 2921 */ 2922 if ((uap->iovcnt & 1) || (uap->iovcnt < 4)) 2923 return (EINVAL); 2924 2925 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 2926 if (error) 2927 return (error); 2928 error = vfs_donmount(td, uap->flags, auio); 2929 2930 free(auio, M_IOV); 2931 return error; 2932} 2933 2934#if 0 2935int 2936freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 2937{ 2938 struct yyy32 *p32, s32; 2939 struct yyy *p = NULL, s; 2940 struct xxx_arg ap; 2941 int error; 2942 2943 if (uap->zzz) { 2944 error = copyin(uap->zzz, &s32, sizeof(s32)); 2945 if (error) 2946 return (error); 2947 /* translate in */ 2948 p = &s; 2949 } 2950 error = kern_xxx(td, p); 2951 if (error) 2952 return (error); 2953 if (uap->zzz) { 2954 /* translate out */ 2955 error = copyout(&s32, p32, sizeof(s32)); 2956 } 2957 return (error); 2958} 2959#endif 2960 2961int 2962syscall32_register(int *offset, struct sysent *new_sysent, 2963 struct sysent *old_sysent) 2964{ 2965 if (*offset == NO_SYSCALL) { 2966 int i; 2967 2968 for (i = 1; i < SYS_MAXSYSCALL; ++i) 2969 if (freebsd32_sysent[i].sy_call == 2970 (sy_call_t *)lkmnosys) 2971 break; 2972 if (i == SYS_MAXSYSCALL) 2973 return (ENFILE); 2974 *offset = i; 2975 } else if (*offset < 0 || *offset >= SYS_MAXSYSCALL) 2976 return (EINVAL); 2977 else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys && 2978 freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys) 2979 return (EEXIST); 2980 2981 *old_sysent = freebsd32_sysent[*offset]; 2982 freebsd32_sysent[*offset] = *new_sysent; 2983 return 0; 2984} 2985 2986int 2987syscall32_deregister(int *offset, struct sysent *old_sysent) 2988{ 2989 2990 if (*offset) 2991 freebsd32_sysent[*offset] = *old_sysent; 2992 return 0; 2993} 2994 2995int 2996syscall32_module_handler(struct module *mod, int what, void *arg) 2997{ 2998 struct syscall_module_data *data = (struct syscall_module_data*)arg; 2999 modspecific_t ms; 3000 int error; 3001 3002 switch (what) { 3003 case MOD_LOAD: 3004 error = syscall32_register(data->offset, data->new_sysent, 3005 &data->old_sysent); 3006 if (error) { 3007 /* Leave a mark so we know to safely unload below. */ 3008 data->offset = NULL; 3009 return error; 3010 } 3011 ms.intval = *data->offset; 3012 MOD_XLOCK; 3013 module_setspecific(mod, &ms); 3014 MOD_XUNLOCK; 3015 if (data->chainevh) 3016 error = data->chainevh(mod, what, data->chainarg); 3017 return (error); 3018 case MOD_UNLOAD: 3019 /* 3020 * MOD_LOAD failed, so just return without calling the 3021 * chained handler since we didn't pass along the MOD_LOAD 3022 * event. 3023 */ 3024 if (data->offset == NULL) 3025 return (0); 3026 if (data->chainevh) { 3027 error = data->chainevh(mod, what, data->chainarg); 3028 if (error) 3029 return (error); 3030 } 3031 error = syscall32_deregister(data->offset, &data->old_sysent); 3032 return (error); 3033 default: 3034 error = EOPNOTSUPP; 3035 if (data->chainevh) 3036 error = data->chainevh(mod, what, data->chainarg); 3037 return (error); 3038 } 3039} 3040