Path: blob/main/sys/compat/freebsd32/freebsd32_misc.c
107074 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2002 Doug Rabson4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/cdefs.h>29#include "opt_ffclock.h"30#include "opt_inet.h"31#include "opt_inet6.h"32#include "opt_ktrace.h"3334#define __ELF_WORD_SIZE 323536#ifdef COMPAT_FREEBSD1137#define _WANT_FREEBSD11_KEVENT38#endif3940#include <sys/param.h>41#include <sys/bus.h>42#include <sys/capsicum.h>43#include <sys/clock.h>44#include <sys/exec.h>45#include <sys/fcntl.h>46#include <sys/filedesc.h>47#include <sys/imgact.h>48#include <sys/jail.h>49#include <sys/kernel.h>50#include <sys/limits.h>51#include <sys/linker.h>52#include <sys/lock.h>53#include <sys/malloc.h>54#include <sys/file.h> /* Must come after sys/malloc.h */55#include <sys/imgact.h>56#include <sys/mbuf.h>57#include <sys/mman.h>58#include <sys/module.h>59#include <sys/mount.h>60#include <sys/mutex.h>61#include <sys/namei.h>62#include <sys/priv.h>63#include <sys/proc.h>64#include <sys/procctl.h>65#include <sys/ptrace.h>66#include <sys/reboot.h>67#include <sys/resource.h>68#include <sys/resourcevar.h>69#include <sys/selinfo.h>70#include <sys/eventvar.h> /* Must come after sys/selinfo.h */71#include <sys/pipe.h> /* Must come after sys/selinfo.h */72#include <sys/signal.h>73#include <sys/signalvar.h>74#include <sys/socket.h>75#include <sys/socketvar.h>76#include <sys/stat.h>77#include <sys/syscall.h>78#include <sys/syscallsubr.h>79#include <sys/sysctl.h>80#include <sys/sysent.h>81#include <sys/sysproto.h>82#include <sys/systm.h>83#include <sys/thr.h>84#include <sys/timerfd.h>85#include <sys/timex.h>86#include <sys/unistd.h>87#include <sys/ucontext.h>88#include <sys/ucred.h>89#include <sys/vnode.h>90#include <sys/wait.h>91#include <sys/ipc.h>92#include <sys/msg.h>93#include <sys/sem.h>94#include <sys/shm.h>95#include <sys/timeffc.h>96#ifdef KTRACE97#include <sys/ktrace.h>98#endif99100#ifdef INET101#include <netinet/in.h>102#endif103104#include <vm/vm.h>105#include <vm/vm_param.h>106#include <vm/pmap.h>107#include <vm/vm_map.h>108#include <vm/vm_object.h>109#include <vm/vm_extern.h>110111#include <machine/cpu.h>112#include <machine/elf.h>113#ifdef __amd64__114#include <machine/md_var.h>115#endif116117#include <security/audit/audit.h>118#include <security/mac/mac_syscalls.h>119120#include <compat/freebsd32/freebsd32_util.h>121#include <compat/freebsd32/freebsd32.h>122#include <compat/freebsd32/freebsd32_ipc.h>123#include <compat/freebsd32/freebsd32_misc.h>124#include <compat/freebsd32/freebsd32_signal.h>125#include <compat/freebsd32/freebsd32_proto.h>126127int compat_freebsd_32bit = 1;128129static void130register_compat32_feature(void *arg)131{132if (!compat_freebsd_32bit)133return;134135FEATURE_ADD("compat_freebsd32", "Compatible with 32-bit FreeBSD");136FEATURE_ADD("compat_freebsd_32bit",137"Compatible with 32-bit FreeBSD (legacy feature name)");138}139SYSINIT(freebsd32, SI_SUB_EXEC, SI_ORDER_ANY, register_compat32_feature,140NULL);141142struct ptrace_io_desc32 {143int piod_op;144uint32_t piod_offs;145uint32_t piod_addr;146uint32_t piod_len;147};148149struct ptrace_vm_entry32 {150int pve_entry;151int pve_timestamp;152uint32_t pve_start;153uint32_t pve_end;154uint32_t pve_offset;155u_int pve_prot;156u_int pve_pathlen;157int32_t pve_fileid;158u_int pve_fsid;159uint32_t pve_path;160};161162#ifdef __amd64__163CTASSERT(sizeof(struct timeval32) == 8);164CTASSERT(sizeof(struct timespec32) == 8);165CTASSERT(sizeof(struct itimerval32) == 16);166CTASSERT(sizeof(struct bintime32) == 12);167#else168CTASSERT(sizeof(struct timeval32) == 16);169CTASSERT(sizeof(struct timespec32) == 16);170CTASSERT(sizeof(struct itimerval32) == 32);171CTASSERT(sizeof(struct bintime32) == 16);172#endif173CTASSERT(sizeof(struct ostatfs32) == 256);174#ifdef __amd64__175CTASSERT(sizeof(struct rusage32) == 72);176#else177CTASSERT(sizeof(struct rusage32) == 88);178#endif179CTASSERT(sizeof(struct sigaltstack32) == 12);180#ifdef __amd64__181CTASSERT(sizeof(struct kevent32) == 56);182#else183CTASSERT(sizeof(struct kevent32) == 64);184#endif185CTASSERT(sizeof(struct iovec32) == 8);186CTASSERT(sizeof(struct msghdr32) == 28);187#ifdef __amd64__188CTASSERT(sizeof(struct stat32) == 208);189CTASSERT(sizeof(struct freebsd11_stat32) == 96);190#else191CTASSERT(sizeof(struct stat32) == 224);192CTASSERT(sizeof(struct freebsd11_stat32) == 120);193#endif194CTASSERT(sizeof(struct sigaction32) == 24);195196static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);197static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);198static int freebsd32_user_clock_nanosleep(struct thread *td, clockid_t clock_id,199int flags, const struct timespec32 *ua_rqtp, struct timespec32 *ua_rmtp);200201void202freebsd32_rusage_out(const struct rusage *s, struct rusage32 *s32)203{204205bzero(s32, sizeof(*s32));206TV_CP(*s, *s32, ru_utime);207TV_CP(*s, *s32, ru_stime);208CP(*s, *s32, ru_maxrss);209CP(*s, *s32, ru_ixrss);210CP(*s, *s32, ru_idrss);211CP(*s, *s32, ru_isrss);212CP(*s, *s32, ru_minflt);213CP(*s, *s32, ru_majflt);214CP(*s, *s32, ru_nswap);215CP(*s, *s32, ru_inblock);216CP(*s, *s32, ru_oublock);217CP(*s, *s32, ru_msgsnd);218CP(*s, *s32, ru_msgrcv);219CP(*s, *s32, ru_nsignals);220CP(*s, *s32, ru_nvcsw);221CP(*s, *s32, ru_nivcsw);222}223224int225freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)226{227int error, status;228struct rusage32 ru32;229struct rusage ru, *rup;230231if (uap->rusage != NULL)232rup = &ru;233else234rup = NULL;235error = kern_wait(td, uap->pid, &status, uap->options, rup);236if (error)237return (error);238if (uap->status != NULL)239error = copyout(&status, uap->status, sizeof(status));240if (uap->rusage != NULL && error == 0) {241freebsd32_rusage_out(&ru, &ru32);242error = copyout(&ru32, uap->rusage, sizeof(ru32));243}244return (error);245}246247int248freebsd32_wait6(struct thread *td, struct freebsd32_wait6_args *uap)249{250struct __wrusage32 wru32;251struct __wrusage wru, *wrup;252struct __siginfo32 si32;253struct __siginfo si, *sip;254int error, status;255256if (uap->wrusage != NULL)257wrup = &wru;258else259wrup = NULL;260if (uap->info != NULL) {261sip = &si;262bzero(sip, sizeof(*sip));263} else264sip = NULL;265error = kern_wait6(td, uap->idtype, PAIR32TO64(id_t, uap->id),266&status, uap->options, wrup, sip);267if (error != 0)268return (error);269if (uap->status != NULL)270error = copyout(&status, uap->status, sizeof(status));271if (uap->wrusage != NULL && error == 0) {272freebsd32_rusage_out(&wru.wru_self, &wru32.wru_self);273freebsd32_rusage_out(&wru.wru_children, &wru32.wru_children);274error = copyout(&wru32, uap->wrusage, sizeof(wru32));275}276if (uap->info != NULL && error == 0) {277siginfo_to_siginfo32 (&si, &si32);278error = copyout(&si32, uap->info, sizeof(si32));279}280return (error);281}282283int284freebsd32_pdwait(struct thread *td, struct freebsd32_pdwait_args *uap)285{286struct __wrusage32 wru32;287struct __wrusage wru, *wrup;288struct __siginfo32 si32;289struct __siginfo si, *sip;290int error, status;291292wrup = uap->wrusage != NULL ? &wru : NULL;293if (uap->info != NULL) {294sip = &si;295bzero(sip, sizeof(*sip));296} else {297sip = NULL;298}299error = kern_pdwait(td, uap->fd, &status, uap->options, wrup, sip);300if (uap->status != NULL && error == 0)301error = copyout(&status, uap->status, sizeof(status));302if (uap->wrusage != NULL && error == 0) {303freebsd32_rusage_out(&wru.wru_self, &wru32.wru_self);304freebsd32_rusage_out(&wru.wru_children, &wru32.wru_children);305error = copyout(&wru32, uap->wrusage, sizeof(wru32));306}307if (uap->info != NULL && error == 0) {308siginfo_to_siginfo32 (&si, &si32);309error = copyout(&si32, uap->info, sizeof(si32));310}311return (error);312}313314#ifdef COMPAT_FREEBSD4315static void316copy_statfs(struct statfs *in, struct ostatfs32 *out)317{318319statfs_scale_blocks(in, INT32_MAX);320bzero(out, sizeof(*out));321CP(*in, *out, f_bsize);322out->f_iosize = MIN(in->f_iosize, INT32_MAX);323CP(*in, *out, f_blocks);324CP(*in, *out, f_bfree);325CP(*in, *out, f_bavail);326out->f_files = MIN(in->f_files, INT32_MAX);327out->f_ffree = MIN(in->f_ffree, INT32_MAX);328CP(*in, *out, f_fsid);329CP(*in, *out, f_owner);330CP(*in, *out, f_type);331CP(*in, *out, f_flags);332out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);333out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);334strlcpy(out->f_fstypename,335in->f_fstypename, MFSNAMELEN);336strlcpy(out->f_mntonname,337in->f_mntonname, min(MNAMELEN, FREEBSD4_OMNAMELEN));338out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);339out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);340strlcpy(out->f_mntfromname,341in->f_mntfromname, min(MNAMELEN, FREEBSD4_OMNAMELEN));342}343#endif344345int346freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)347{348size_t count;349int error;350351if (uap->bufsize < 0 || uap->bufsize > SIZE_MAX)352return (EINVAL);353error = kern_getfsstat(td, &uap->buf, uap->bufsize, &count,354UIO_USERSPACE, uap->mode);355if (error == 0)356td->td_retval[0] = count;357return (error);358}359360#ifdef COMPAT_FREEBSD4361int362freebsd4_freebsd32_getfsstat(struct thread *td,363struct freebsd4_freebsd32_getfsstat_args *uap)364{365struct statfs *buf, *sp;366struct ostatfs32 stat32;367size_t count, size, copycount;368int error;369370count = uap->bufsize / sizeof(struct ostatfs32);371size = count * sizeof(struct statfs);372error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE, uap->mode);373if (size > 0) {374sp = buf;375copycount = count;376while (copycount > 0 && error == 0) {377copy_statfs(sp, &stat32);378error = copyout(&stat32, uap->buf, sizeof(stat32));379sp++;380uap->buf++;381copycount--;382}383free(buf, M_STATFS);384}385if (error == 0)386td->td_retval[0] = count;387return (error);388}389#endif390391#ifdef COMPAT_FREEBSD11392int393freebsd11_freebsd32_getfsstat(struct thread *td,394struct freebsd11_freebsd32_getfsstat_args *uap)395{396return(kern_freebsd11_getfsstat(td, uap->buf, uap->bufsize,397uap->mode));398}399#endif400401int402freebsd32_sigaltstack(struct thread *td,403struct freebsd32_sigaltstack_args *uap)404{405struct sigaltstack32 s32;406struct sigaltstack ss, oss, *ssp;407int error;408409if (uap->ss != NULL) {410error = copyin(uap->ss, &s32, sizeof(s32));411if (error)412return (error);413PTRIN_CP(s32, ss, ss_sp);414CP(s32, ss, ss_size);415CP(s32, ss, ss_flags);416ssp = &ss;417} else418ssp = NULL;419error = kern_sigaltstack(td, ssp, &oss);420if (error == 0 && uap->oss != NULL) {421PTROUT_CP(oss, s32, ss_sp);422CP(oss, s32, ss_size);423CP(oss, s32, ss_flags);424error = copyout(&s32, uap->oss, sizeof(s32));425}426return (error);427}428429/*430* Custom version of exec_copyin_args() so that we can translate431* the pointers.432*/433int434freebsd32_exec_copyin_args(struct image_args *args, const char *fname,435uint32_t *argv, uint32_t *envv)436{437char *argp, *envp;438uint32_t *p32, arg;439int error;440441bzero(args, sizeof(*args));442if (argv == NULL)443return (EFAULT);444445/*446* Allocate demand-paged memory for the file name, argument, and447* environment strings.448*/449error = exec_alloc_args(args);450if (error != 0)451return (error);452453/*454* Copy the file name.455*/456error = exec_args_add_fname(args, fname, UIO_USERSPACE);457if (error != 0)458goto err_exit;459460/*461* extract arguments first462*/463p32 = argv;464for (;;) {465error = copyin(p32++, &arg, sizeof(arg));466if (error)467goto err_exit;468if (arg == 0)469break;470argp = PTRIN(arg);471error = exec_args_add_arg(args, argp, UIO_USERSPACE);472if (error != 0)473goto err_exit;474}475476/*477* extract environment strings478*/479if (envv) {480p32 = envv;481for (;;) {482error = copyin(p32++, &arg, sizeof(arg));483if (error)484goto err_exit;485if (arg == 0)486break;487envp = PTRIN(arg);488error = exec_args_add_env(args, envp, UIO_USERSPACE);489if (error != 0)490goto err_exit;491}492}493494return (0);495496err_exit:497exec_free_args(args);498return (error);499}500501int502freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)503{504struct image_args eargs;505struct vmspace *oldvmspace;506int error;507508error = pre_execve(td, &oldvmspace);509if (error != 0)510return (error);511error = freebsd32_exec_copyin_args(&eargs, uap->fname, uap->argv,512uap->envv);513if (error == 0)514error = kern_execve(td, &eargs, NULL, oldvmspace);515post_execve(td, error, oldvmspace);516AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td);517return (error);518}519520int521freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)522{523struct image_args eargs;524struct vmspace *oldvmspace;525int error;526527error = pre_execve(td, &oldvmspace);528if (error != 0)529return (error);530error = freebsd32_exec_copyin_args(&eargs, NULL, uap->argv, uap->envv);531if (error == 0) {532eargs.fd = uap->fd;533error = kern_execve(td, &eargs, NULL, oldvmspace);534}535post_execve(td, error, oldvmspace);536AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td);537return (error);538}539540int541freebsd32_mknodat(struct thread *td, struct freebsd32_mknodat_args *uap)542{543544return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE,545uap->mode, PAIR32TO64(dev_t, uap->dev)));546}547548int549freebsd32_mprotect(struct thread *td, struct freebsd32_mprotect_args *uap)550{551int prot;552553prot = uap->prot;554#if defined(__amd64__)555if (i386_read_exec && (prot & PROT_READ) != 0)556prot |= PROT_EXEC;557#endif558return (kern_mprotect(td, (uintptr_t)PTRIN(uap->addr), uap->len,559prot, 0));560}561562int563freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)564{565int prot;566567prot = uap->prot;568#if defined(__amd64__)569if (i386_read_exec && (prot & PROT_READ))570prot |= PROT_EXEC;571#endif572573return (kern_mmap(td, &(struct mmap_req){574.mr_hint = (uintptr_t)uap->addr,575.mr_len = uap->len,576.mr_prot = prot,577.mr_flags = uap->flags,578.mr_fd = uap->fd,579.mr_pos = PAIR32TO64(off_t, uap->pos),580}));581}582583#ifdef COMPAT_FREEBSD6584int585freebsd6_freebsd32_mmap(struct thread *td,586struct freebsd6_freebsd32_mmap_args *uap)587{588int prot;589590prot = uap->prot;591#if defined(__amd64__)592if (i386_read_exec && (prot & PROT_READ))593prot |= PROT_EXEC;594#endif595596return (kern_mmap(td, &(struct mmap_req){597.mr_hint = (uintptr_t)uap->addr,598.mr_len = uap->len,599.mr_prot = prot,600.mr_flags = uap->flags,601.mr_fd = uap->fd,602.mr_pos = PAIR32TO64(off_t, uap->pos),603}));604}605#endif606607#ifdef COMPAT_43608int609ofreebsd32_mmap(struct thread *td, struct ofreebsd32_mmap_args *uap)610{611return (kern_ommap(td, (uintptr_t)uap->addr, uap->len, uap->prot,612uap->flags, uap->fd, uap->pos));613}614#endif615616int617freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)618{619struct itimerval itv, oitv, *itvp;620struct itimerval32 i32;621int error;622623if (uap->itv != NULL) {624error = copyin(uap->itv, &i32, sizeof(i32));625if (error)626return (error);627TV_CP(i32, itv, it_interval);628TV_CP(i32, itv, it_value);629itvp = &itv;630} else631itvp = NULL;632error = kern_setitimer(td, uap->which, itvp, &oitv);633if (error || uap->oitv == NULL)634return (error);635TV_CP(oitv, i32, it_interval);636TV_CP(oitv, i32, it_value);637return (copyout(&i32, uap->oitv, sizeof(i32)));638}639640int641freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)642{643struct itimerval itv;644struct itimerval32 i32;645int error;646647error = kern_getitimer(td, uap->which, &itv);648if (error || uap->itv == NULL)649return (error);650TV_CP(itv, i32, it_interval);651TV_CP(itv, i32, it_value);652return (copyout(&i32, uap->itv, sizeof(i32)));653}654655int656freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)657{658struct timeval32 tv32;659struct timeval tv, *tvp;660int error;661662if (uap->tv != NULL) {663error = copyin(uap->tv, &tv32, sizeof(tv32));664if (error)665return (error);666CP(tv32, tv, tv_sec);667CP(tv32, tv, tv_usec);668tvp = &tv;669} else670tvp = NULL;671/*672* XXX Do pointers need PTRIN()?673*/674return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,675sizeof(int32_t) * 8));676}677678int679freebsd32_pselect(struct thread *td, struct freebsd32_pselect_args *uap)680{681struct timespec32 ts32;682struct timespec ts;683struct timeval tv, *tvp;684sigset_t set, *uset;685int error;686687if (uap->ts != NULL) {688error = copyin(uap->ts, &ts32, sizeof(ts32));689if (error != 0)690return (error);691CP(ts32, ts, tv_sec);692CP(ts32, ts, tv_nsec);693TIMESPEC_TO_TIMEVAL(&tv, &ts);694tvp = &tv;695} else696tvp = NULL;697if (uap->sm != NULL) {698error = copyin(uap->sm, &set, sizeof(set));699if (error != 0)700return (error);701uset = &set;702} else703uset = NULL;704/*705* XXX Do pointers need PTRIN()?706*/707error = kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,708uset, sizeof(int32_t) * 8);709return (error);710}711712static void713freebsd32_kevent_to_kevent32(const struct kevent *kevp, struct kevent32 *ks32)714{715int j;716717CP(*kevp, *ks32, ident);718CP(*kevp, *ks32, filter);719CP(*kevp, *ks32, flags);720CP(*kevp, *ks32, fflags);721FU64_CP(*kevp, *ks32, data);722PTROUT_CP(*kevp, *ks32, udata);723for (j = 0; j < nitems(kevp->ext); j++)724FU64_CP(*kevp, *ks32, ext[j]);725}726727void728freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,729struct kinfo_knote32 *kin32)730{731memset(kin32, 0, sizeof(*kin32));732CP(*kin, *kin32, knt_kq_fd);733freebsd32_kevent_to_kevent32(&kin->knt_event, &kin32->knt_event);734CP(*kin, *kin32, knt_status);735CP(*kin, *kin32, knt_extdata);736switch (kin->knt_extdata) {737case KNOTE_EXTDATA_NONE:738break;739case KNOTE_EXTDATA_VNODE:740CP(*kin, *kin32, knt_vnode.knt_vnode_type);741FU64_CP(*kin, *kin32, knt_vnode.knt_vnode_fsid);742FU64_CP(*kin, *kin32, knt_vnode.knt_vnode_fileid);743memcpy(kin32->knt_vnode.knt_vnode_fullpath,744kin->knt_vnode.knt_vnode_fullpath, PATH_MAX);745break;746case KNOTE_EXTDATA_PIPE:747FU64_CP(*kin, *kin32, knt_pipe.knt_pipe_ino);748break;749}750}751752/*753* Copy 'count' items into the destination list pointed to by uap->eventlist.754*/755static int756freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)757{758struct freebsd32_kevent_args *uap;759struct kevent32 ks32[KQ_NEVENTS];760int i, error;761762KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));763uap = (struct freebsd32_kevent_args *)arg;764765for (i = 0; i < count; i++)766freebsd32_kevent_to_kevent32(&kevp[i], &ks32[i]);767error = copyout(ks32, uap->eventlist, count * sizeof *ks32);768if (error == 0)769uap->eventlist += count;770return (error);771}772773/*774* Copy 'count' items from the list pointed to by uap->changelist.775*/776static int777freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)778{779struct freebsd32_kevent_args *uap;780struct kevent32 ks32[KQ_NEVENTS];781int i, j, error;782783KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));784uap = (struct freebsd32_kevent_args *)arg;785786error = copyin(uap->changelist, ks32, count * sizeof *ks32);787if (error)788goto done;789uap->changelist += count;790791for (i = 0; i < count; i++) {792CP(ks32[i], kevp[i], ident);793CP(ks32[i], kevp[i], filter);794CP(ks32[i], kevp[i], flags);795CP(ks32[i], kevp[i], fflags);796FU64_CP(ks32[i], kevp[i], data);797PTRIN_CP(ks32[i], kevp[i], udata);798for (j = 0; j < nitems(kevp->ext); j++)799FU64_CP(ks32[i], kevp[i], ext[j]);800}801done:802return (error);803}804805int806freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)807{808struct timespec32 ts32;809struct timespec ts, *tsp;810struct kevent_copyops k_ops = {811.arg = uap,812.k_copyout = freebsd32_kevent_copyout,813.k_copyin = freebsd32_kevent_copyin,814};815#ifdef KTRACE816struct kevent32 *eventlist = uap->eventlist;817#endif818int error;819820if (uap->timeout) {821error = copyin(uap->timeout, &ts32, sizeof(ts32));822if (error)823return (error);824CP(ts32, ts, tv_sec);825CP(ts32, ts, tv_nsec);826tsp = &ts;827} else828tsp = NULL;829#ifdef KTRACE830if (KTRPOINT(td, KTR_STRUCT_ARRAY))831ktrstructarray("kevent32", UIO_USERSPACE, uap->changelist,832uap->nchanges, sizeof(struct kevent32));833#endif834error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,835&k_ops, tsp);836#ifdef KTRACE837if (error == 0 && KTRPOINT(td, KTR_STRUCT_ARRAY))838ktrstructarray("kevent32", UIO_USERSPACE, eventlist,839td->td_retval[0], sizeof(struct kevent32));840#endif841return (error);842}843844#ifdef COMPAT_FREEBSD11845static int846freebsd32_kevent11_copyout(void *arg, struct kevent *kevp, int count)847{848struct freebsd11_freebsd32_kevent_args *uap;849struct freebsd11_kevent32 ks32[KQ_NEVENTS];850int i, error;851852KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));853uap = (struct freebsd11_freebsd32_kevent_args *)arg;854855for (i = 0; i < count; i++) {856CP(kevp[i], ks32[i], ident);857CP(kevp[i], ks32[i], filter);858CP(kevp[i], ks32[i], flags);859CP(kevp[i], ks32[i], fflags);860CP(kevp[i], ks32[i], data);861PTROUT_CP(kevp[i], ks32[i], udata);862}863error = copyout(ks32, uap->eventlist, count * sizeof *ks32);864if (error == 0)865uap->eventlist += count;866return (error);867}868869/*870* Copy 'count' items from the list pointed to by uap->changelist.871*/872static int873freebsd32_kevent11_copyin(void *arg, struct kevent *kevp, int count)874{875struct freebsd11_freebsd32_kevent_args *uap;876struct freebsd11_kevent32 ks32[KQ_NEVENTS];877int i, j, error;878879KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));880uap = (struct freebsd11_freebsd32_kevent_args *)arg;881882error = copyin(uap->changelist, ks32, count * sizeof *ks32);883if (error)884goto done;885uap->changelist += count;886887for (i = 0; i < count; i++) {888CP(ks32[i], kevp[i], ident);889CP(ks32[i], kevp[i], filter);890CP(ks32[i], kevp[i], flags);891CP(ks32[i], kevp[i], fflags);892CP(ks32[i], kevp[i], data);893PTRIN_CP(ks32[i], kevp[i], udata);894for (j = 0; j < nitems(kevp->ext); j++)895kevp[i].ext[j] = 0;896}897done:898return (error);899}900901int902freebsd11_freebsd32_kevent(struct thread *td,903struct freebsd11_freebsd32_kevent_args *uap)904{905struct timespec32 ts32;906struct timespec ts, *tsp;907struct kevent_copyops k_ops = {908.arg = uap,909.k_copyout = freebsd32_kevent11_copyout,910.k_copyin = freebsd32_kevent11_copyin,911};912#ifdef KTRACE913struct freebsd11_kevent32 *eventlist = uap->eventlist;914#endif915int error;916917if (uap->timeout) {918error = copyin(uap->timeout, &ts32, sizeof(ts32));919if (error)920return (error);921CP(ts32, ts, tv_sec);922CP(ts32, ts, tv_nsec);923tsp = &ts;924} else925tsp = NULL;926#ifdef KTRACE927if (KTRPOINT(td, KTR_STRUCT_ARRAY))928ktrstructarray("freebsd11_kevent32", UIO_USERSPACE,929uap->changelist, uap->nchanges,930sizeof(struct freebsd11_kevent32));931#endif932error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,933&k_ops, tsp);934#ifdef KTRACE935if (error == 0 && KTRPOINT(td, KTR_STRUCT_ARRAY))936ktrstructarray("freebsd11_kevent32", UIO_USERSPACE,937eventlist, td->td_retval[0],938sizeof(struct freebsd11_kevent32));939#endif940return (error);941}942#endif943944int945freebsd32_gettimeofday(struct thread *td,946struct freebsd32_gettimeofday_args *uap)947{948struct timeval atv;949struct timeval32 atv32;950struct timezone rtz;951int error = 0;952953if (uap->tp) {954microtime(&atv);955CP(atv, atv32, tv_sec);956CP(atv, atv32, tv_usec);957error = copyout(&atv32, uap->tp, sizeof (atv32));958}959if (error == 0 && uap->tzp != NULL) {960rtz.tz_minuteswest = 0;961rtz.tz_dsttime = 0;962error = copyout(&rtz, uap->tzp, sizeof (rtz));963}964return (error);965}966967int968freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)969{970struct rusage32 s32;971struct rusage s;972int error;973974error = kern_getrusage(td, uap->who, &s);975if (error == 0) {976freebsd32_rusage_out(&s, &s32);977error = copyout(&s32, uap->rusage, sizeof(s32));978}979return (error);980}981982static void983ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,984struct ptrace_lwpinfo32 *pl32)985{986987bzero(pl32, sizeof(*pl32));988pl32->pl_lwpid = pl->pl_lwpid;989pl32->pl_event = pl->pl_event;990pl32->pl_flags = pl->pl_flags;991pl32->pl_sigmask = pl->pl_sigmask;992pl32->pl_siglist = pl->pl_siglist;993siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);994strcpy(pl32->pl_tdname, pl->pl_tdname);995pl32->pl_child_pid = pl->pl_child_pid;996pl32->pl_syscall_code = pl->pl_syscall_code;997pl32->pl_syscall_narg = pl->pl_syscall_narg;998}9991000static void1001ptrace_sc_ret_to32(const struct ptrace_sc_ret *psr,1002struct ptrace_sc_ret32 *psr32)1003{10041005bzero(psr32, sizeof(*psr32));1006psr32->sr_retval[0] = psr->sr_retval[0];1007psr32->sr_retval[1] = psr->sr_retval[1];1008psr32->sr_error = psr->sr_error;1009}10101011int1012freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)1013{1014union {1015struct ptrace_io_desc piod;1016struct ptrace_lwpinfo pl;1017struct ptrace_vm_entry pve;1018struct ptrace_coredump pc;1019struct ptrace_sc_remote sr;1020struct dbreg32 dbreg;1021struct fpreg32 fpreg;1022struct reg32 reg;1023struct iovec vec;1024register_t args[nitems(td->td_sa.args)];1025struct ptrace_sc_ret psr;1026int ptevents;1027} r;1028union {1029struct ptrace_io_desc32 piod;1030struct ptrace_lwpinfo32 pl;1031struct ptrace_vm_entry32 pve;1032struct ptrace_coredump32 pc;1033struct ptrace_sc_remote32 sr;1034uint32_t args[nitems(td->td_sa.args)];1035struct ptrace_sc_ret32 psr;1036struct iovec32 vec;1037} r32;1038syscallarg_t pscr_args[nitems(td->td_sa.args)];1039u_int pscr_args32[nitems(td->td_sa.args)];1040void *addr;1041int data, error, i;10421043if (!allow_ptrace)1044return (ENOSYS);1045error = 0;10461047AUDIT_ARG_PID(uap->pid);1048AUDIT_ARG_CMD(uap->req);1049AUDIT_ARG_VALUE(uap->data);1050addr = &r;1051data = uap->data;1052switch (uap->req) {1053case PT_GET_EVENT_MASK:1054case PT_GET_SC_ARGS:1055case PT_GET_SC_RET:1056break;1057case PT_LWPINFO:1058if (uap->data > sizeof(r32.pl))1059return (EINVAL);10601061/*1062* Pass size of native structure in 'data'. Truncate1063* if necessary to avoid siginfo.1064*/1065data = sizeof(r.pl);1066if (uap->data < offsetof(struct ptrace_lwpinfo32, pl_siginfo) +1067sizeof(struct __siginfo32))1068data = offsetof(struct ptrace_lwpinfo, pl_siginfo);1069break;1070case PT_GETREGS:1071bzero(&r.reg, sizeof(r.reg));1072break;1073case PT_GETFPREGS:1074bzero(&r.fpreg, sizeof(r.fpreg));1075break;1076case PT_GETDBREGS:1077bzero(&r.dbreg, sizeof(r.dbreg));1078break;1079case PT_SETREGS:1080error = copyin(uap->addr, &r.reg, sizeof(r.reg));1081break;1082case PT_SETFPREGS:1083error = copyin(uap->addr, &r.fpreg, sizeof(r.fpreg));1084break;1085case PT_SETDBREGS:1086error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg));1087break;1088case PT_GETREGSET:1089case PT_SETREGSET:1090error = copyin(uap->addr, &r32.vec, sizeof(r32.vec));1091if (error != 0)1092break;10931094r.vec.iov_len = r32.vec.iov_len;1095r.vec.iov_base = PTRIN(r32.vec.iov_base);1096break;1097case PT_SET_EVENT_MASK:1098if (uap->data != sizeof(r.ptevents))1099error = EINVAL;1100else1101error = copyin(uap->addr, &r.ptevents, uap->data);1102break;1103case PT_IO:1104error = copyin(uap->addr, &r32.piod, sizeof(r32.piod));1105if (error)1106break;1107CP(r32.piod, r.piod, piod_op);1108PTRIN_CP(r32.piod, r.piod, piod_offs);1109PTRIN_CP(r32.piod, r.piod, piod_addr);1110CP(r32.piod, r.piod, piod_len);1111break;1112case PT_VM_ENTRY:1113error = copyin(uap->addr, &r32.pve, sizeof(r32.pve));1114if (error)1115break;11161117CP(r32.pve, r.pve, pve_entry);1118CP(r32.pve, r.pve, pve_timestamp);1119CP(r32.pve, r.pve, pve_start);1120CP(r32.pve, r.pve, pve_end);1121CP(r32.pve, r.pve, pve_offset);1122CP(r32.pve, r.pve, pve_prot);1123CP(r32.pve, r.pve, pve_pathlen);1124CP(r32.pve, r.pve, pve_fileid);1125CP(r32.pve, r.pve, pve_fsid);1126PTRIN_CP(r32.pve, r.pve, pve_path);1127break;1128case PT_COREDUMP:1129if (uap->data != sizeof(r32.pc))1130error = EINVAL;1131else1132error = copyin(uap->addr, &r32.pc, uap->data);1133CP(r32.pc, r.pc, pc_fd);1134CP(r32.pc, r.pc, pc_flags);1135r.pc.pc_limit = PAIR32TO64(off_t, r32.pc.pc_limit);1136data = sizeof(r.pc);1137break;1138case PT_SC_REMOTE:1139if (uap->data != sizeof(r32.sr)) {1140error = EINVAL;1141break;1142}1143error = copyin(uap->addr, &r32.sr, uap->data);1144if (error != 0)1145break;1146CP(r32.sr, r.sr, pscr_syscall);1147CP(r32.sr, r.sr, pscr_nargs);1148if (r.sr.pscr_nargs > nitems(td->td_sa.args)) {1149error = EINVAL;1150break;1151}1152error = copyin(PTRIN(r32.sr.pscr_args), pscr_args32,1153sizeof(u_int) * r32.sr.pscr_nargs);1154if (error != 0)1155break;1156for (i = 0; i < r32.sr.pscr_nargs; i++)1157pscr_args[i] = pscr_args32[i];1158r.sr.pscr_args = pscr_args;1159break;1160case PTINTERNAL_FIRST ... PTINTERNAL_LAST:1161error = EINVAL;1162break;1163default:1164addr = uap->addr;1165break;1166}1167if (error)1168return (error);11691170error = kern_ptrace(td, uap->req, uap->pid, addr, data);1171if (error)1172return (error);11731174switch (uap->req) {1175case PT_VM_ENTRY:1176CP(r.pve, r32.pve, pve_entry);1177CP(r.pve, r32.pve, pve_timestamp);1178CP(r.pve, r32.pve, pve_start);1179CP(r.pve, r32.pve, pve_end);1180CP(r.pve, r32.pve, pve_offset);1181CP(r.pve, r32.pve, pve_prot);1182CP(r.pve, r32.pve, pve_pathlen);1183CP(r.pve, r32.pve, pve_fileid);1184CP(r.pve, r32.pve, pve_fsid);1185error = copyout(&r32.pve, uap->addr, sizeof(r32.pve));1186break;1187case PT_IO:1188CP(r.piod, r32.piod, piod_len);1189error = copyout(&r32.piod, uap->addr, sizeof(r32.piod));1190break;1191case PT_GETREGS:1192error = copyout(&r.reg, uap->addr, sizeof(r.reg));1193break;1194case PT_GETFPREGS:1195error = copyout(&r.fpreg, uap->addr, sizeof(r.fpreg));1196break;1197case PT_GETDBREGS:1198error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));1199break;1200case PT_GETREGSET:1201r32.vec.iov_len = r.vec.iov_len;1202error = copyout(&r32.vec, uap->addr, sizeof(r32.vec));1203break;1204case PT_GET_EVENT_MASK:1205/* NB: The size in uap->data is validated in kern_ptrace(). */1206error = copyout(&r.ptevents, uap->addr, uap->data);1207break;1208case PT_LWPINFO:1209ptrace_lwpinfo_to32(&r.pl, &r32.pl);1210error = copyout(&r32.pl, uap->addr, uap->data);1211break;1212case PT_GET_SC_ARGS:1213for (i = 0; i < nitems(r.args); i++)1214r32.args[i] = (uint32_t)r.args[i];1215error = copyout(r32.args, uap->addr, MIN(uap->data,1216sizeof(r32.args)));1217break;1218case PT_GET_SC_RET:1219ptrace_sc_ret_to32(&r.psr, &r32.psr);1220error = copyout(&r32.psr, uap->addr, MIN(uap->data,1221sizeof(r32.psr)));1222break;1223case PT_SC_REMOTE:1224ptrace_sc_ret_to32(&r.sr.pscr_ret, &r32.sr.pscr_ret);1225error = copyout(&r32.sr.pscr_ret, uap->addr +1226offsetof(struct ptrace_sc_remote32, pscr_ret),1227sizeof(r32.psr));1228break;1229}12301231return (error);1232}12331234int1235freebsd32_copyinuio(const struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)1236{1237struct iovec32 iov32;1238struct iovec *iov;1239struct uio *uio;1240int error, i;12411242*uiop = NULL;1243if (iovcnt > UIO_MAXIOV)1244return (EINVAL);1245uio = allocuio(iovcnt);1246iov = uio->uio_iov;1247for (i = 0; i < iovcnt; i++) {1248error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));1249if (error) {1250freeuio(uio);1251return (error);1252}1253iov[i].iov_base = PTRIN(iov32.iov_base);1254iov[i].iov_len = iov32.iov_len;1255}1256uio->uio_iovcnt = iovcnt;1257uio->uio_segflg = UIO_USERSPACE;1258uio->uio_offset = -1;1259uio->uio_resid = 0;1260for (i = 0; i < iovcnt; i++) {1261if (iov->iov_len > INT_MAX - uio->uio_resid) {1262freeuio(uio);1263return (EINVAL);1264}1265uio->uio_resid += iov->iov_len;1266iov++;1267}1268*uiop = uio;1269return (0);1270}12711272int1273freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)1274{1275struct uio *auio;1276int error;12771278error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);1279if (error)1280return (error);1281error = kern_readv(td, uap->fd, auio);1282freeuio(auio);1283return (error);1284}12851286int1287freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)1288{1289struct uio *auio;1290int error;12911292error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);1293if (error)1294return (error);1295error = kern_writev(td, uap->fd, auio);1296freeuio(auio);1297return (error);1298}12991300int1301freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)1302{1303struct uio *auio;1304int error;13051306error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);1307if (error)1308return (error);1309error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));1310freeuio(auio);1311return (error);1312}13131314int1315freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)1316{1317struct uio *auio;1318int error;13191320error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);1321if (error)1322return (error);1323error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));1324freeuio(auio);1325return (error);1326}13271328int1329freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,1330int error)1331{1332struct iovec32 iov32;1333struct iovec *iov;1334u_int iovlen;1335int i;13361337*iovp = NULL;1338if (iovcnt > UIO_MAXIOV)1339return (error);1340iovlen = iovcnt * sizeof(struct iovec);1341iov = malloc(iovlen, M_IOV, M_WAITOK);1342for (i = 0; i < iovcnt; i++) {1343error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));1344if (error) {1345free(iov, M_IOV);1346return (error);1347}1348iov[i].iov_base = PTRIN(iov32.iov_base);1349iov[i].iov_len = iov32.iov_len;1350}1351*iovp = iov;1352return (0);1353}13541355static int1356freebsd32_copyinmsghdr(const struct msghdr32 *msg32, struct msghdr *msg)1357{1358struct msghdr32 m32;1359int error;13601361error = copyin(msg32, &m32, sizeof(m32));1362if (error)1363return (error);1364msg->msg_name = PTRIN(m32.msg_name);1365msg->msg_namelen = m32.msg_namelen;1366msg->msg_iov = PTRIN(m32.msg_iov);1367msg->msg_iovlen = m32.msg_iovlen;1368msg->msg_control = PTRIN(m32.msg_control);1369msg->msg_controllen = m32.msg_controllen;1370msg->msg_flags = m32.msg_flags;1371return (0);1372}13731374static int1375freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)1376{1377struct msghdr32 m32;1378int error;13791380m32.msg_name = PTROUT(msg->msg_name);1381m32.msg_namelen = msg->msg_namelen;1382m32.msg_iov = PTROUT(msg->msg_iov);1383m32.msg_iovlen = msg->msg_iovlen;1384m32.msg_control = PTROUT(msg->msg_control);1385m32.msg_controllen = msg->msg_controllen;1386m32.msg_flags = msg->msg_flags;1387error = copyout(&m32, msg32, sizeof(m32));1388return (error);1389}13901391#define FREEBSD32_ALIGNBYTES (sizeof(int) - 1)1392#define FREEBSD32_ALIGN(p) \1393(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)1394#define FREEBSD32_CMSG_SPACE(l) \1395(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))13961397#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \1398FREEBSD32_ALIGN(sizeof(struct cmsghdr)))13991400static size_t1401freebsd32_cmsg_convert(const struct cmsghdr *cm, void *data, socklen_t datalen)1402{1403size_t copylen;1404union {1405struct timespec32 ts;1406struct timeval32 tv;1407struct bintime32 bt;1408} tmp32;14091410union {1411struct timespec ts;1412struct timeval tv;1413struct bintime bt;1414} *in;14151416in = data;1417copylen = 0;1418switch (cm->cmsg_level) {1419case SOL_SOCKET:1420switch (cm->cmsg_type) {1421case SCM_TIMESTAMP:1422TV_CP(*in, tmp32, tv);1423copylen = sizeof(tmp32.tv);1424break;14251426case SCM_BINTIME:1427BT_CP(*in, tmp32, bt);1428copylen = sizeof(tmp32.bt);1429break;14301431case SCM_REALTIME:1432case SCM_MONOTONIC:1433TS_CP(*in, tmp32, ts);1434copylen = sizeof(tmp32.ts);1435break;14361437default:1438break;1439}14401441default:1442break;1443}14441445if (copylen == 0)1446return (datalen);14471448KASSERT((datalen >= copylen), ("corrupted cmsghdr"));14491450bcopy(&tmp32, data, copylen);1451return (copylen);1452}14531454static int1455freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)1456{1457struct cmsghdr *cm;1458void *data;1459socklen_t clen, datalen, datalen_out, oldclen;1460int error;1461caddr_t ctlbuf;1462int len, copylen;1463struct mbuf *m;1464error = 0;14651466len = msg->msg_controllen;1467msg->msg_controllen = 0;14681469ctlbuf = msg->msg_control;1470for (m = control; m != NULL && len > 0; m = m->m_next) {1471cm = mtod(m, struct cmsghdr *);1472clen = m->m_len;1473while (cm != NULL) {1474if (sizeof(struct cmsghdr) > clen ||1475cm->cmsg_len > clen) {1476error = EINVAL;1477break;1478}14791480data = CMSG_DATA(cm);1481datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;1482datalen_out = freebsd32_cmsg_convert(cm, data, datalen);14831484/*1485* Copy out the message header. Preserve the native1486* message size in case we need to inspect the message1487* contents later.1488*/1489copylen = sizeof(struct cmsghdr);1490if (len < copylen) {1491msg->msg_flags |= MSG_CTRUNC;1492m_dispose_extcontrolm(m);1493goto exit;1494}1495oldclen = cm->cmsg_len;1496cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +1497datalen_out;1498error = copyout(cm, ctlbuf, copylen);1499cm->cmsg_len = oldclen;1500if (error != 0)1501goto exit;15021503ctlbuf += FREEBSD32_ALIGN(copylen);1504len -= FREEBSD32_ALIGN(copylen);15051506copylen = datalen_out;1507if (len < copylen) {1508msg->msg_flags |= MSG_CTRUNC;1509m_dispose_extcontrolm(m);1510break;1511}15121513/* Copy out the message data. */1514error = copyout(data, ctlbuf, copylen);1515if (error)1516goto exit;15171518ctlbuf += FREEBSD32_ALIGN(copylen);1519len -= FREEBSD32_ALIGN(copylen);15201521if (CMSG_SPACE(datalen) < clen) {1522clen -= CMSG_SPACE(datalen);1523cm = (struct cmsghdr *)1524((caddr_t)cm + CMSG_SPACE(datalen));1525} else {1526clen = 0;1527cm = NULL;1528}15291530msg->msg_controllen +=1531FREEBSD32_CMSG_SPACE(datalen_out);1532}1533}1534if (len == 0 && m != NULL) {1535msg->msg_flags |= MSG_CTRUNC;1536m_dispose_extcontrolm(m);1537}15381539exit:1540return (error);1541}15421543int1544freebsd32_recvmsg(struct thread *td, struct freebsd32_recvmsg_args *uap)1545{1546struct msghdr msg;1547struct iovec *uiov, *iov;1548struct mbuf *control = NULL;1549struct mbuf **controlp;1550int error;15511552error = freebsd32_copyinmsghdr(uap->msg, &msg);1553if (error)1554return (error);1555error = freebsd32_copyiniov((void *)msg.msg_iov, msg.msg_iovlen, &iov,1556EMSGSIZE);1557if (error)1558return (error);1559msg.msg_flags = uap->flags;1560uiov = msg.msg_iov;1561msg.msg_iov = iov;15621563controlp = (msg.msg_control != NULL) ? &control : NULL;1564error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);1565if (error == 0) {1566msg.msg_iov = uiov;15671568if (control != NULL)1569error = freebsd32_copy_msg_out(&msg, control);1570else1571msg.msg_controllen = 0;15721573if (error == 0)1574error = freebsd32_copyoutmsghdr(&msg, uap->msg);1575}1576free(iov, M_IOV);15771578if (control != NULL) {1579if (error != 0)1580m_dispose_extcontrolm(control);1581m_freem(control);1582}15831584return (error);1585}15861587#ifdef COMPAT_431588int1589ofreebsd32_recvmsg(struct thread *td, struct ofreebsd32_recvmsg_args *uap)1590{1591return (ENOSYS);1592}1593#endif15941595/*1596* Copy-in the array of control messages constructed using alignment1597* and padding suitable for a 32-bit environment and construct an1598* mbuf using alignment and padding suitable for a 64-bit kernel.1599* The alignment and padding are defined indirectly by CMSG_DATA(),1600* CMSG_SPACE() and CMSG_LEN().1601*/1602static int1603freebsd32_copyin_control(struct mbuf **mp, caddr_t buf, u_int buflen)1604{1605struct cmsghdr *cm;1606struct mbuf *m;1607void *in, *in1, *md;1608u_int msglen, outlen;1609int error;16101611/* Enforce the size limit of the native implementation. */1612if (buflen > MCLBYTES)1613return (EINVAL);16141615in = malloc(buflen, M_TEMP, M_WAITOK);1616error = copyin(buf, in, buflen);1617if (error != 0)1618goto out;16191620/*1621* Make a pass over the input buffer to determine the amount of space1622* required for 64 bit-aligned copies of the control messages.1623*/1624in1 = in;1625outlen = 0;1626while (buflen > 0) {1627if (buflen < sizeof(*cm)) {1628error = EINVAL;1629break;1630}1631cm = (struct cmsghdr *)in1;1632if (cm->cmsg_len < FREEBSD32_ALIGN(sizeof(*cm)) ||1633cm->cmsg_len > buflen) {1634error = EINVAL;1635break;1636}1637msglen = FREEBSD32_ALIGN(cm->cmsg_len);1638if (msglen < cm->cmsg_len) {1639error = EINVAL;1640break;1641}1642/* The native ABI permits the final padding to be omitted. */1643if (msglen > buflen)1644msglen = buflen;1645buflen -= msglen;16461647in1 = (char *)in1 + msglen;1648outlen += CMSG_ALIGN(sizeof(*cm)) +1649CMSG_ALIGN(msglen - FREEBSD32_ALIGN(sizeof(*cm)));1650}1651if (error != 0)1652goto out;16531654/*1655* Allocate up to MJUMPAGESIZE space for the re-aligned and1656* re-padded control messages. This allows a full MCLBYTES of1657* 32-bit sized and aligned messages to fit and avoids an ABI1658* mismatch with the native implementation.1659*/1660m = m_get2(outlen, M_WAITOK, MT_CONTROL, 0);1661if (m == NULL) {1662error = EINVAL;1663goto out;1664}1665m->m_len = outlen;1666md = mtod(m, void *);16671668/*1669* Make a second pass over input messages, copying them into the output1670* buffer.1671*/1672in1 = in;1673while (outlen > 0) {1674/* Copy the message header and align the length field. */1675cm = md;1676memcpy(cm, in1, sizeof(*cm));1677msglen = cm->cmsg_len - FREEBSD32_ALIGN(sizeof(*cm));1678cm->cmsg_len = CMSG_ALIGN(sizeof(*cm)) + msglen;16791680/* Copy the message body. */1681in1 = (char *)in1 + FREEBSD32_ALIGN(sizeof(*cm));1682md = (char *)md + CMSG_ALIGN(sizeof(*cm));1683memcpy(md, in1, msglen);1684in1 = (char *)in1 + FREEBSD32_ALIGN(msglen);1685md = (char *)md + CMSG_ALIGN(msglen);1686KASSERT(outlen >= CMSG_ALIGN(sizeof(*cm)) + CMSG_ALIGN(msglen),1687("outlen %u underflow, msglen %u", outlen, msglen));1688outlen -= CMSG_ALIGN(sizeof(*cm)) + CMSG_ALIGN(msglen);1689}16901691*mp = m;1692out:1693free(in, M_TEMP);1694return (error);1695}16961697int1698freebsd32_sendmsg(struct thread *td, struct freebsd32_sendmsg_args *uap)1699{1700struct msghdr msg;1701struct iovec *iov;1702struct mbuf *control = NULL;1703struct sockaddr *to = NULL;1704int error;17051706error = freebsd32_copyinmsghdr(uap->msg, &msg);1707if (error)1708return (error);1709error = freebsd32_copyiniov((void *)msg.msg_iov, msg.msg_iovlen, &iov,1710EMSGSIZE);1711if (error)1712return (error);1713msg.msg_iov = iov;1714if (msg.msg_name != NULL) {1715error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);1716if (error) {1717to = NULL;1718goto out;1719}1720msg.msg_name = to;1721}17221723if (msg.msg_control) {1724if (msg.msg_controllen < sizeof(struct cmsghdr)) {1725error = EINVAL;1726goto out;1727}17281729error = freebsd32_copyin_control(&control, msg.msg_control,1730msg.msg_controllen);1731if (error)1732goto out;17331734msg.msg_control = NULL;1735msg.msg_controllen = 0;1736}17371738error = kern_sendit(td, uap->s, &msg, uap->flags, control,1739UIO_USERSPACE);17401741out:1742free(iov, M_IOV);1743if (to)1744free(to, M_SONAME);1745return (error);1746}17471748#ifdef COMPAT_431749int1750ofreebsd32_sendmsg(struct thread *td, struct ofreebsd32_sendmsg_args *uap)1751{1752return (ENOSYS);1753}1754#endif175517561757int1758freebsd32_settimeofday(struct thread *td,1759struct freebsd32_settimeofday_args *uap)1760{1761struct timeval32 tv32;1762struct timeval tv, *tvp;1763struct timezone tz, *tzp;1764int error;17651766if (uap->tv) {1767error = copyin(uap->tv, &tv32, sizeof(tv32));1768if (error)1769return (error);1770CP(tv32, tv, tv_sec);1771CP(tv32, tv, tv_usec);1772tvp = &tv;1773} else1774tvp = NULL;1775if (uap->tzp) {1776error = copyin(uap->tzp, &tz, sizeof(tz));1777if (error)1778return (error);1779tzp = &tz;1780} else1781tzp = NULL;1782return (kern_settimeofday(td, tvp, tzp));1783}17841785int1786freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)1787{1788struct timeval32 s32[2];1789struct timeval s[2], *sp;1790int error;17911792if (uap->tptr != NULL) {1793error = copyin(uap->tptr, s32, sizeof(s32));1794if (error)1795return (error);1796CP(s32[0], s[0], tv_sec);1797CP(s32[0], s[0], tv_usec);1798CP(s32[1], s[1], tv_sec);1799CP(s32[1], s[1], tv_usec);1800sp = s;1801} else1802sp = NULL;1803return (kern_utimesat(td, AT_FDCWD, uap->path, UIO_USERSPACE,1804sp, UIO_SYSSPACE));1805}18061807int1808freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)1809{1810struct timeval32 s32[2];1811struct timeval s[2], *sp;1812int error;18131814if (uap->tptr != NULL) {1815error = copyin(uap->tptr, s32, sizeof(s32));1816if (error)1817return (error);1818CP(s32[0], s[0], tv_sec);1819CP(s32[0], s[0], tv_usec);1820CP(s32[1], s[1], tv_sec);1821CP(s32[1], s[1], tv_usec);1822sp = s;1823} else1824sp = NULL;1825return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));1826}18271828int1829freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)1830{1831struct timeval32 s32[2];1832struct timeval s[2], *sp;1833int error;18341835if (uap->tptr != NULL) {1836error = copyin(uap->tptr, s32, sizeof(s32));1837if (error)1838return (error);1839CP(s32[0], s[0], tv_sec);1840CP(s32[0], s[0], tv_usec);1841CP(s32[1], s[1], tv_sec);1842CP(s32[1], s[1], tv_usec);1843sp = s;1844} else1845sp = NULL;1846return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));1847}18481849int1850freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)1851{1852struct timeval32 s32[2];1853struct timeval s[2], *sp;1854int error;18551856if (uap->times != NULL) {1857error = copyin(uap->times, s32, sizeof(s32));1858if (error)1859return (error);1860CP(s32[0], s[0], tv_sec);1861CP(s32[0], s[0], tv_usec);1862CP(s32[1], s[1], tv_sec);1863CP(s32[1], s[1], tv_usec);1864sp = s;1865} else1866sp = NULL;1867return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,1868sp, UIO_SYSSPACE));1869}18701871int1872freebsd32_futimens(struct thread *td, struct freebsd32_futimens_args *uap)1873{1874struct timespec32 ts32[2];1875struct timespec ts[2], *tsp;1876int error;18771878if (uap->times != NULL) {1879error = copyin(uap->times, ts32, sizeof(ts32));1880if (error)1881return (error);1882CP(ts32[0], ts[0], tv_sec);1883CP(ts32[0], ts[0], tv_nsec);1884CP(ts32[1], ts[1], tv_sec);1885CP(ts32[1], ts[1], tv_nsec);1886tsp = ts;1887} else1888tsp = NULL;1889return (kern_futimens(td, uap->fd, tsp, UIO_SYSSPACE));1890}18911892int1893freebsd32_utimensat(struct thread *td, struct freebsd32_utimensat_args *uap)1894{1895struct timespec32 ts32[2];1896struct timespec ts[2], *tsp;1897int error;18981899if (uap->times != NULL) {1900error = copyin(uap->times, ts32, sizeof(ts32));1901if (error)1902return (error);1903CP(ts32[0], ts[0], tv_sec);1904CP(ts32[0], ts[0], tv_nsec);1905CP(ts32[1], ts[1], tv_sec);1906CP(ts32[1], ts[1], tv_nsec);1907tsp = ts;1908} else1909tsp = NULL;1910return (kern_utimensat(td, uap->fd, uap->path, UIO_USERSPACE,1911tsp, UIO_SYSSPACE, uap->flag));1912}19131914int1915freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)1916{1917struct timeval32 tv32;1918struct timeval delta, olddelta, *deltap;1919int error;19201921if (uap->delta) {1922error = copyin(uap->delta, &tv32, sizeof(tv32));1923if (error)1924return (error);1925CP(tv32, delta, tv_sec);1926CP(tv32, delta, tv_usec);1927deltap = δ1928} else1929deltap = NULL;1930error = kern_adjtime(td, deltap, &olddelta);1931if (uap->olddelta && error == 0) {1932CP(olddelta, tv32, tv_sec);1933CP(olddelta, tv32, tv_usec);1934error = copyout(&tv32, uap->olddelta, sizeof(tv32));1935}1936return (error);1937}19381939#ifdef COMPAT_FREEBSD41940int1941freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)1942{1943struct ostatfs32 s32;1944struct statfs *sp;1945int error;19461947sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);1948error = kern_statfs(td, uap->path, UIO_USERSPACE, sp);1949if (error == 0) {1950copy_statfs(sp, &s32);1951error = copyout(&s32, uap->buf, sizeof(s32));1952}1953free(sp, M_STATFS);1954return (error);1955}1956#endif19571958#ifdef COMPAT_FREEBSD41959int1960freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)1961{1962struct ostatfs32 s32;1963struct statfs *sp;1964int error;19651966sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);1967error = kern_fstatfs(td, uap->fd, sp);1968if (error == 0) {1969copy_statfs(sp, &s32);1970error = copyout(&s32, uap->buf, sizeof(s32));1971}1972free(sp, M_STATFS);1973return (error);1974}1975#endif19761977#ifdef COMPAT_FREEBSD41978int1979freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)1980{1981struct ostatfs32 s32;1982struct statfs *sp;1983fhandle_t fh;1984int error;19851986if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)1987return (error);1988sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);1989error = kern_fhstatfs(td, fh, sp);1990if (error == 0) {1991copy_statfs(sp, &s32);1992error = copyout(&s32, uap->buf, sizeof(s32));1993}1994free(sp, M_STATFS);1995return (error);1996}1997#endif19981999int2000freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)2001{20022003return (kern_pread(td, uap->fd, uap->buf, uap->nbyte,2004PAIR32TO64(off_t, uap->offset)));2005}20062007int2008freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)2009{20102011return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte,2012PAIR32TO64(off_t, uap->offset)));2013}20142015#ifdef COMPAT_432016int2017ofreebsd32_lseek(struct thread *td, struct ofreebsd32_lseek_args *uap)2018{20192020return (kern_lseek(td, uap->fd, uap->offset, uap->whence));2021}2022#endif20232024int2025freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)2026{2027int error;2028off_t pos;20292030error = kern_lseek(td, uap->fd, PAIR32TO64(off_t, uap->offset),2031uap->whence);2032/* Expand the quad return into two parts for eax and edx */2033pos = td->td_uretoff.tdu_off;2034td->td_retval[RETVAL_LO] = pos & 0xffffffff; /* %eax */2035td->td_retval[RETVAL_HI] = pos >> 32; /* %edx */2036return error;2037}20382039int2040freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)2041{20422043return (kern_truncate(td, uap->path, UIO_USERSPACE,2044PAIR32TO64(off_t, uap->length)));2045}20462047#ifdef COMPAT_432048int2049ofreebsd32_truncate(struct thread *td, struct ofreebsd32_truncate_args *uap)2050{2051return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));2052}2053#endif20542055int2056freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)2057{20582059return (kern_ftruncate(td, uap->fd, PAIR32TO64(off_t, uap->length)));2060}20612062#ifdef COMPAT_432063int2064ofreebsd32_ftruncate(struct thread *td, struct ofreebsd32_ftruncate_args *uap)2065{2066return (kern_ftruncate(td, uap->fd, uap->length));2067}20682069int2070ofreebsd32_getdirentries(struct thread *td,2071struct ofreebsd32_getdirentries_args *uap)2072{2073struct ogetdirentries_args ap;2074int error;2075long loff;2076int32_t loff_cut;20772078ap.fd = uap->fd;2079ap.buf = uap->buf;2080ap.count = uap->count;2081ap.basep = NULL;2082error = kern_ogetdirentries(td, &ap, &loff);2083if (error == 0) {2084loff_cut = loff;2085error = copyout(&loff_cut, uap->basep, sizeof(int32_t));2086}2087return (error);2088}2089#endif20902091#if defined(COMPAT_FREEBSD11)2092int2093freebsd11_freebsd32_getdirentries(struct thread *td,2094struct freebsd11_freebsd32_getdirentries_args *uap)2095{2096long base;2097int32_t base32;2098int error;20992100error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,2101&base, NULL);2102if (error)2103return (error);2104if (uap->basep != NULL) {2105base32 = base;2106error = copyout(&base32, uap->basep, sizeof(int32_t));2107}2108return (error);2109}2110#endif /* COMPAT_FREEBSD11 */21112112#ifdef COMPAT_FREEBSD62113/* versions with the 'int pad' argument */2114int2115freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)2116{21172118return (kern_pread(td, uap->fd, uap->buf, uap->nbyte,2119PAIR32TO64(off_t, uap->offset)));2120}21212122int2123freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)2124{21252126return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte,2127PAIR32TO64(off_t, uap->offset)));2128}21292130int2131freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)2132{2133int error;2134off_t pos;21352136error = kern_lseek(td, uap->fd, PAIR32TO64(off_t, uap->offset),2137uap->whence);2138/* Expand the quad return into two parts for eax and edx */2139pos = *(off_t *)(td->td_retval);2140td->td_retval[RETVAL_LO] = pos & 0xffffffff; /* %eax */2141td->td_retval[RETVAL_HI] = pos >> 32; /* %edx */2142return error;2143}21442145int2146freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)2147{21482149return (kern_truncate(td, uap->path, UIO_USERSPACE,2150PAIR32TO64(off_t, uap->length)));2151}21522153int2154freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)2155{21562157return (kern_ftruncate(td, uap->fd, PAIR32TO64(off_t, uap->length)));2158}2159#endif /* COMPAT_FREEBSD6 */21602161struct sf_hdtr32 {2162uint32_t headers;2163int hdr_cnt;2164uint32_t trailers;2165int trl_cnt;2166};21672168static int2169freebsd32_do_sendfile(struct thread *td,2170struct freebsd32_sendfile_args *uap, int compat)2171{2172struct sf_hdtr32 hdtr32;2173struct sf_hdtr hdtr;2174struct uio *hdr_uio, *trl_uio;2175struct file *fp;2176cap_rights_t rights;2177struct iovec32 *iov32;2178off_t offset, sbytes;2179int error;21802181offset = PAIR32TO64(off_t, uap->offset);2182if (offset < 0)2183return (EINVAL);21842185hdr_uio = trl_uio = NULL;21862187if (uap->hdtr != NULL) {2188error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));2189if (error)2190goto out;2191PTRIN_CP(hdtr32, hdtr, headers);2192CP(hdtr32, hdtr, hdr_cnt);2193PTRIN_CP(hdtr32, hdtr, trailers);2194CP(hdtr32, hdtr, trl_cnt);21952196if (hdtr.headers != NULL) {2197iov32 = PTRIN(hdtr32.headers);2198error = freebsd32_copyinuio(iov32,2199hdtr32.hdr_cnt, &hdr_uio);2200if (error)2201goto out;2202#ifdef COMPAT_FREEBSD42203/*2204* In FreeBSD < 5.0 the nbytes to send also included2205* the header. If compat is specified subtract the2206* header size from nbytes.2207*/2208if (compat) {2209if (uap->nbytes > hdr_uio->uio_resid)2210uap->nbytes -= hdr_uio->uio_resid;2211else2212uap->nbytes = 0;2213}2214#endif2215}2216if (hdtr.trailers != NULL) {2217iov32 = PTRIN(hdtr32.trailers);2218error = freebsd32_copyinuio(iov32,2219hdtr32.trl_cnt, &trl_uio);2220if (error)2221goto out;2222}2223}22242225AUDIT_ARG_FD(uap->fd);22262227if ((error = fget_read(td, uap->fd,2228cap_rights_init_one(&rights, CAP_PREAD), &fp)) != 0)2229goto out;22302231error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, offset,2232uap->nbytes, &sbytes, uap->flags, td);2233fdrop(fp, td);22342235if (uap->sbytes != NULL)2236(void)copyout(&sbytes, uap->sbytes, sizeof(off_t));22372238out:2239if (hdr_uio)2240freeuio(hdr_uio);2241if (trl_uio)2242freeuio(trl_uio);2243return (error);2244}22452246#ifdef COMPAT_FREEBSD42247int2248freebsd4_freebsd32_sendfile(struct thread *td,2249struct freebsd4_freebsd32_sendfile_args *uap)2250{2251return (freebsd32_do_sendfile(td,2252(struct freebsd32_sendfile_args *)uap, 1));2253}2254#endif22552256int2257freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)2258{22592260return (freebsd32_do_sendfile(td, uap, 0));2261}22622263static void2264copy_stat(struct stat *in, struct stat32 *out)2265{22662267#ifndef __amd64__2268/*2269* 32-bit architectures other than i386 have 64-bit time_t. This2270* results in struct timespec32 with 12 bytes for tv_sec and tv_nsec,2271* and 4 bytes of padding. Zero the padding holes in struct stat32.2272*/2273bzero(&out->st_atim, sizeof(out->st_atim));2274bzero(&out->st_mtim, sizeof(out->st_mtim));2275bzero(&out->st_ctim, sizeof(out->st_ctim));2276bzero(&out->st_birthtim, sizeof(out->st_birthtim));2277#endif2278CP(*in, *out, st_dev);2279CP(*in, *out, st_ino);2280CP(*in, *out, st_mode);2281CP(*in, *out, st_nlink);2282CP(*in, *out, st_uid);2283CP(*in, *out, st_gid);2284CP(*in, *out, st_rdev);2285TS_CP(*in, *out, st_atim);2286TS_CP(*in, *out, st_mtim);2287TS_CP(*in, *out, st_ctim);2288CP(*in, *out, st_size);2289FU64_CP(*in, *out, st_blocks);2290CP(*in, *out, st_blksize);2291CP(*in, *out, st_flags);2292FU64_CP(*in, *out, st_gen);2293FU64_CP(*in, *out, st_filerev);2294CP(*in, *out, st_bsdflags);2295TS_CP(*in, *out, st_birthtim);2296out->st_padding1 = 0;2297#ifdef __STAT32_TIME_T_EXT2298out->st_atim_ext = 0;2299out->st_mtim_ext = 0;2300out->st_ctim_ext = 0;2301out->st_btim_ext = 0;2302#endif2303bzero(out->st_spare, sizeof(out->st_spare));2304}23052306#ifdef COMPAT_432307static void2308copy_ostat(struct stat *in, struct ostat32 *out)2309{23102311bzero(out, sizeof(*out));2312CP(*in, *out, st_dev);2313CP(*in, *out, st_ino);2314CP(*in, *out, st_mode);2315CP(*in, *out, st_nlink);2316CP(*in, *out, st_uid);2317CP(*in, *out, st_gid);2318CP(*in, *out, st_rdev);2319out->st_size = MIN(in->st_size, INT32_MAX);2320TS_CP(*in, *out, st_atim);2321TS_CP(*in, *out, st_mtim);2322TS_CP(*in, *out, st_ctim);2323CP(*in, *out, st_blksize);2324CP(*in, *out, st_blocks);2325CP(*in, *out, st_flags);2326CP(*in, *out, st_gen);2327}2328#endif23292330#ifdef COMPAT_432331int2332ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)2333{2334struct stat sb;2335struct ostat32 sb32;2336int error;23372338error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);2339if (error)2340return (error);2341copy_ostat(&sb, &sb32);2342error = copyout(&sb32, uap->ub, sizeof (sb32));2343return (error);2344}2345#endif23462347int2348freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)2349{2350struct stat ub;2351struct stat32 ub32;2352int error;23532354error = kern_fstat(td, uap->fd, &ub);2355if (error)2356return (error);2357copy_stat(&ub, &ub32);2358error = copyout(&ub32, uap->sb, sizeof(ub32));2359return (error);2360}23612362#ifdef COMPAT_432363int2364ofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap)2365{2366struct stat ub;2367struct ostat32 ub32;2368int error;23692370error = kern_fstat(td, uap->fd, &ub);2371if (error)2372return (error);2373copy_ostat(&ub, &ub32);2374error = copyout(&ub32, uap->sb, sizeof(ub32));2375return (error);2376}2377#endif23782379int2380freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)2381{2382struct stat ub;2383struct stat32 ub32;2384int error;23852386error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE,2387&ub);2388if (error)2389return (error);2390copy_stat(&ub, &ub32);2391error = copyout(&ub32, uap->buf, sizeof(ub32));2392return (error);2393}23942395#ifdef COMPAT_432396int2397ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)2398{2399struct stat sb;2400struct ostat32 sb32;2401int error;24022403error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,2404UIO_USERSPACE, &sb);2405if (error)2406return (error);2407copy_ostat(&sb, &sb32);2408error = copyout(&sb32, uap->ub, sizeof (sb32));2409return (error);2410}2411#endif24122413int2414freebsd32_fhstat(struct thread *td, struct freebsd32_fhstat_args *uap)2415{2416struct stat sb;2417struct stat32 sb32;2418struct fhandle fh;2419int error;24202421error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));2422if (error != 0)2423return (error);2424error = kern_fhstat(td, fh, &sb);2425if (error != 0)2426return (error);2427copy_stat(&sb, &sb32);2428error = copyout(&sb32, uap->sb, sizeof (sb32));2429return (error);2430}24312432#if defined(COMPAT_FREEBSD11)2433extern int ino64_trunc_error;24342435static int2436freebsd11_cvtstat32(struct stat *in, struct freebsd11_stat32 *out)2437{24382439#ifndef __amd64__2440/*2441* 32-bit architectures other than i386 have 64-bit time_t. This2442* results in struct timespec32 with 12 bytes for tv_sec and tv_nsec,2443* and 4 bytes of padding. Zero the padding holes in freebsd11_stat32.2444*/2445bzero(&out->st_atim, sizeof(out->st_atim));2446bzero(&out->st_mtim, sizeof(out->st_mtim));2447bzero(&out->st_ctim, sizeof(out->st_ctim));2448bzero(&out->st_birthtim, sizeof(out->st_birthtim));2449#endif24502451CP(*in, *out, st_ino);2452if (in->st_ino != out->st_ino) {2453switch (ino64_trunc_error) {2454default:2455case 0:2456break;2457case 1:2458return (EOVERFLOW);2459case 2:2460out->st_ino = UINT32_MAX;2461break;2462}2463}2464CP(*in, *out, st_nlink);2465if (in->st_nlink != out->st_nlink) {2466switch (ino64_trunc_error) {2467default:2468case 0:2469break;2470case 1:2471return (EOVERFLOW);2472case 2:2473out->st_nlink = UINT16_MAX;2474break;2475}2476}2477out->st_dev = in->st_dev;2478if (out->st_dev != in->st_dev) {2479switch (ino64_trunc_error) {2480default:2481break;2482case 1:2483return (EOVERFLOW);2484}2485}2486CP(*in, *out, st_mode);2487CP(*in, *out, st_uid);2488CP(*in, *out, st_gid);2489out->st_rdev = in->st_rdev;2490if (out->st_rdev != in->st_rdev) {2491switch (ino64_trunc_error) {2492default:2493break;2494case 1:2495return (EOVERFLOW);2496}2497}2498TS_CP(*in, *out, st_atim);2499TS_CP(*in, *out, st_mtim);2500TS_CP(*in, *out, st_ctim);2501CP(*in, *out, st_size);2502FU64_CP(*in, *out, st_blocks);2503CP(*in, *out, st_blksize);2504CP(*in, *out, st_flags);2505CP(*in, *out, st_gen);2506TS_CP(*in, *out, st_birthtim);2507out->st_lspare = 0;2508bzero((char *)&out->st_birthtim + sizeof(out->st_birthtim),2509sizeof(*out) - offsetof(struct freebsd11_stat32,2510st_birthtim) - sizeof(out->st_birthtim));2511return (0);2512}25132514int2515freebsd11_freebsd32_stat(struct thread *td,2516struct freebsd11_freebsd32_stat_args *uap)2517{2518struct stat sb;2519struct freebsd11_stat32 sb32;2520int error;25212522error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);2523if (error != 0)2524return (error);2525error = freebsd11_cvtstat32(&sb, &sb32);2526if (error == 0)2527error = copyout(&sb32, uap->ub, sizeof (sb32));2528return (error);2529}25302531int2532freebsd11_freebsd32_fstat(struct thread *td,2533struct freebsd11_freebsd32_fstat_args *uap)2534{2535struct stat sb;2536struct freebsd11_stat32 sb32;2537int error;25382539error = kern_fstat(td, uap->fd, &sb);2540if (error != 0)2541return (error);2542error = freebsd11_cvtstat32(&sb, &sb32);2543if (error == 0)2544error = copyout(&sb32, uap->sb, sizeof (sb32));2545return (error);2546}25472548int2549freebsd11_freebsd32_fstatat(struct thread *td,2550struct freebsd11_freebsd32_fstatat_args *uap)2551{2552struct stat sb;2553struct freebsd11_stat32 sb32;2554int error;25552556error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE,2557&sb);2558if (error != 0)2559return (error);2560error = freebsd11_cvtstat32(&sb, &sb32);2561if (error == 0)2562error = copyout(&sb32, uap->buf, sizeof (sb32));2563return (error);2564}25652566int2567freebsd11_freebsd32_lstat(struct thread *td,2568struct freebsd11_freebsd32_lstat_args *uap)2569{2570struct stat sb;2571struct freebsd11_stat32 sb32;2572int error;25732574error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,2575UIO_USERSPACE, &sb);2576if (error != 0)2577return (error);2578error = freebsd11_cvtstat32(&sb, &sb32);2579if (error == 0)2580error = copyout(&sb32, uap->ub, sizeof (sb32));2581return (error);2582}25832584int2585freebsd11_freebsd32_fhstat(struct thread *td,2586struct freebsd11_freebsd32_fhstat_args *uap)2587{2588struct stat sb;2589struct freebsd11_stat32 sb32;2590struct fhandle fh;2591int error;25922593error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));2594if (error != 0)2595return (error);2596error = kern_fhstat(td, fh, &sb);2597if (error != 0)2598return (error);2599error = freebsd11_cvtstat32(&sb, &sb32);2600if (error == 0)2601error = copyout(&sb32, uap->sb, sizeof (sb32));2602return (error);2603}26042605static int2606freebsd11_cvtnstat32(struct stat *sb, struct nstat32 *nsb32)2607{2608struct nstat nsb;2609int error;26102611error = freebsd11_cvtnstat(sb, &nsb);2612if (error != 0)2613return (error);26142615bzero(nsb32, sizeof(*nsb32));2616CP(nsb, *nsb32, st_dev);2617CP(nsb, *nsb32, st_ino);2618CP(nsb, *nsb32, st_mode);2619CP(nsb, *nsb32, st_nlink);2620CP(nsb, *nsb32, st_uid);2621CP(nsb, *nsb32, st_gid);2622CP(nsb, *nsb32, st_rdev);2623CP(nsb, *nsb32, st_atim.tv_sec);2624CP(nsb, *nsb32, st_atim.tv_nsec);2625CP(nsb, *nsb32, st_mtim.tv_sec);2626CP(nsb, *nsb32, st_mtim.tv_nsec);2627CP(nsb, *nsb32, st_ctim.tv_sec);2628CP(nsb, *nsb32, st_ctim.tv_nsec);2629CP(nsb, *nsb32, st_size);2630CP(nsb, *nsb32, st_blocks);2631CP(nsb, *nsb32, st_blksize);2632CP(nsb, *nsb32, st_flags);2633CP(nsb, *nsb32, st_gen);2634CP(nsb, *nsb32, st_birthtim.tv_sec);2635CP(nsb, *nsb32, st_birthtim.tv_nsec);2636return (0);2637}26382639int2640freebsd11_freebsd32_nstat(struct thread *td,2641struct freebsd11_freebsd32_nstat_args *uap)2642{2643struct stat sb;2644struct nstat32 nsb;2645int error;26462647error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);2648if (error != 0)2649return (error);2650error = freebsd11_cvtnstat32(&sb, &nsb);2651if (error != 0)2652error = copyout(&nsb, uap->ub, sizeof (nsb));2653return (error);2654}26552656int2657freebsd11_freebsd32_nlstat(struct thread *td,2658struct freebsd11_freebsd32_nlstat_args *uap)2659{2660struct stat sb;2661struct nstat32 nsb;2662int error;26632664error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,2665UIO_USERSPACE, &sb);2666if (error != 0)2667return (error);2668error = freebsd11_cvtnstat32(&sb, &nsb);2669if (error == 0)2670error = copyout(&nsb, uap->ub, sizeof (nsb));2671return (error);2672}26732674int2675freebsd11_freebsd32_nfstat(struct thread *td,2676struct freebsd11_freebsd32_nfstat_args *uap)2677{2678struct nstat32 nub;2679struct stat ub;2680int error;26812682error = kern_fstat(td, uap->fd, &ub);2683if (error != 0)2684return (error);2685error = freebsd11_cvtnstat32(&ub, &nub);2686if (error == 0)2687error = copyout(&nub, uap->sb, sizeof(nub));2688return (error);2689}2690#endif26912692int2693freebsd32___sysctl(struct thread *td, struct freebsd32___sysctl_args *uap)2694{2695int error, name[CTL_MAXNAME];2696size_t j, oldlen;2697uint32_t tmp;26982699if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)2700return (EINVAL);2701error = copyin(uap->name, name, uap->namelen * sizeof(int));2702if (error)2703return (error);2704if (uap->oldlenp) {2705error = fueword32(uap->oldlenp, &tmp);2706oldlen = tmp;2707} else {2708oldlen = 0;2709}2710if (error != 0)2711return (EFAULT);2712error = userland_sysctl(td, name, uap->namelen,2713uap->old, &oldlen, 1,2714uap->new, uap->newlen, &j, SCTL_MASK32);2715if (error)2716return (error);2717if (uap->oldlenp != NULL && suword32(uap->oldlenp, j) != 0)2718error = EFAULT;2719return (error);2720}27212722int2723freebsd32___sysctlbyname(struct thread *td,2724struct freebsd32___sysctlbyname_args *uap)2725{2726size_t oldlen, rv;2727int error;2728uint32_t tmp;27292730if (uap->oldlenp != NULL) {2731error = fueword32(uap->oldlenp, &tmp);2732oldlen = tmp;2733} else {2734error = oldlen = 0;2735}2736if (error != 0)2737return (EFAULT);2738error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,2739&oldlen, uap->new, uap->newlen, &rv, SCTL_MASK32, 1);2740if (error != 0)2741return (error);2742if (uap->oldlenp != NULL && suword32(uap->oldlenp, rv) != 0)2743error = EFAULT;2744return (error);2745}27462747int2748freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)2749{2750uint32_t version;2751int error;2752struct jail j;27532754error = copyin(uap->jail, &version, sizeof(uint32_t));2755if (error)2756return (error);27572758switch (version) {2759case 0:2760{2761/* FreeBSD single IPv4 jails. */2762struct jail32_v0 j32_v0;27632764bzero(&j, sizeof(struct jail));2765error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));2766if (error)2767return (error);2768CP(j32_v0, j, version);2769PTRIN_CP(j32_v0, j, path);2770PTRIN_CP(j32_v0, j, hostname);2771j.ip4s = htonl(j32_v0.ip_number); /* jail_v0 is host order */2772break;2773}27742775case 1:2776/*2777* Version 1 was used by multi-IPv4 jail implementations2778* that never made it into the official kernel.2779*/2780return (EINVAL);27812782case 2: /* JAIL_API_VERSION */2783{2784/* FreeBSD multi-IPv4/IPv6,noIP jails. */2785struct jail32 j32;27862787error = copyin(uap->jail, &j32, sizeof(struct jail32));2788if (error)2789return (error);2790CP(j32, j, version);2791PTRIN_CP(j32, j, path);2792PTRIN_CP(j32, j, hostname);2793PTRIN_CP(j32, j, jailname);2794CP(j32, j, ip4s);2795CP(j32, j, ip6s);2796PTRIN_CP(j32, j, ip4);2797PTRIN_CP(j32, j, ip6);2798break;2799}28002801default:2802/* Sci-Fi jails are not supported, sorry. */2803return (EINVAL);2804}2805return (kern_jail(td, &j));2806}28072808int2809freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)2810{2811struct uio *auio;2812int error;28132814/* Check that we have an even number of iovecs. */2815if (uap->iovcnt & 1)2816return (EINVAL);28172818error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);2819if (error)2820return (error);2821error = kern_jail_set(td, auio, uap->flags);2822freeuio(auio);2823return (error);2824}28252826int2827freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)2828{2829struct iovec32 iov32;2830struct uio *auio;2831int error, i;28322833/* Check that we have an even number of iovecs. */2834if (uap->iovcnt & 1)2835return (EINVAL);28362837error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);2838if (error)2839return (error);2840error = kern_jail_get(td, auio, uap->flags);2841if (error == 0)2842for (i = 0; i < uap->iovcnt; i++) {2843PTROUT_CP(auio->uio_iov[i], iov32, iov_base);2844CP(auio->uio_iov[i], iov32, iov_len);2845error = copyout(&iov32, uap->iovp + i, sizeof(iov32));2846if (error != 0)2847break;2848}2849freeuio(auio);2850return (error);2851}28522853int2854freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)2855{2856struct sigaction32 s32;2857struct sigaction sa, osa, *sap;2858int error;28592860if (uap->act) {2861error = copyin(uap->act, &s32, sizeof(s32));2862if (error)2863return (error);2864sa.sa_handler = PTRIN(s32.sa_u);2865CP(s32, sa, sa_flags);2866CP(s32, sa, sa_mask);2867sap = &sa;2868} else2869sap = NULL;2870error = kern_sigaction(td, uap->sig, sap, &osa, 0);2871if (error == 0 && uap->oact != NULL) {2872s32.sa_u = PTROUT(osa.sa_handler);2873CP(osa, s32, sa_flags);2874CP(osa, s32, sa_mask);2875error = copyout(&s32, uap->oact, sizeof(s32));2876}2877return (error);2878}28792880#ifdef COMPAT_FREEBSD42881int2882freebsd4_freebsd32_sigaction(struct thread *td,2883struct freebsd4_freebsd32_sigaction_args *uap)2884{2885struct sigaction32 s32;2886struct sigaction sa, osa, *sap;2887int error;28882889if (uap->act) {2890error = copyin(uap->act, &s32, sizeof(s32));2891if (error)2892return (error);2893sa.sa_handler = PTRIN(s32.sa_u);2894CP(s32, sa, sa_flags);2895CP(s32, sa, sa_mask);2896sap = &sa;2897} else2898sap = NULL;2899error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);2900if (error == 0 && uap->oact != NULL) {2901s32.sa_u = PTROUT(osa.sa_handler);2902CP(osa, s32, sa_flags);2903CP(osa, s32, sa_mask);2904error = copyout(&s32, uap->oact, sizeof(s32));2905}2906return (error);2907}2908#endif29092910#ifdef COMPAT_432911struct osigaction32 {2912uint32_t sa_u;2913osigset_t sa_mask;2914int sa_flags;2915};29162917#define ONSIG 3229182919int2920ofreebsd32_sigaction(struct thread *td,2921struct ofreebsd32_sigaction_args *uap)2922{2923struct osigaction32 s32;2924struct sigaction sa, osa, *sap;2925int error;29262927if (uap->signum <= 0 || uap->signum >= ONSIG)2928return (EINVAL);29292930if (uap->nsa) {2931error = copyin(uap->nsa, &s32, sizeof(s32));2932if (error)2933return (error);2934sa.sa_handler = PTRIN(s32.sa_u);2935CP(s32, sa, sa_flags);2936OSIG2SIG(s32.sa_mask, sa.sa_mask);2937sap = &sa;2938} else2939sap = NULL;2940error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);2941if (error == 0 && uap->osa != NULL) {2942s32.sa_u = PTROUT(osa.sa_handler);2943CP(osa, s32, sa_flags);2944SIG2OSIG(osa.sa_mask, s32.sa_mask);2945error = copyout(&s32, uap->osa, sizeof(s32));2946}2947return (error);2948}29492950struct sigvec32 {2951uint32_t sv_handler;2952int sv_mask;2953int sv_flags;2954};29552956int2957ofreebsd32_sigvec(struct thread *td,2958struct ofreebsd32_sigvec_args *uap)2959{2960struct sigvec32 vec;2961struct sigaction sa, osa, *sap;2962int error;29632964if (uap->signum <= 0 || uap->signum >= ONSIG)2965return (EINVAL);29662967if (uap->nsv) {2968error = copyin(uap->nsv, &vec, sizeof(vec));2969if (error)2970return (error);2971sa.sa_handler = PTRIN(vec.sv_handler);2972OSIG2SIG(vec.sv_mask, sa.sa_mask);2973sa.sa_flags = vec.sv_flags;2974sa.sa_flags ^= SA_RESTART;2975sap = &sa;2976} else2977sap = NULL;2978error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);2979if (error == 0 && uap->osv != NULL) {2980vec.sv_handler = PTROUT(osa.sa_handler);2981SIG2OSIG(osa.sa_mask, vec.sv_mask);2982vec.sv_flags = osa.sa_flags;2983vec.sv_flags &= ~SA_NOCLDWAIT;2984vec.sv_flags ^= SA_RESTART;2985error = copyout(&vec, uap->osv, sizeof(vec));2986}2987return (error);2988}29892990struct sigstack32 {2991uint32_t ss_sp;2992int ss_onstack;2993};29942995int2996ofreebsd32_sigstack(struct thread *td,2997struct ofreebsd32_sigstack_args *uap)2998{2999struct sigstack32 s32;3000struct sigstack nss, oss;3001int error = 0, unss;30023003if (uap->nss != NULL) {3004error = copyin(uap->nss, &s32, sizeof(s32));3005if (error)3006return (error);3007nss.ss_sp = PTRIN(s32.ss_sp);3008CP(s32, nss, ss_onstack);3009unss = 1;3010} else {3011unss = 0;3012}3013oss.ss_sp = td->td_sigstk.ss_sp;3014oss.ss_onstack = sigonstack(cpu_getstack(td));3015if (unss) {3016td->td_sigstk.ss_sp = nss.ss_sp;3017td->td_sigstk.ss_size = 0;3018td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);3019td->td_pflags |= TDP_ALTSTACK;3020}3021if (uap->oss != NULL) {3022s32.ss_sp = PTROUT(oss.ss_sp);3023CP(oss, s32, ss_onstack);3024error = copyout(&s32, uap->oss, sizeof(s32));3025}3026return (error);3027}3028#endif30293030int3031freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)3032{30333034return (freebsd32_user_clock_nanosleep(td, CLOCK_REALTIME,3035TIMER_RELTIME, uap->rqtp, uap->rmtp));3036}30373038int3039freebsd32_clock_nanosleep(struct thread *td,3040struct freebsd32_clock_nanosleep_args *uap)3041{3042int error;30433044error = freebsd32_user_clock_nanosleep(td, uap->clock_id, uap->flags,3045uap->rqtp, uap->rmtp);3046return (kern_posix_error(td, error));3047}30483049static int3050freebsd32_user_clock_nanosleep(struct thread *td, clockid_t clock_id,3051int flags, const struct timespec32 *ua_rqtp, struct timespec32 *ua_rmtp)3052{3053struct timespec32 rmt32, rqt32;3054struct timespec rmt, rqt;3055int error, error2;30563057error = copyin(ua_rqtp, &rqt32, sizeof(rqt32));3058if (error)3059return (error);30603061CP(rqt32, rqt, tv_sec);3062CP(rqt32, rqt, tv_nsec);30633064error = kern_clock_nanosleep(td, clock_id, flags, &rqt, &rmt);3065if (error == EINTR && ua_rmtp != NULL && (flags & TIMER_ABSTIME) == 0) {3066CP(rmt, rmt32, tv_sec);3067CP(rmt, rmt32, tv_nsec);30683069error2 = copyout(&rmt32, ua_rmtp, sizeof(rmt32));3070if (error2 != 0)3071error = error2;3072}3073return (error);3074}30753076int3077freebsd32_clock_gettime(struct thread *td,3078struct freebsd32_clock_gettime_args *uap)3079{3080struct timespec ats;3081struct timespec32 ats32;3082int error;30833084error = kern_clock_gettime(td, uap->clock_id, &ats);3085if (error == 0) {3086CP(ats, ats32, tv_sec);3087CP(ats, ats32, tv_nsec);3088error = copyout(&ats32, uap->tp, sizeof(ats32));3089}3090return (error);3091}30923093int3094freebsd32_clock_settime(struct thread *td,3095struct freebsd32_clock_settime_args *uap)3096{3097struct timespec ats;3098struct timespec32 ats32;3099int error;31003101error = copyin(uap->tp, &ats32, sizeof(ats32));3102if (error)3103return (error);3104CP(ats32, ats, tv_sec);3105CP(ats32, ats, tv_nsec);31063107return (kern_clock_settime(td, uap->clock_id, &ats));3108}31093110int3111freebsd32_clock_getres(struct thread *td,3112struct freebsd32_clock_getres_args *uap)3113{3114struct timespec ts;3115struct timespec32 ts32;3116int error;31173118if (uap->tp == NULL)3119return (0);3120error = kern_clock_getres(td, uap->clock_id, &ts);3121if (error == 0) {3122CP(ts, ts32, tv_sec);3123CP(ts, ts32, tv_nsec);3124error = copyout(&ts32, uap->tp, sizeof(ts32));3125}3126return (error);3127}31283129int freebsd32_ktimer_create(struct thread *td,3130struct freebsd32_ktimer_create_args *uap)3131{3132struct sigevent32 ev32;3133struct sigevent ev, *evp;3134int error, id;31353136if (uap->evp == NULL) {3137evp = NULL;3138} else {3139evp = &ev;3140error = copyin(uap->evp, &ev32, sizeof(ev32));3141if (error != 0)3142return (error);3143error = convert_sigevent32(&ev32, &ev);3144if (error != 0)3145return (error);3146}3147error = kern_ktimer_create(td, uap->clock_id, evp, &id, -1);3148if (error == 0) {3149error = copyout(&id, uap->timerid, sizeof(int));3150if (error != 0)3151kern_ktimer_delete(td, id);3152}3153return (error);3154}31553156int3157freebsd32_ktimer_settime(struct thread *td,3158struct freebsd32_ktimer_settime_args *uap)3159{3160struct itimerspec32 val32, oval32;3161struct itimerspec val, oval, *ovalp;3162int error;31633164error = copyin(uap->value, &val32, sizeof(val32));3165if (error != 0)3166return (error);3167ITS_CP(val32, val);3168ovalp = uap->ovalue != NULL ? &oval : NULL;3169error = kern_ktimer_settime(td, uap->timerid, uap->flags, &val, ovalp);3170if (error == 0 && uap->ovalue != NULL) {3171ITS_CP(oval, oval32);3172error = copyout(&oval32, uap->ovalue, sizeof(oval32));3173}3174return (error);3175}31763177int3178freebsd32_ktimer_gettime(struct thread *td,3179struct freebsd32_ktimer_gettime_args *uap)3180{3181struct itimerspec32 val32;3182struct itimerspec val;3183int error;31843185error = kern_ktimer_gettime(td, uap->timerid, &val);3186if (error == 0) {3187ITS_CP(val, val32);3188error = copyout(&val32, uap->value, sizeof(val32));3189}3190return (error);3191}31923193int3194freebsd32_timerfd_gettime(struct thread *td,3195struct freebsd32_timerfd_gettime_args *uap)3196{3197struct itimerspec curr_value;3198struct itimerspec32 curr_value32;3199int error;32003201error = kern_timerfd_gettime(td, uap->fd, &curr_value);3202if (error == 0) {3203CP(curr_value, curr_value32, it_value.tv_sec);3204CP(curr_value, curr_value32, it_value.tv_nsec);3205CP(curr_value, curr_value32, it_interval.tv_sec);3206CP(curr_value, curr_value32, it_interval.tv_nsec);3207error = copyout(&curr_value32, uap->curr_value,3208sizeof(curr_value32));3209}32103211return (error);3212}32133214int3215freebsd32_timerfd_settime(struct thread *td,3216struct freebsd32_timerfd_settime_args *uap)3217{3218struct itimerspec new_value, old_value;3219struct itimerspec32 new_value32, old_value32;3220int error;32213222error = copyin(uap->new_value, &new_value32, sizeof(new_value32));3223if (error != 0)3224return (error);3225CP(new_value32, new_value, it_value.tv_sec);3226CP(new_value32, new_value, it_value.tv_nsec);3227CP(new_value32, new_value, it_interval.tv_sec);3228CP(new_value32, new_value, it_interval.tv_nsec);3229if (uap->old_value == NULL) {3230error = kern_timerfd_settime(td, uap->fd, uap->flags,3231&new_value, NULL);3232} else {3233error = kern_timerfd_settime(td, uap->fd, uap->flags,3234&new_value, &old_value);3235if (error == 0) {3236CP(old_value, old_value32, it_value.tv_sec);3237CP(old_value, old_value32, it_value.tv_nsec);3238CP(old_value, old_value32, it_interval.tv_sec);3239CP(old_value, old_value32, it_interval.tv_nsec);3240error = copyout(&old_value32, uap->old_value,3241sizeof(old_value32));3242}3243}3244return (error);3245}32463247int3248freebsd32_clock_getcpuclockid2(struct thread *td,3249struct freebsd32_clock_getcpuclockid2_args *uap)3250{3251clockid_t clk_id;3252int error;32533254error = kern_clock_getcpuclockid2(td, PAIR32TO64(id_t, uap->id),3255uap->which, &clk_id);3256if (error == 0)3257error = copyout(&clk_id, uap->clock_id, sizeof(clockid_t));3258return (error);3259}32603261int3262freebsd32_thr_new(struct thread *td,3263struct freebsd32_thr_new_args *uap)3264{3265struct thr_param32 param32;3266struct thr_param param;3267int error;32683269if (uap->param_size < 0 ||3270uap->param_size > sizeof(struct thr_param32))3271return (EINVAL);3272bzero(¶m, sizeof(struct thr_param));3273bzero(¶m32, sizeof(struct thr_param32));3274error = copyin(uap->param, ¶m32, uap->param_size);3275if (error != 0)3276return (error);3277param.start_func = PTRIN(param32.start_func);3278param.arg = PTRIN(param32.arg);3279param.stack_base = PTRIN(param32.stack_base);3280param.stack_size = param32.stack_size;3281param.tls_base = PTRIN(param32.tls_base);3282param.tls_size = param32.tls_size;3283param.child_tid = PTRIN(param32.child_tid);3284param.parent_tid = PTRIN(param32.parent_tid);3285param.flags = param32.flags;3286param.rtp = PTRIN(param32.rtp);3287param.spare[0] = PTRIN(param32.spare[0]);3288param.spare[1] = PTRIN(param32.spare[1]);3289param.spare[2] = PTRIN(param32.spare[2]);32903291return (kern_thr_new(td, ¶m));3292}32933294int3295freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)3296{3297struct timespec32 ts32;3298struct timespec ts, *tsp;3299int error;33003301error = 0;3302tsp = NULL;3303if (uap->timeout != NULL) {3304error = copyin((const void *)uap->timeout, (void *)&ts32,3305sizeof(struct timespec32));3306if (error != 0)3307return (error);3308ts.tv_sec = ts32.tv_sec;3309ts.tv_nsec = ts32.tv_nsec;3310tsp = &ts;3311}3312return (kern_thr_suspend(td, tsp));3313}33143315void3316siginfo_to_siginfo32(const siginfo_t *src, struct __siginfo32 *dst)3317{3318bzero(dst, sizeof(*dst));3319dst->si_signo = src->si_signo;3320dst->si_errno = src->si_errno;3321dst->si_code = src->si_code;3322dst->si_pid = src->si_pid;3323dst->si_uid = src->si_uid;3324dst->si_status = src->si_status;3325dst->si_addr = (uintptr_t)src->si_addr;3326dst->si_value.sival_int = src->si_value.sival_int;3327dst->si_timerid = src->si_timerid;3328dst->si_overrun = src->si_overrun;3329}33303331#ifndef _FREEBSD32_SYSPROTO_H_3332struct freebsd32_sigqueue_args {3333pid_t pid;3334int signum;3335/* union sigval32 */ int value;3336};3337#endif3338int3339freebsd32_sigqueue(struct thread *td, struct freebsd32_sigqueue_args *uap)3340{3341union sigval sv;33423343/*3344* On 32-bit ABIs, sival_int and sival_ptr are the same.3345* On 64-bit little-endian ABIs, the low bits are the same.3346* In 64-bit big-endian ABIs, sival_int overlaps with3347* sival_ptr's HIGH bits. We choose to support sival_int3348* rather than sival_ptr in this case as it seems to be3349* more common.3350*/3351bzero(&sv, sizeof(sv));3352sv.sival_int = (uint32_t)(uint64_t)uap->value;33533354return (kern_sigqueue(td, uap->pid, uap->signum, &sv));3355}33563357int3358freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)3359{3360struct timespec32 ts32;3361struct timespec ts;3362struct timespec *timeout;3363sigset_t set;3364ksiginfo_t ksi;3365struct __siginfo32 si32;3366int error;33673368if (uap->timeout) {3369error = copyin(uap->timeout, &ts32, sizeof(ts32));3370if (error)3371return (error);3372ts.tv_sec = ts32.tv_sec;3373ts.tv_nsec = ts32.tv_nsec;3374timeout = &ts;3375} else3376timeout = NULL;33773378error = copyin(uap->set, &set, sizeof(set));3379if (error)3380return (error);33813382error = kern_sigtimedwait(td, set, &ksi, timeout);3383if (error)3384return (error);33853386if (uap->info) {3387siginfo_to_siginfo32(&ksi.ksi_info, &si32);3388error = copyout(&si32, uap->info, sizeof(struct __siginfo32));3389}33903391if (error == 0)3392td->td_retval[0] = ksi.ksi_signo;3393return (error);3394}33953396/*3397* MPSAFE3398*/3399int3400freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)3401{3402ksiginfo_t ksi;3403struct __siginfo32 si32;3404sigset_t set;3405int error;34063407error = copyin(uap->set, &set, sizeof(set));3408if (error)3409return (error);34103411error = kern_sigtimedwait(td, set, &ksi, NULL);3412if (error)3413return (error);34143415if (uap->info) {3416siginfo_to_siginfo32(&ksi.ksi_info, &si32);3417error = copyout(&si32, uap->info, sizeof(struct __siginfo32));3418}3419if (error == 0)3420td->td_retval[0] = ksi.ksi_signo;3421return (error);3422}34233424int3425freebsd32_cpuset_setid(struct thread *td,3426struct freebsd32_cpuset_setid_args *uap)3427{34283429return (kern_cpuset_setid(td, uap->which,3430PAIR32TO64(id_t, uap->id), uap->setid));3431}34323433int3434freebsd32_cpuset_getid(struct thread *td,3435struct freebsd32_cpuset_getid_args *uap)3436{34373438return (kern_cpuset_getid(td, uap->level, uap->which,3439PAIR32TO64(id_t, uap->id), uap->setid));3440}34413442static int3443copyin32_set(const void *u, void *k, size_t size)3444{3445#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__3446int rv;3447struct bitset *kb = k;3448int *p;34493450rv = copyin(u, k, size);3451if (rv != 0)3452return (rv);34533454p = (int *)kb->__bits;3455/* Loop through swapping words.3456* `size' is in bytes, we need bits. */3457for (int i = 0; i < __bitset_words(size * 8); i++) {3458int tmp = p[0];3459p[0] = p[1];3460p[1] = tmp;3461p += 2;3462}3463return (0);3464#else3465return (copyin(u, k, size));3466#endif3467}34683469static int3470copyout32_set(const void *k, void *u, size_t size)3471{3472#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__3473const struct bitset *kb = k;3474struct bitset *ub = u;3475const int *kp = (const int *)kb->__bits;3476int *up = (int *)ub->__bits;3477int rv;34783479for (int i = 0; i < __bitset_words(CPU_SETSIZE); i++) {3480/* `size' is in bytes, we need bits. */3481for (int i = 0; i < __bitset_words(size * 8); i++) {3482rv = suword32(up, kp[1]);3483if (rv == 0)3484rv = suword32(up + 1, kp[0]);3485if (rv != 0)3486return (EFAULT);3487}3488}3489return (0);3490#else3491return (copyout(k, u, size));3492#endif3493}34943495static const struct cpuset_copy_cb cpuset_copy32_cb = {3496.cpuset_copyin = copyin32_set,3497.cpuset_copyout = copyout32_set3498};34993500int3501freebsd32_cpuset_getaffinity(struct thread *td,3502struct freebsd32_cpuset_getaffinity_args *uap)3503{35043505return (user_cpuset_getaffinity(td, uap->level, uap->which,3506PAIR32TO64(id_t,uap->id), uap->cpusetsize, uap->mask,3507&cpuset_copy32_cb));3508}35093510int3511freebsd32_cpuset_setaffinity(struct thread *td,3512struct freebsd32_cpuset_setaffinity_args *uap)3513{35143515return (user_cpuset_setaffinity(td, uap->level, uap->which,3516PAIR32TO64(id_t,uap->id), uap->cpusetsize, uap->mask,3517&cpuset_copy32_cb));3518}35193520int3521freebsd32_cpuset_getdomain(struct thread *td,3522struct freebsd32_cpuset_getdomain_args *uap)3523{35243525return (kern_cpuset_getdomain(td, uap->level, uap->which,3526PAIR32TO64(id_t,uap->id), uap->domainsetsize, uap->mask, uap->policy,3527&cpuset_copy32_cb));3528}35293530int3531freebsd32_cpuset_setdomain(struct thread *td,3532struct freebsd32_cpuset_setdomain_args *uap)3533{35343535return (kern_cpuset_setdomain(td, uap->level, uap->which,3536PAIR32TO64(id_t,uap->id), uap->domainsetsize, uap->mask, uap->policy,3537&cpuset_copy32_cb));3538}35393540int3541freebsd32_nmount(struct thread *td,3542struct freebsd32_nmount_args /* {3543struct iovec *iovp;3544unsigned int iovcnt;3545int flags;3546} */ *uap)3547{3548struct uio *auio;3549uint64_t flags;3550int error;35513552/*3553* Mount flags are now 64-bits. On 32-bit archtectures only3554* 32-bits are passed in, but from here on everything handles3555* 64-bit flags correctly.3556*/3557flags = uap->flags;35583559AUDIT_ARG_FFLAGS(flags);35603561/*3562* Filter out MNT_ROOTFS. We do not want clients of nmount() in3563* userspace to set this flag, but we must filter it out if we want3564* MNT_UPDATE on the root file system to work.3565* MNT_ROOTFS should only be set by the kernel when mounting its3566* root file system.3567*/3568flags &= ~MNT_ROOTFS;35693570/*3571* check that we have an even number of iovec's3572* and that we have at least two options.3573*/3574if ((uap->iovcnt & 1) || (uap->iovcnt < 4))3575return (EINVAL);35763577error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);3578if (error)3579return (error);3580error = vfs_donmount(td, flags, auio);35813582freeuio(auio);3583return error;3584}35853586#if 03587int3588freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)3589{3590struct yyy32 *p32, s32;3591struct yyy *p = NULL, s;3592struct xxx_arg ap;3593int error;35943595if (uap->zzz) {3596error = copyin(uap->zzz, &s32, sizeof(s32));3597if (error)3598return (error);3599/* translate in */3600p = &s;3601}3602error = kern_xxx(td, p);3603if (error)3604return (error);3605if (uap->zzz) {3606/* translate out */3607error = copyout(&s32, p32, sizeof(s32));3608}3609return (error);3610}3611#endif36123613int3614syscall32_module_handler(struct module *mod, int what, void *arg)3615{36163617return (kern_syscall_module_handler(freebsd32_sysent, mod, what, arg));3618}36193620int3621syscall32_helper_register(struct syscall_helper_data *sd, int flags)3622{36233624return (kern_syscall_helper_register(freebsd32_sysent, sd, flags));3625}36263627int3628syscall32_helper_unregister(struct syscall_helper_data *sd)3629{36303631return (kern_syscall_helper_unregister(freebsd32_sysent, sd));3632}36333634int3635freebsd32_copyout_strings(struct image_params *imgp, uintptr_t *stack_base)3636{3637struct sysentvec *sysent;3638int argc, envc, i;3639uint32_t *vectp;3640char *stringp;3641uintptr_t destp, ustringp;3642struct freebsd32_ps_strings *arginfo;3643char canary[sizeof(long) * 8];3644int32_t pagesizes32[MAXPAGESIZES];3645size_t execpath_len;3646int error, szsigcode;36473648sysent = imgp->sysent;36493650arginfo = (struct freebsd32_ps_strings *)PROC_PS_STRINGS(imgp->proc);3651imgp->ps_strings = arginfo;3652destp = (uintptr_t)arginfo;36533654/*3655* Install sigcode.3656*/3657if (!PROC_HAS_SHP(imgp->proc)) {3658szsigcode = *sysent->sv_szsigcode;3659destp -= szsigcode;3660destp = rounddown2(destp, sizeof(uint32_t));3661error = copyout(sysent->sv_sigcode, (void *)destp,3662szsigcode);3663if (error != 0)3664return (error);3665}36663667/*3668* Copy the image path for the rtld.3669*/3670if (imgp->execpath != NULL && imgp->auxargs != NULL) {3671execpath_len = strlen(imgp->execpath) + 1;3672destp -= execpath_len;3673imgp->execpathp = (void *)destp;3674error = copyout(imgp->execpath, imgp->execpathp, execpath_len);3675if (error != 0)3676return (error);3677}36783679/*3680* Prepare the canary for SSP.3681*/3682arc4rand(canary, sizeof(canary), 0);3683destp -= sizeof(canary);3684imgp->canary = (void *)destp;3685error = copyout(canary, imgp->canary, sizeof(canary));3686if (error != 0)3687return (error);3688imgp->canarylen = sizeof(canary);36893690/*3691* Prepare the pagesizes array.3692*/3693for (i = 0; i < MAXPAGESIZES; i++)3694pagesizes32[i] = (uint32_t)pagesizes[i];3695destp -= sizeof(pagesizes32);3696destp = rounddown2(destp, sizeof(uint32_t));3697imgp->pagesizes = (void *)destp;3698error = copyout(pagesizes32, imgp->pagesizes, sizeof(pagesizes32));3699if (error != 0)3700return (error);3701imgp->pagesizeslen = sizeof(pagesizes32);37023703/*3704* Allocate room for the argument and environment strings.3705*/3706destp -= ARG_MAX - imgp->args->stringspace;3707destp = rounddown2(destp, sizeof(uint32_t));3708ustringp = destp;37093710if (imgp->auxargs) {3711/*3712* Allocate room on the stack for the ELF auxargs3713* array. It has up to AT_COUNT entries.3714*/3715destp -= AT_COUNT * sizeof(Elf32_Auxinfo);3716destp = rounddown2(destp, sizeof(uint32_t));3717}37183719vectp = (uint32_t *)destp;37203721/*3722* Allocate room for the argv[] and env vectors including the3723* terminating NULL pointers.3724*/3725vectp -= imgp->args->argc + 1 + imgp->args->envc + 1;37263727/*3728* vectp also becomes our initial stack base3729*/3730*stack_base = (uintptr_t)vectp;37313732stringp = imgp->args->begin_argv;3733argc = imgp->args->argc;3734envc = imgp->args->envc;3735/*3736* Copy out strings - arguments and environment.3737*/3738error = copyout(stringp, (void *)ustringp,3739ARG_MAX - imgp->args->stringspace);3740if (error != 0)3741return (error);37423743/*3744* Fill in "ps_strings" struct for ps, w, etc.3745*/3746imgp->argv = vectp;3747if (suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp) != 0 ||3748suword32(&arginfo->ps_nargvstr, argc) != 0)3749return (EFAULT);37503751/*3752* Fill in argument portion of vector table.3753*/3754for (; argc > 0; --argc) {3755if (suword32(vectp++, ustringp) != 0)3756return (EFAULT);3757while (*stringp++ != 0)3758ustringp++;3759ustringp++;3760}37613762/* a null vector table pointer separates the argp's from the envp's */3763if (suword32(vectp++, 0) != 0)3764return (EFAULT);37653766imgp->envv = vectp;3767if (suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp) != 0 ||3768suword32(&arginfo->ps_nenvstr, envc) != 0)3769return (EFAULT);37703771/*3772* Fill in environment portion of vector table.3773*/3774for (; envc > 0; --envc) {3775if (suword32(vectp++, ustringp) != 0)3776return (EFAULT);3777while (*stringp++ != 0)3778ustringp++;3779ustringp++;3780}37813782/* end of vector table is a null pointer */3783if (suword32(vectp, 0) != 0)3784return (EFAULT);37853786if (imgp->auxargs) {3787vectp++;3788error = imgp->sysent->sv_copyout_auxargs(imgp,3789(uintptr_t)vectp);3790if (error != 0)3791return (error);3792}37933794return (0);3795}37963797int3798freebsd32_kldstat(struct thread *td, struct freebsd32_kldstat_args *uap)3799{3800struct kld_file_stat *stat;3801struct kld_file_stat32 *stat32;3802int error, version;38033804if ((error = copyin(&uap->stat->version, &version, sizeof(version)))3805!= 0)3806return (error);3807if (version != sizeof(struct kld_file_stat_1_32) &&3808version != sizeof(struct kld_file_stat32))3809return (EINVAL);38103811stat = malloc(sizeof(*stat), M_TEMP, M_WAITOK | M_ZERO);3812stat32 = malloc(sizeof(*stat32), M_TEMP, M_WAITOK | M_ZERO);3813error = kern_kldstat(td, uap->fileid, stat);3814if (error == 0) {3815bcopy(&stat->name[0], &stat32->name[0], sizeof(stat->name));3816CP(*stat, *stat32, refs);3817CP(*stat, *stat32, id);3818PTROUT_CP(*stat, *stat32, address);3819CP(*stat, *stat32, size);3820bcopy(&stat->pathname[0], &stat32->pathname[0],3821sizeof(stat->pathname));3822stat32->version = version;3823error = copyout(stat32, uap->stat, version);3824}3825free(stat, M_TEMP);3826free(stat32, M_TEMP);3827return (error);3828}38293830int3831freebsd32_posix_fallocate(struct thread *td,3832struct freebsd32_posix_fallocate_args *uap)3833{3834int error;38353836error = kern_posix_fallocate(td, uap->fd,3837PAIR32TO64(off_t, uap->offset), PAIR32TO64(off_t, uap->len));3838return (kern_posix_error(td, error));3839}38403841int3842freebsd32_posix_fadvise(struct thread *td,3843struct freebsd32_posix_fadvise_args *uap)3844{3845int error;38463847error = kern_posix_fadvise(td, uap->fd, PAIR32TO64(off_t, uap->offset),3848PAIR32TO64(off_t, uap->len), uap->advice);3849return (kern_posix_error(td, error));3850}38513852int3853convert_sigevent32(struct sigevent32 *sig32, struct sigevent *sig)3854{38553856CP(*sig32, *sig, sigev_notify);3857switch (sig->sigev_notify) {3858case SIGEV_NONE:3859break;3860case SIGEV_THREAD_ID:3861CP(*sig32, *sig, sigev_notify_thread_id);3862/* FALLTHROUGH */3863case SIGEV_SIGNAL:3864CP(*sig32, *sig, sigev_signo);3865PTRIN_CP(*sig32, *sig, sigev_value.sival_ptr);3866break;3867case SIGEV_KEVENT:3868CP(*sig32, *sig, sigev_notify_kqueue);3869CP(*sig32, *sig, sigev_notify_kevent_flags);3870PTRIN_CP(*sig32, *sig, sigev_value.sival_ptr);3871break;3872default:3873return (EINVAL);3874}3875return (0);3876}38773878int3879freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)3880{3881void *data;3882union {3883struct procctl_reaper_status rs;3884struct procctl_reaper_pids rp;3885struct procctl_reaper_kill rk;3886} x;3887union {3888struct procctl_reaper_pids32 rp;3889} x32;3890int error, error1, flags, signum;38913892if (uap->com >= PROC_PROCCTL_MD_MIN)3893return (cpu_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id),3894uap->com, PTRIN(uap->data)));38953896switch (uap->com) {3897case PROC_ASLR_CTL:3898case PROC_PROTMAX_CTL:3899case PROC_SPROTECT:3900case PROC_STACKGAP_CTL:3901case PROC_TRACE_CTL:3902case PROC_TRAPCAP_CTL:3903case PROC_NO_NEW_PRIVS_CTL:3904case PROC_WXMAP_CTL:3905case PROC_LOGSIGEXIT_CTL:3906error = copyin(PTRIN(uap->data), &flags, sizeof(flags));3907if (error != 0)3908return (error);3909data = &flags;3910break;3911case PROC_REAP_ACQUIRE:3912case PROC_REAP_RELEASE:3913if (uap->data != NULL)3914return (EINVAL);3915data = NULL;3916break;3917case PROC_REAP_STATUS:3918data = &x.rs;3919break;3920case PROC_REAP_GETPIDS:3921error = copyin(uap->data, &x32.rp, sizeof(x32.rp));3922if (error != 0)3923return (error);3924CP(x32.rp, x.rp, rp_count);3925PTRIN_CP(x32.rp, x.rp, rp_pids);3926data = &x.rp;3927break;3928case PROC_REAP_KILL:3929error = copyin(uap->data, &x.rk, sizeof(x.rk));3930if (error != 0)3931return (error);3932data = &x.rk;3933break;3934case PROC_ASLR_STATUS:3935case PROC_PROTMAX_STATUS:3936case PROC_STACKGAP_STATUS:3937case PROC_TRACE_STATUS:3938case PROC_TRAPCAP_STATUS:3939case PROC_NO_NEW_PRIVS_STATUS:3940case PROC_WXMAP_STATUS:3941case PROC_LOGSIGEXIT_STATUS:3942data = &flags;3943break;3944case PROC_PDEATHSIG_CTL:3945error = copyin(uap->data, &signum, sizeof(signum));3946if (error != 0)3947return (error);3948data = &signum;3949break;3950case PROC_PDEATHSIG_STATUS:3951data = &signum;3952break;3953default:3954return (EINVAL);3955}3956error = kern_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id),3957uap->com, data);3958switch (uap->com) {3959case PROC_REAP_STATUS:3960if (error == 0)3961error = copyout(&x.rs, uap->data, sizeof(x.rs));3962break;3963case PROC_REAP_KILL:3964error1 = copyout(&x.rk, uap->data, sizeof(x.rk));3965if (error == 0)3966error = error1;3967break;3968case PROC_ASLR_STATUS:3969case PROC_PROTMAX_STATUS:3970case PROC_STACKGAP_STATUS:3971case PROC_TRACE_STATUS:3972case PROC_TRAPCAP_STATUS:3973case PROC_NO_NEW_PRIVS_STATUS:3974case PROC_WXMAP_STATUS:3975case PROC_LOGSIGEXIT_STATUS:3976if (error == 0)3977error = copyout(&flags, uap->data, sizeof(flags));3978break;3979case PROC_PDEATHSIG_STATUS:3980if (error == 0)3981error = copyout(&signum, uap->data, sizeof(signum));3982break;3983}3984return (error);3985}39863987int3988freebsd32_fcntl(struct thread *td, struct freebsd32_fcntl_args *uap)3989{3990intptr_t tmp;39913992switch (uap->cmd) {3993/*3994* Do unsigned conversion for arg when operation3995* interprets it as flags or pointer.3996*/3997case F_SETLK_REMOTE:3998case F_SETLKW:3999case F_SETLK:4000case F_GETLK:4001case F_SETFD:4002case F_SETFL:4003case F_OGETLK:4004case F_OSETLK:4005case F_OSETLKW:4006case F_KINFO:4007tmp = (unsigned int)(uap->arg);4008break;4009default:4010tmp = uap->arg;4011break;4012}4013return (kern_fcntl_freebsd(td, uap->fd, uap->cmd, tmp));4014}40154016int4017freebsd32_ppoll(struct thread *td, struct freebsd32_ppoll_args *uap)4018{4019struct timespec32 ts32;4020struct timespec ts, *tsp;4021sigset_t set, *ssp;4022int error;40234024if (uap->ts != NULL) {4025error = copyin(uap->ts, &ts32, sizeof(ts32));4026if (error != 0)4027return (error);4028CP(ts32, ts, tv_sec);4029CP(ts32, ts, tv_nsec);4030tsp = &ts;4031} else4032tsp = NULL;4033if (uap->set != NULL) {4034error = copyin(uap->set, &set, sizeof(set));4035if (error != 0)4036return (error);4037ssp = &set;4038} else4039ssp = NULL;40404041return (kern_poll(td, uap->fds, uap->nfds, tsp, ssp));4042}40434044int4045freebsd32_sched_rr_get_interval(struct thread *td,4046struct freebsd32_sched_rr_get_interval_args *uap)4047{4048struct timespec ts;4049struct timespec32 ts32;4050int error;40514052error = kern_sched_rr_get_interval(td, uap->pid, &ts);4053if (error == 0) {4054CP(ts, ts32, tv_sec);4055CP(ts, ts32, tv_nsec);4056error = copyout(&ts32, uap->interval, sizeof(ts32));4057}4058return (error);4059}40604061static void4062timex_to_32(struct timex32 *dst, struct timex *src)4063{4064CP(*src, *dst, modes);4065CP(*src, *dst, offset);4066CP(*src, *dst, freq);4067CP(*src, *dst, maxerror);4068CP(*src, *dst, esterror);4069CP(*src, *dst, status);4070CP(*src, *dst, constant);4071CP(*src, *dst, precision);4072CP(*src, *dst, tolerance);4073CP(*src, *dst, ppsfreq);4074CP(*src, *dst, jitter);4075CP(*src, *dst, shift);4076CP(*src, *dst, stabil);4077CP(*src, *dst, jitcnt);4078CP(*src, *dst, calcnt);4079CP(*src, *dst, errcnt);4080CP(*src, *dst, stbcnt);4081}40824083static void4084timex_from_32(struct timex *dst, struct timex32 *src)4085{4086CP(*src, *dst, modes);4087CP(*src, *dst, offset);4088CP(*src, *dst, freq);4089CP(*src, *dst, maxerror);4090CP(*src, *dst, esterror);4091CP(*src, *dst, status);4092CP(*src, *dst, constant);4093CP(*src, *dst, precision);4094CP(*src, *dst, tolerance);4095CP(*src, *dst, ppsfreq);4096CP(*src, *dst, jitter);4097CP(*src, *dst, shift);4098CP(*src, *dst, stabil);4099CP(*src, *dst, jitcnt);4100CP(*src, *dst, calcnt);4101CP(*src, *dst, errcnt);4102CP(*src, *dst, stbcnt);4103}41044105int4106freebsd32_ntp_adjtime(struct thread *td, struct freebsd32_ntp_adjtime_args *uap)4107{4108struct timex tx;4109struct timex32 tx32;4110int error, retval;41114112error = copyin(uap->tp, &tx32, sizeof(tx32));4113if (error == 0) {4114timex_from_32(&tx, &tx32);4115error = kern_ntp_adjtime(td, &tx, &retval);4116if (error == 0) {4117timex_to_32(&tx32, &tx);4118error = copyout(&tx32, uap->tp, sizeof(tx32));4119if (error == 0)4120td->td_retval[0] = retval;4121}4122}4123return (error);4124}41254126#ifdef FFCLOCK4127extern struct mtx ffclock_mtx;4128extern struct ffclock_estimate ffclock_estimate;4129extern int8_t ffclock_updated;41304131int4132freebsd32_ffclock_setestimate(struct thread *td,4133struct freebsd32_ffclock_setestimate_args *uap)4134{4135struct ffclock_estimate cest;4136struct ffclock_estimate32 cest32;4137int error;41384139/* Reuse of PRIV_CLOCK_SETTIME. */4140if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0)4141return (error);41424143if ((error = copyin(uap->cest, &cest32,4144sizeof(struct ffclock_estimate32))) != 0)4145return (error);41464147CP(cest.update_time, cest32.update_time, sec);4148memcpy(&cest.update_time.frac, &cest32.update_time.frac, sizeof(uint64_t));4149CP(cest, cest32, update_ffcount);4150CP(cest, cest32, leapsec_next);4151FU64_CP(cest, cest32, period);4152CP(cest, cest32, errb_abs);4153CP(cest, cest32, errb_rate);4154CP(cest, cest32, status);4155CP(cest, cest32, leapsec_total);4156CP(cest, cest32, leapsec);41574158mtx_lock(&ffclock_mtx);4159memcpy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate));4160ffclock_updated++;4161mtx_unlock(&ffclock_mtx);4162return (error);4163}41644165int4166freebsd32_ffclock_getestimate(struct thread *td,4167struct freebsd32_ffclock_getestimate_args *uap)4168{4169struct ffclock_estimate cest;4170struct ffclock_estimate32 cest32;4171int error;41724173mtx_lock(&ffclock_mtx);4174memcpy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate));4175mtx_unlock(&ffclock_mtx);41764177CP(cest32.update_time, cest.update_time, sec);4178memcpy(&cest32.update_time.frac, &cest.update_time.frac, sizeof(uint64_t));4179CP(cest32, cest, update_ffcount);4180CP(cest32, cest, leapsec_next);4181FU64_CP(cest32, cest, period);4182CP(cest32, cest, errb_abs);4183CP(cest32, cest, errb_rate);4184CP(cest32, cest, status);4185CP(cest32, cest, leapsec_total);4186CP(cest32, cest, leapsec);41874188error = copyout(&cest32, uap->cest, sizeof(struct ffclock_estimate32));4189return (error);4190}4191#else /* !FFCLOCK */4192int4193freebsd32_ffclock_setestimate(struct thread *td,4194struct freebsd32_ffclock_setestimate_args *uap)4195{4196return (ENOSYS);4197}41984199int4200freebsd32_ffclock_getestimate(struct thread *td,4201struct freebsd32_ffclock_getestimate_args *uap)4202{4203return (ENOSYS);4204}4205#endif /* FFCLOCK */42064207#ifdef COMPAT_434208int4209ofreebsd32_sethostid(struct thread *td, struct ofreebsd32_sethostid_args *uap)4210{4211int name[] = { CTL_KERN, KERN_HOSTID };4212long hostid;42134214hostid = uap->hostid;4215return (kernel_sysctl(td, name, nitems(name), NULL, NULL, &hostid,4216sizeof(hostid), NULL, 0));4217}4218#endif42194220int4221freebsd32_setcred(struct thread *td, struct freebsd32_setcred_args *uap)4222{4223struct setcred wcred;4224struct setcred32 wcred32;4225int error;42264227if (uap->size != sizeof(wcred32))4228return (EINVAL);4229error = copyin(uap->wcred, &wcred32, sizeof(wcred32));4230if (error != 0)4231return (error);4232memset(&wcred, 0, sizeof(wcred));4233CP(wcred32, wcred, sc_uid);4234CP(wcred32, wcred, sc_ruid);4235CP(wcred32, wcred, sc_svuid);4236CP(wcred32, wcred, sc_gid);4237CP(wcred32, wcred, sc_rgid);4238CP(wcred32, wcred, sc_svgid);4239CP(wcred32, wcred, sc_supp_groups_nb);4240PTRIN_CP(wcred32, wcred, sc_supp_groups);4241PTRIN_CP(wcred32, wcred, sc_label);4242return (user_setcred(td, uap->flags, &wcred));4243}424442454246