The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/freebsd32/freebsd32_misc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: b9e8b490734448a1a3cd6e222914f9dc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.