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

Cache object: f62de1ec46bbdb23f1006213d09c672c


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