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

Cache object: 88fd4ee1a99898d6c2f21e949d5cf1d7


[ 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.