Path: blob/main/sys/compat/freebsd32/freebsd32_misc.c
39478 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{204205TV_CP(*s, *s32, ru_utime);206TV_CP(*s, *s32, ru_stime);207CP(*s, *s32, ru_maxrss);208CP(*s, *s32, ru_ixrss);209CP(*s, *s32, ru_idrss);210CP(*s, *s32, ru_isrss);211CP(*s, *s32, ru_minflt);212CP(*s, *s32, ru_majflt);213CP(*s, *s32, ru_nswap);214CP(*s, *s32, ru_inblock);215CP(*s, *s32, ru_oublock);216CP(*s, *s32, ru_msgsnd);217CP(*s, *s32, ru_msgrcv);218CP(*s, *s32, ru_nsignals);219CP(*s, *s32, ru_nvcsw);220CP(*s, *s32, ru_nivcsw);221}222223int224freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)225{226int error, status;227struct rusage32 ru32;228struct rusage ru, *rup;229230if (uap->rusage != NULL)231rup = &ru;232else233rup = NULL;234error = kern_wait(td, uap->pid, &status, uap->options, rup);235if (error)236return (error);237if (uap->status != NULL)238error = copyout(&status, uap->status, sizeof(status));239if (uap->rusage != NULL && error == 0) {240freebsd32_rusage_out(&ru, &ru32);241error = copyout(&ru32, uap->rusage, sizeof(ru32));242}243return (error);244}245246int247freebsd32_wait6(struct thread *td, struct freebsd32_wait6_args *uap)248{249struct __wrusage32 wru32;250struct __wrusage wru, *wrup;251struct __siginfo32 si32;252struct __siginfo si, *sip;253int error, status;254255if (uap->wrusage != NULL)256wrup = &wru;257else258wrup = NULL;259if (uap->info != NULL) {260sip = &si;261bzero(sip, sizeof(*sip));262} else263sip = NULL;264error = kern_wait6(td, uap->idtype, PAIR32TO64(id_t, uap->id),265&status, uap->options, wrup, sip);266if (error != 0)267return (error);268if (uap->status != NULL)269error = copyout(&status, uap->status, sizeof(status));270if (uap->wrusage != NULL && error == 0) {271freebsd32_rusage_out(&wru.wru_self, &wru32.wru_self);272freebsd32_rusage_out(&wru.wru_children, &wru32.wru_children);273error = copyout(&wru32, uap->wrusage, sizeof(wru32));274}275if (uap->info != NULL && error == 0) {276siginfo_to_siginfo32 (&si, &si32);277error = copyout(&si32, uap->info, sizeof(si32));278}279return (error);280}281282#ifdef COMPAT_FREEBSD4283static void284copy_statfs(struct statfs *in, struct ostatfs32 *out)285{286287statfs_scale_blocks(in, INT32_MAX);288bzero(out, sizeof(*out));289CP(*in, *out, f_bsize);290out->f_iosize = MIN(in->f_iosize, INT32_MAX);291CP(*in, *out, f_blocks);292CP(*in, *out, f_bfree);293CP(*in, *out, f_bavail);294out->f_files = MIN(in->f_files, INT32_MAX);295out->f_ffree = MIN(in->f_ffree, INT32_MAX);296CP(*in, *out, f_fsid);297CP(*in, *out, f_owner);298CP(*in, *out, f_type);299CP(*in, *out, f_flags);300out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);301out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);302strlcpy(out->f_fstypename,303in->f_fstypename, MFSNAMELEN);304strlcpy(out->f_mntonname,305in->f_mntonname, min(MNAMELEN, FREEBSD4_OMNAMELEN));306out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);307out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);308strlcpy(out->f_mntfromname,309in->f_mntfromname, min(MNAMELEN, FREEBSD4_OMNAMELEN));310}311#endif312313int314freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)315{316size_t count;317int error;318319if (uap->bufsize < 0 || uap->bufsize > SIZE_MAX)320return (EINVAL);321error = kern_getfsstat(td, &uap->buf, uap->bufsize, &count,322UIO_USERSPACE, uap->mode);323if (error == 0)324td->td_retval[0] = count;325return (error);326}327328#ifdef COMPAT_FREEBSD4329int330freebsd4_freebsd32_getfsstat(struct thread *td,331struct freebsd4_freebsd32_getfsstat_args *uap)332{333struct statfs *buf, *sp;334struct ostatfs32 stat32;335size_t count, size, copycount;336int error;337338count = uap->bufsize / sizeof(struct ostatfs32);339size = count * sizeof(struct statfs);340error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE, uap->mode);341if (size > 0) {342sp = buf;343copycount = count;344while (copycount > 0 && error == 0) {345copy_statfs(sp, &stat32);346error = copyout(&stat32, uap->buf, sizeof(stat32));347sp++;348uap->buf++;349copycount--;350}351free(buf, M_STATFS);352}353if (error == 0)354td->td_retval[0] = count;355return (error);356}357#endif358359#ifdef COMPAT_FREEBSD11360int361freebsd11_freebsd32_getfsstat(struct thread *td,362struct freebsd11_freebsd32_getfsstat_args *uap)363{364return(kern_freebsd11_getfsstat(td, uap->buf, uap->bufsize,365uap->mode));366}367#endif368369int370freebsd32_sigaltstack(struct thread *td,371struct freebsd32_sigaltstack_args *uap)372{373struct sigaltstack32 s32;374struct sigaltstack ss, oss, *ssp;375int error;376377if (uap->ss != NULL) {378error = copyin(uap->ss, &s32, sizeof(s32));379if (error)380return (error);381PTRIN_CP(s32, ss, ss_sp);382CP(s32, ss, ss_size);383CP(s32, ss, ss_flags);384ssp = &ss;385} else386ssp = NULL;387error = kern_sigaltstack(td, ssp, &oss);388if (error == 0 && uap->oss != NULL) {389PTROUT_CP(oss, s32, ss_sp);390CP(oss, s32, ss_size);391CP(oss, s32, ss_flags);392error = copyout(&s32, uap->oss, sizeof(s32));393}394return (error);395}396397/*398* Custom version of exec_copyin_args() so that we can translate399* the pointers.400*/401int402freebsd32_exec_copyin_args(struct image_args *args, const char *fname,403uint32_t *argv, uint32_t *envv)404{405char *argp, *envp;406uint32_t *p32, arg;407int error;408409bzero(args, sizeof(*args));410if (argv == NULL)411return (EFAULT);412413/*414* Allocate demand-paged memory for the file name, argument, and415* environment strings.416*/417error = exec_alloc_args(args);418if (error != 0)419return (error);420421/*422* Copy the file name.423*/424error = exec_args_add_fname(args, fname, UIO_USERSPACE);425if (error != 0)426goto err_exit;427428/*429* extract arguments first430*/431p32 = argv;432for (;;) {433error = copyin(p32++, &arg, sizeof(arg));434if (error)435goto err_exit;436if (arg == 0)437break;438argp = PTRIN(arg);439error = exec_args_add_arg(args, argp, UIO_USERSPACE);440if (error != 0)441goto err_exit;442}443444/*445* extract environment strings446*/447if (envv) {448p32 = envv;449for (;;) {450error = copyin(p32++, &arg, sizeof(arg));451if (error)452goto err_exit;453if (arg == 0)454break;455envp = PTRIN(arg);456error = exec_args_add_env(args, envp, UIO_USERSPACE);457if (error != 0)458goto err_exit;459}460}461462return (0);463464err_exit:465exec_free_args(args);466return (error);467}468469int470freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)471{472struct image_args eargs;473struct vmspace *oldvmspace;474int error;475476error = pre_execve(td, &oldvmspace);477if (error != 0)478return (error);479error = freebsd32_exec_copyin_args(&eargs, uap->fname, uap->argv,480uap->envv);481if (error == 0)482error = kern_execve(td, &eargs, NULL, oldvmspace);483post_execve(td, error, oldvmspace);484AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td);485return (error);486}487488int489freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)490{491struct image_args eargs;492struct vmspace *oldvmspace;493int error;494495error = pre_execve(td, &oldvmspace);496if (error != 0)497return (error);498error = freebsd32_exec_copyin_args(&eargs, NULL, uap->argv, uap->envv);499if (error == 0) {500eargs.fd = uap->fd;501error = kern_execve(td, &eargs, NULL, oldvmspace);502}503post_execve(td, error, oldvmspace);504AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td);505return (error);506}507508int509freebsd32_mknodat(struct thread *td, struct freebsd32_mknodat_args *uap)510{511512return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE,513uap->mode, PAIR32TO64(dev_t, uap->dev)));514}515516int517freebsd32_mprotect(struct thread *td, struct freebsd32_mprotect_args *uap)518{519int prot;520521prot = uap->prot;522#if defined(__amd64__)523if (i386_read_exec && (prot & PROT_READ) != 0)524prot |= PROT_EXEC;525#endif526return (kern_mprotect(td, (uintptr_t)PTRIN(uap->addr), uap->len,527prot, 0));528}529530int531freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)532{533int prot;534535prot = uap->prot;536#if defined(__amd64__)537if (i386_read_exec && (prot & PROT_READ))538prot |= PROT_EXEC;539#endif540541return (kern_mmap(td, &(struct mmap_req){542.mr_hint = (uintptr_t)uap->addr,543.mr_len = uap->len,544.mr_prot = prot,545.mr_flags = uap->flags,546.mr_fd = uap->fd,547.mr_pos = PAIR32TO64(off_t, uap->pos),548}));549}550551#ifdef COMPAT_FREEBSD6552int553freebsd6_freebsd32_mmap(struct thread *td,554struct freebsd6_freebsd32_mmap_args *uap)555{556int prot;557558prot = uap->prot;559#if defined(__amd64__)560if (i386_read_exec && (prot & PROT_READ))561prot |= PROT_EXEC;562#endif563564return (kern_mmap(td, &(struct mmap_req){565.mr_hint = (uintptr_t)uap->addr,566.mr_len = uap->len,567.mr_prot = prot,568.mr_flags = uap->flags,569.mr_fd = uap->fd,570.mr_pos = PAIR32TO64(off_t, uap->pos),571}));572}573#endif574575#ifdef COMPAT_43576int577ofreebsd32_mmap(struct thread *td, struct ofreebsd32_mmap_args *uap)578{579return (kern_ommap(td, (uintptr_t)uap->addr, uap->len, uap->prot,580uap->flags, uap->fd, uap->pos));581}582#endif583584int585freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)586{587struct itimerval itv, oitv, *itvp;588struct itimerval32 i32;589int error;590591if (uap->itv != NULL) {592error = copyin(uap->itv, &i32, sizeof(i32));593if (error)594return (error);595TV_CP(i32, itv, it_interval);596TV_CP(i32, itv, it_value);597itvp = &itv;598} else599itvp = NULL;600error = kern_setitimer(td, uap->which, itvp, &oitv);601if (error || uap->oitv == NULL)602return (error);603TV_CP(oitv, i32, it_interval);604TV_CP(oitv, i32, it_value);605return (copyout(&i32, uap->oitv, sizeof(i32)));606}607608int609freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)610{611struct itimerval itv;612struct itimerval32 i32;613int error;614615error = kern_getitimer(td, uap->which, &itv);616if (error || uap->itv == NULL)617return (error);618TV_CP(itv, i32, it_interval);619TV_CP(itv, i32, it_value);620return (copyout(&i32, uap->itv, sizeof(i32)));621}622623int624freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)625{626struct timeval32 tv32;627struct timeval tv, *tvp;628int error;629630if (uap->tv != NULL) {631error = copyin(uap->tv, &tv32, sizeof(tv32));632if (error)633return (error);634CP(tv32, tv, tv_sec);635CP(tv32, tv, tv_usec);636tvp = &tv;637} else638tvp = NULL;639/*640* XXX Do pointers need PTRIN()?641*/642return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,643sizeof(int32_t) * 8));644}645646int647freebsd32_pselect(struct thread *td, struct freebsd32_pselect_args *uap)648{649struct timespec32 ts32;650struct timespec ts;651struct timeval tv, *tvp;652sigset_t set, *uset;653int error;654655if (uap->ts != NULL) {656error = copyin(uap->ts, &ts32, sizeof(ts32));657if (error != 0)658return (error);659CP(ts32, ts, tv_sec);660CP(ts32, ts, tv_nsec);661TIMESPEC_TO_TIMEVAL(&tv, &ts);662tvp = &tv;663} else664tvp = NULL;665if (uap->sm != NULL) {666error = copyin(uap->sm, &set, sizeof(set));667if (error != 0)668return (error);669uset = &set;670} else671uset = NULL;672/*673* XXX Do pointers need PTRIN()?674*/675error = kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,676uset, sizeof(int32_t) * 8);677return (error);678}679680static void681freebsd32_kevent_to_kevent32(const struct kevent *kevp, struct kevent32 *ks32)682{683uint64_t e;684int j;685686CP(*kevp, *ks32, ident);687CP(*kevp, *ks32, filter);688CP(*kevp, *ks32, flags);689CP(*kevp, *ks32, fflags);690#if BYTE_ORDER == LITTLE_ENDIAN691ks32->data1 = kevp->data;692ks32->data2 = kevp->data >> 32;693#else694ks32->data1 = kevp->data >> 32;695ks32->data2 = kevp->data;696#endif697PTROUT_CP(*kevp, *ks32, udata);698for (j = 0; j < nitems(kevp->ext); j++) {699e = kevp->ext[j];700#if BYTE_ORDER == LITTLE_ENDIAN701ks32->ext64[2 * j] = e;702ks32->ext64[2 * j + 1] = e >> 32;703#else704ks32->ext64[2 * j] = e >> 32;705ks32->ext64[2 * j + 1] = e;706#endif707}708}709710void711freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,712struct kinfo_knote32 *kin32)713{714memset(kin32, 0, sizeof(*kin32));715CP(*kin, *kin32, knt_kq_fd);716freebsd32_kevent_to_kevent32(&kin->knt_event, &kin32->knt_event);717CP(*kin, *kin32, knt_status);718CP(*kin, *kin32, knt_extdata);719switch (kin->knt_extdata) {720case KNOTE_EXTDATA_NONE:721break;722case KNOTE_EXTDATA_VNODE:723CP(*kin, *kin32, knt_vnode.knt_vnode_type);724#if BYTE_ORDER == LITTLE_ENDIAN725kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.726knt_vnode_fsid;727kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.728knt_vnode_fsid >> 32;729kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.730knt_vnode_fileid;731kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.732knt_vnode_fileid >> 32;733#else734kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.735knt_vnode_fsid;736kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.737knt_vnode_fsid >> 32;738kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.739knt_vnode_fileid;740kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.741knt_vnode_fileid >> 32;742#endif743memcpy(kin32->knt_vnode.knt_vnode_fullpath,744kin->knt_vnode.knt_vnode_fullpath, PATH_MAX);745break;746case KNOTE_EXTDATA_PIPE:747#if BYTE_ORDER == LITTLE_ENDIAN748kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.knt_pipe_ino;749kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.750knt_pipe_ino >> 32;751#else752kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.knt_pipe_ino;753kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.754knt_pipe_ino >> 32;755#endif756break;757}758}759760/*761* Copy 'count' items into the destination list pointed to by uap->eventlist.762*/763static int764freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)765{766struct freebsd32_kevent_args *uap;767struct kevent32 ks32[KQ_NEVENTS];768int i, error;769770KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));771uap = (struct freebsd32_kevent_args *)arg;772773for (i = 0; i < count; i++)774freebsd32_kevent_to_kevent32(&kevp[i], &ks32[i]);775error = copyout(ks32, uap->eventlist, count * sizeof *ks32);776if (error == 0)777uap->eventlist += count;778return (error);779}780781/*782* Copy 'count' items from the list pointed to by uap->changelist.783*/784static int785freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)786{787struct freebsd32_kevent_args *uap;788struct kevent32 ks32[KQ_NEVENTS];789uint64_t e;790int i, j, error;791792KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));793uap = (struct freebsd32_kevent_args *)arg;794795error = copyin(uap->changelist, ks32, count * sizeof *ks32);796if (error)797goto done;798uap->changelist += count;799800for (i = 0; i < count; i++) {801CP(ks32[i], kevp[i], ident);802CP(ks32[i], kevp[i], filter);803CP(ks32[i], kevp[i], flags);804CP(ks32[i], kevp[i], fflags);805kevp[i].data = PAIR32TO64(uint64_t, ks32[i].data);806PTRIN_CP(ks32[i], kevp[i], udata);807for (j = 0; j < nitems(kevp->ext); j++) {808#if BYTE_ORDER == LITTLE_ENDIAN809e = ks32[i].ext64[2 * j + 1];810e <<= 32;811e += ks32[i].ext64[2 * j];812#else813e = ks32[i].ext64[2 * j];814e <<= 32;815e += ks32[i].ext64[2 * j + 1];816#endif817kevp[i].ext[j] = e;818}819}820done:821return (error);822}823824int825freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)826{827struct timespec32 ts32;828struct timespec ts, *tsp;829struct kevent_copyops k_ops = {830.arg = uap,831.k_copyout = freebsd32_kevent_copyout,832.k_copyin = freebsd32_kevent_copyin,833};834#ifdef KTRACE835struct kevent32 *eventlist = uap->eventlist;836#endif837int error;838839if (uap->timeout) {840error = copyin(uap->timeout, &ts32, sizeof(ts32));841if (error)842return (error);843CP(ts32, ts, tv_sec);844CP(ts32, ts, tv_nsec);845tsp = &ts;846} else847tsp = NULL;848#ifdef KTRACE849if (KTRPOINT(td, KTR_STRUCT_ARRAY))850ktrstructarray("kevent32", UIO_USERSPACE, uap->changelist,851uap->nchanges, sizeof(struct kevent32));852#endif853error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,854&k_ops, tsp);855#ifdef KTRACE856if (error == 0 && KTRPOINT(td, KTR_STRUCT_ARRAY))857ktrstructarray("kevent32", UIO_USERSPACE, eventlist,858td->td_retval[0], sizeof(struct kevent32));859#endif860return (error);861}862863#ifdef COMPAT_FREEBSD11864static int865freebsd32_kevent11_copyout(void *arg, struct kevent *kevp, int count)866{867struct freebsd11_freebsd32_kevent_args *uap;868struct freebsd11_kevent32 ks32[KQ_NEVENTS];869int i, error;870871KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));872uap = (struct freebsd11_freebsd32_kevent_args *)arg;873874for (i = 0; i < count; i++) {875CP(kevp[i], ks32[i], ident);876CP(kevp[i], ks32[i], filter);877CP(kevp[i], ks32[i], flags);878CP(kevp[i], ks32[i], fflags);879CP(kevp[i], ks32[i], data);880PTROUT_CP(kevp[i], ks32[i], udata);881}882error = copyout(ks32, uap->eventlist, count * sizeof *ks32);883if (error == 0)884uap->eventlist += count;885return (error);886}887888/*889* Copy 'count' items from the list pointed to by uap->changelist.890*/891static int892freebsd32_kevent11_copyin(void *arg, struct kevent *kevp, int count)893{894struct freebsd11_freebsd32_kevent_args *uap;895struct freebsd11_kevent32 ks32[KQ_NEVENTS];896int i, j, error;897898KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));899uap = (struct freebsd11_freebsd32_kevent_args *)arg;900901error = copyin(uap->changelist, ks32, count * sizeof *ks32);902if (error)903goto done;904uap->changelist += count;905906for (i = 0; i < count; i++) {907CP(ks32[i], kevp[i], ident);908CP(ks32[i], kevp[i], filter);909CP(ks32[i], kevp[i], flags);910CP(ks32[i], kevp[i], fflags);911CP(ks32[i], kevp[i], data);912PTRIN_CP(ks32[i], kevp[i], udata);913for (j = 0; j < nitems(kevp->ext); j++)914kevp[i].ext[j] = 0;915}916done:917return (error);918}919920int921freebsd11_freebsd32_kevent(struct thread *td,922struct freebsd11_freebsd32_kevent_args *uap)923{924struct timespec32 ts32;925struct timespec ts, *tsp;926struct kevent_copyops k_ops = {927.arg = uap,928.k_copyout = freebsd32_kevent11_copyout,929.k_copyin = freebsd32_kevent11_copyin,930};931#ifdef KTRACE932struct freebsd11_kevent32 *eventlist = uap->eventlist;933#endif934int error;935936if (uap->timeout) {937error = copyin(uap->timeout, &ts32, sizeof(ts32));938if (error)939return (error);940CP(ts32, ts, tv_sec);941CP(ts32, ts, tv_nsec);942tsp = &ts;943} else944tsp = NULL;945#ifdef KTRACE946if (KTRPOINT(td, KTR_STRUCT_ARRAY))947ktrstructarray("freebsd11_kevent32", UIO_USERSPACE,948uap->changelist, uap->nchanges,949sizeof(struct freebsd11_kevent32));950#endif951error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,952&k_ops, tsp);953#ifdef KTRACE954if (error == 0 && KTRPOINT(td, KTR_STRUCT_ARRAY))955ktrstructarray("freebsd11_kevent32", UIO_USERSPACE,956eventlist, td->td_retval[0],957sizeof(struct freebsd11_kevent32));958#endif959return (error);960}961#endif962963int964freebsd32_gettimeofday(struct thread *td,965struct freebsd32_gettimeofday_args *uap)966{967struct timeval atv;968struct timeval32 atv32;969struct timezone rtz;970int error = 0;971972if (uap->tp) {973microtime(&atv);974CP(atv, atv32, tv_sec);975CP(atv, atv32, tv_usec);976error = copyout(&atv32, uap->tp, sizeof (atv32));977}978if (error == 0 && uap->tzp != NULL) {979rtz.tz_minuteswest = 0;980rtz.tz_dsttime = 0;981error = copyout(&rtz, uap->tzp, sizeof (rtz));982}983return (error);984}985986int987freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)988{989struct rusage32 s32;990struct rusage s;991int error;992993error = kern_getrusage(td, uap->who, &s);994if (error == 0) {995freebsd32_rusage_out(&s, &s32);996error = copyout(&s32, uap->rusage, sizeof(s32));997}998return (error);999}10001001static void1002ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,1003struct ptrace_lwpinfo32 *pl32)1004{10051006bzero(pl32, sizeof(*pl32));1007pl32->pl_lwpid = pl->pl_lwpid;1008pl32->pl_event = pl->pl_event;1009pl32->pl_flags = pl->pl_flags;1010pl32->pl_sigmask = pl->pl_sigmask;1011pl32->pl_siglist = pl->pl_siglist;1012siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);1013strcpy(pl32->pl_tdname, pl->pl_tdname);1014pl32->pl_child_pid = pl->pl_child_pid;1015pl32->pl_syscall_code = pl->pl_syscall_code;1016pl32->pl_syscall_narg = pl->pl_syscall_narg;1017}10181019static void1020ptrace_sc_ret_to32(const struct ptrace_sc_ret *psr,1021struct ptrace_sc_ret32 *psr32)1022{10231024bzero(psr32, sizeof(*psr32));1025psr32->sr_retval[0] = psr->sr_retval[0];1026psr32->sr_retval[1] = psr->sr_retval[1];1027psr32->sr_error = psr->sr_error;1028}10291030int1031freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)1032{1033union {1034struct ptrace_io_desc piod;1035struct ptrace_lwpinfo pl;1036struct ptrace_vm_entry pve;1037struct ptrace_coredump pc;1038struct ptrace_sc_remote sr;1039struct dbreg32 dbreg;1040struct fpreg32 fpreg;1041struct reg32 reg;1042struct iovec vec;1043register_t args[nitems(td->td_sa.args)];1044struct ptrace_sc_ret psr;1045int ptevents;1046} r;1047union {1048struct ptrace_io_desc32 piod;1049struct ptrace_lwpinfo32 pl;1050struct ptrace_vm_entry32 pve;1051struct ptrace_coredump32 pc;1052struct ptrace_sc_remote32 sr;1053uint32_t args[nitems(td->td_sa.args)];1054struct ptrace_sc_ret32 psr;1055struct iovec32 vec;1056} r32;1057syscallarg_t pscr_args[nitems(td->td_sa.args)];1058u_int pscr_args32[nitems(td->td_sa.args)];1059void *addr;1060int data, error, i;10611062if (!allow_ptrace)1063return (ENOSYS);1064error = 0;10651066AUDIT_ARG_PID(uap->pid);1067AUDIT_ARG_CMD(uap->req);1068AUDIT_ARG_VALUE(uap->data);1069addr = &r;1070data = uap->data;1071switch (uap->req) {1072case PT_GET_EVENT_MASK:1073case PT_GET_SC_ARGS:1074case PT_GET_SC_RET:1075break;1076case PT_LWPINFO:1077if (uap->data > sizeof(r32.pl))1078return (EINVAL);10791080/*1081* Pass size of native structure in 'data'. Truncate1082* if necessary to avoid siginfo.1083*/1084data = sizeof(r.pl);1085if (uap->data < offsetof(struct ptrace_lwpinfo32, pl_siginfo) +1086sizeof(struct __siginfo32))1087data = offsetof(struct ptrace_lwpinfo, pl_siginfo);1088break;1089case PT_GETREGS:1090bzero(&r.reg, sizeof(r.reg));1091break;1092case PT_GETFPREGS:1093bzero(&r.fpreg, sizeof(r.fpreg));1094break;1095case PT_GETDBREGS:1096bzero(&r.dbreg, sizeof(r.dbreg));1097break;1098case PT_SETREGS:1099error = copyin(uap->addr, &r.reg, sizeof(r.reg));1100break;1101case PT_SETFPREGS:1102error = copyin(uap->addr, &r.fpreg, sizeof(r.fpreg));1103break;1104case PT_SETDBREGS:1105error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg));1106break;1107case PT_GETREGSET:1108case PT_SETREGSET:1109error = copyin(uap->addr, &r32.vec, sizeof(r32.vec));1110if (error != 0)1111break;11121113r.vec.iov_len = r32.vec.iov_len;1114r.vec.iov_base = PTRIN(r32.vec.iov_base);1115break;1116case PT_SET_EVENT_MASK:1117if (uap->data != sizeof(r.ptevents))1118error = EINVAL;1119else1120error = copyin(uap->addr, &r.ptevents, uap->data);1121break;1122case PT_IO:1123error = copyin(uap->addr, &r32.piod, sizeof(r32.piod));1124if (error)1125break;1126CP(r32.piod, r.piod, piod_op);1127PTRIN_CP(r32.piod, r.piod, piod_offs);1128PTRIN_CP(r32.piod, r.piod, piod_addr);1129CP(r32.piod, r.piod, piod_len);1130break;1131case PT_VM_ENTRY:1132error = copyin(uap->addr, &r32.pve, sizeof(r32.pve));1133if (error)1134break;11351136CP(r32.pve, r.pve, pve_entry);1137CP(r32.pve, r.pve, pve_timestamp);1138CP(r32.pve, r.pve, pve_start);1139CP(r32.pve, r.pve, pve_end);1140CP(r32.pve, r.pve, pve_offset);1141CP(r32.pve, r.pve, pve_prot);1142CP(r32.pve, r.pve, pve_pathlen);1143CP(r32.pve, r.pve, pve_fileid);1144CP(r32.pve, r.pve, pve_fsid);1145PTRIN_CP(r32.pve, r.pve, pve_path);1146break;1147case PT_COREDUMP:1148if (uap->data != sizeof(r32.pc))1149error = EINVAL;1150else1151error = copyin(uap->addr, &r32.pc, uap->data);1152CP(r32.pc, r.pc, pc_fd);1153CP(r32.pc, r.pc, pc_flags);1154r.pc.pc_limit = PAIR32TO64(off_t, r32.pc.pc_limit);1155data = sizeof(r.pc);1156break;1157case PT_SC_REMOTE:1158if (uap->data != sizeof(r32.sr)) {1159error = EINVAL;1160break;1161}1162error = copyin(uap->addr, &r32.sr, uap->data);1163if (error != 0)1164break;1165CP(r32.sr, r.sr, pscr_syscall);1166CP(r32.sr, r.sr, pscr_nargs);1167if (r.sr.pscr_nargs > nitems(td->td_sa.args)) {1168error = EINVAL;1169break;1170}1171error = copyin(PTRIN(r32.sr.pscr_args), pscr_args32,1172sizeof(u_int) * r32.sr.pscr_nargs);1173if (error != 0)1174break;1175for (i = 0; i < r32.sr.pscr_nargs; i++)1176pscr_args[i] = pscr_args32[i];1177r.sr.pscr_args = pscr_args;1178break;1179case PTINTERNAL_FIRST ... PTINTERNAL_LAST:1180error = EINVAL;1181break;1182default:1183addr = uap->addr;1184break;1185}1186if (error)1187return (error);11881189error = kern_ptrace(td, uap->req, uap->pid, addr, data);1190if (error)1191return (error);11921193switch (uap->req) {1194case PT_VM_ENTRY:1195CP(r.pve, r32.pve, pve_entry);1196CP(r.pve, r32.pve, pve_timestamp);1197CP(r.pve, r32.pve, pve_start);1198CP(r.pve, r32.pve, pve_end);1199CP(r.pve, r32.pve, pve_offset);1200CP(r.pve, r32.pve, pve_prot);1201CP(r.pve, r32.pve, pve_pathlen);1202CP(r.pve, r32.pve, pve_fileid);1203CP(r.pve, r32.pve, pve_fsid);1204error = copyout(&r32.pve, uap->addr, sizeof(r32.pve));1205break;1206case PT_IO:1207CP(r.piod, r32.piod, piod_len);1208error = copyout(&r32.piod, uap->addr, sizeof(r32.piod));1209break;1210case PT_GETREGS:1211error = copyout(&r.reg, uap->addr, sizeof(r.reg));1212break;1213case PT_GETFPREGS:1214error = copyout(&r.fpreg, uap->addr, sizeof(r.fpreg));1215break;1216case PT_GETDBREGS:1217error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));1218break;1219case PT_GETREGSET:1220r32.vec.iov_len = r.vec.iov_len;1221error = copyout(&r32.vec, uap->addr, sizeof(r32.vec));1222break;1223case PT_GET_EVENT_MASK:1224/* NB: The size in uap->data is validated in kern_ptrace(). */1225error = copyout(&r.ptevents, uap->addr, uap->data);1226break;1227case PT_LWPINFO:1228ptrace_lwpinfo_to32(&r.pl, &r32.pl);1229error = copyout(&r32.pl, uap->addr, uap->data);1230break;1231case PT_GET_SC_ARGS:1232for (i = 0; i < nitems(r.args); i++)1233r32.args[i] = (uint32_t)r.args[i];1234error = copyout(r32.args, uap->addr, MIN(uap->data,1235sizeof(r32.args)));1236break;1237case PT_GET_SC_RET:1238ptrace_sc_ret_to32(&r.psr, &r32.psr);1239error = copyout(&r32.psr, uap->addr, MIN(uap->data,1240sizeof(r32.psr)));1241break;1242case PT_SC_REMOTE:1243ptrace_sc_ret_to32(&r.sr.pscr_ret, &r32.sr.pscr_ret);1244error = copyout(&r32.sr.pscr_ret, uap->addr +1245offsetof(struct ptrace_sc_remote32, pscr_ret),1246sizeof(r32.psr));1247break;1248}12491250return (error);1251}12521253int1254freebsd32_copyinuio(const struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)1255{1256struct iovec32 iov32;1257struct iovec *iov;1258struct uio *uio;1259int error, i;12601261*uiop = NULL;1262if (iovcnt > UIO_MAXIOV)1263return (EINVAL);1264uio = allocuio(iovcnt);1265iov = uio->uio_iov;1266for (i = 0; i < iovcnt; i++) {1267error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));1268if (error) {1269freeuio(uio);1270return (error);1271}1272iov[i].iov_base = PTRIN(iov32.iov_base);1273iov[i].iov_len = iov32.iov_len;1274}1275uio->uio_iovcnt = iovcnt;1276uio->uio_segflg = UIO_USERSPACE;1277uio->uio_offset = -1;1278uio->uio_resid = 0;1279for (i = 0; i < iovcnt; i++) {1280if (iov->iov_len > INT_MAX - uio->uio_resid) {1281freeuio(uio);1282return (EINVAL);1283}1284uio->uio_resid += iov->iov_len;1285iov++;1286}1287*uiop = uio;1288return (0);1289}12901291int1292freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)1293{1294struct uio *auio;1295int error;12961297error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);1298if (error)1299return (error);1300error = kern_readv(td, uap->fd, auio);1301freeuio(auio);1302return (error);1303}13041305int1306freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)1307{1308struct uio *auio;1309int error;13101311error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);1312if (error)1313return (error);1314error = kern_writev(td, uap->fd, auio);1315freeuio(auio);1316return (error);1317}13181319int1320freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)1321{1322struct uio *auio;1323int error;13241325error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);1326if (error)1327return (error);1328error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));1329freeuio(auio);1330return (error);1331}13321333int1334freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)1335{1336struct uio *auio;1337int error;13381339error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);1340if (error)1341return (error);1342error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));1343freeuio(auio);1344return (error);1345}13461347int1348freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,1349int error)1350{1351struct iovec32 iov32;1352struct iovec *iov;1353u_int iovlen;1354int i;13551356*iovp = NULL;1357if (iovcnt > UIO_MAXIOV)1358return (error);1359iovlen = iovcnt * sizeof(struct iovec);1360iov = malloc(iovlen, M_IOV, M_WAITOK);1361for (i = 0; i < iovcnt; i++) {1362error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));1363if (error) {1364free(iov, M_IOV);1365return (error);1366}1367iov[i].iov_base = PTRIN(iov32.iov_base);1368iov[i].iov_len = iov32.iov_len;1369}1370*iovp = iov;1371return (0);1372}13731374static int1375freebsd32_copyinmsghdr(const struct msghdr32 *msg32, struct msghdr *msg)1376{1377struct msghdr32 m32;1378int error;13791380error = copyin(msg32, &m32, sizeof(m32));1381if (error)1382return (error);1383msg->msg_name = PTRIN(m32.msg_name);1384msg->msg_namelen = m32.msg_namelen;1385msg->msg_iov = PTRIN(m32.msg_iov);1386msg->msg_iovlen = m32.msg_iovlen;1387msg->msg_control = PTRIN(m32.msg_control);1388msg->msg_controllen = m32.msg_controllen;1389msg->msg_flags = m32.msg_flags;1390return (0);1391}13921393static int1394freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)1395{1396struct msghdr32 m32;1397int error;13981399m32.msg_name = PTROUT(msg->msg_name);1400m32.msg_namelen = msg->msg_namelen;1401m32.msg_iov = PTROUT(msg->msg_iov);1402m32.msg_iovlen = msg->msg_iovlen;1403m32.msg_control = PTROUT(msg->msg_control);1404m32.msg_controllen = msg->msg_controllen;1405m32.msg_flags = msg->msg_flags;1406error = copyout(&m32, msg32, sizeof(m32));1407return (error);1408}14091410#define FREEBSD32_ALIGNBYTES (sizeof(int) - 1)1411#define FREEBSD32_ALIGN(p) \1412(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)1413#define FREEBSD32_CMSG_SPACE(l) \1414(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))14151416#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \1417FREEBSD32_ALIGN(sizeof(struct cmsghdr)))14181419static size_t1420freebsd32_cmsg_convert(const struct cmsghdr *cm, void *data, socklen_t datalen)1421{1422size_t copylen;1423union {1424struct timespec32 ts;1425struct timeval32 tv;1426struct bintime32 bt;1427} tmp32;14281429union {1430struct timespec ts;1431struct timeval tv;1432struct bintime bt;1433} *in;14341435in = data;1436copylen = 0;1437switch (cm->cmsg_level) {1438case SOL_SOCKET:1439switch (cm->cmsg_type) {1440case SCM_TIMESTAMP:1441TV_CP(*in, tmp32, tv);1442copylen = sizeof(tmp32.tv);1443break;14441445case SCM_BINTIME:1446BT_CP(*in, tmp32, bt);1447copylen = sizeof(tmp32.bt);1448break;14491450case SCM_REALTIME:1451case SCM_MONOTONIC:1452TS_CP(*in, tmp32, ts);1453copylen = sizeof(tmp32.ts);1454break;14551456default:1457break;1458}14591460default:1461break;1462}14631464if (copylen == 0)1465return (datalen);14661467KASSERT((datalen >= copylen), ("corrupted cmsghdr"));14681469bcopy(&tmp32, data, copylen);1470return (copylen);1471}14721473static int1474freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)1475{1476struct cmsghdr *cm;1477void *data;1478socklen_t clen, datalen, datalen_out, oldclen;1479int error;1480caddr_t ctlbuf;1481int len, copylen;1482struct mbuf *m;1483error = 0;14841485len = msg->msg_controllen;1486msg->msg_controllen = 0;14871488ctlbuf = msg->msg_control;1489for (m = control; m != NULL && len > 0; m = m->m_next) {1490cm = mtod(m, struct cmsghdr *);1491clen = m->m_len;1492while (cm != NULL) {1493if (sizeof(struct cmsghdr) > clen ||1494cm->cmsg_len > clen) {1495error = EINVAL;1496break;1497}14981499data = CMSG_DATA(cm);1500datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;1501datalen_out = freebsd32_cmsg_convert(cm, data, datalen);15021503/*1504* Copy out the message header. Preserve the native1505* message size in case we need to inspect the message1506* contents later.1507*/1508copylen = sizeof(struct cmsghdr);1509if (len < copylen) {1510msg->msg_flags |= MSG_CTRUNC;1511m_dispose_extcontrolm(m);1512goto exit;1513}1514oldclen = cm->cmsg_len;1515cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +1516datalen_out;1517error = copyout(cm, ctlbuf, copylen);1518cm->cmsg_len = oldclen;1519if (error != 0)1520goto exit;15211522ctlbuf += FREEBSD32_ALIGN(copylen);1523len -= FREEBSD32_ALIGN(copylen);15241525copylen = datalen_out;1526if (len < copylen) {1527msg->msg_flags |= MSG_CTRUNC;1528m_dispose_extcontrolm(m);1529break;1530}15311532/* Copy out the message data. */1533error = copyout(data, ctlbuf, copylen);1534if (error)1535goto exit;15361537ctlbuf += FREEBSD32_ALIGN(copylen);1538len -= FREEBSD32_ALIGN(copylen);15391540if (CMSG_SPACE(datalen) < clen) {1541clen -= CMSG_SPACE(datalen);1542cm = (struct cmsghdr *)1543((caddr_t)cm + CMSG_SPACE(datalen));1544} else {1545clen = 0;1546cm = NULL;1547}15481549msg->msg_controllen +=1550FREEBSD32_CMSG_SPACE(datalen_out);1551}1552}1553if (len == 0 && m != NULL) {1554msg->msg_flags |= MSG_CTRUNC;1555m_dispose_extcontrolm(m);1556}15571558exit:1559return (error);1560}15611562int1563freebsd32_recvmsg(struct thread *td, struct freebsd32_recvmsg_args *uap)1564{1565struct msghdr msg;1566struct iovec *uiov, *iov;1567struct mbuf *control = NULL;1568struct mbuf **controlp;1569int error;15701571error = freebsd32_copyinmsghdr(uap->msg, &msg);1572if (error)1573return (error);1574error = freebsd32_copyiniov((void *)msg.msg_iov, msg.msg_iovlen, &iov,1575EMSGSIZE);1576if (error)1577return (error);1578msg.msg_flags = uap->flags;1579uiov = msg.msg_iov;1580msg.msg_iov = iov;15811582controlp = (msg.msg_control != NULL) ? &control : NULL;1583error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);1584if (error == 0) {1585msg.msg_iov = uiov;15861587if (control != NULL)1588error = freebsd32_copy_msg_out(&msg, control);1589else1590msg.msg_controllen = 0;15911592if (error == 0)1593error = freebsd32_copyoutmsghdr(&msg, uap->msg);1594}1595free(iov, M_IOV);15961597if (control != NULL) {1598if (error != 0)1599m_dispose_extcontrolm(control);1600m_freem(control);1601}16021603return (error);1604}16051606#ifdef COMPAT_431607int1608ofreebsd32_recvmsg(struct thread *td, struct ofreebsd32_recvmsg_args *uap)1609{1610return (ENOSYS);1611}1612#endif16131614/*1615* Copy-in the array of control messages constructed using alignment1616* and padding suitable for a 32-bit environment and construct an1617* mbuf using alignment and padding suitable for a 64-bit kernel.1618* The alignment and padding are defined indirectly by CMSG_DATA(),1619* CMSG_SPACE() and CMSG_LEN().1620*/1621static int1622freebsd32_copyin_control(struct mbuf **mp, caddr_t buf, u_int buflen)1623{1624struct cmsghdr *cm;1625struct mbuf *m;1626void *in, *in1, *md;1627u_int msglen, outlen;1628int error;16291630/* Enforce the size limit of the native implementation. */1631if (buflen > MCLBYTES)1632return (EINVAL);16331634in = malloc(buflen, M_TEMP, M_WAITOK);1635error = copyin(buf, in, buflen);1636if (error != 0)1637goto out;16381639/*1640* Make a pass over the input buffer to determine the amount of space1641* required for 64 bit-aligned copies of the control messages.1642*/1643in1 = in;1644outlen = 0;1645while (buflen > 0) {1646if (buflen < sizeof(*cm)) {1647error = EINVAL;1648break;1649}1650cm = (struct cmsghdr *)in1;1651if (cm->cmsg_len < FREEBSD32_ALIGN(sizeof(*cm)) ||1652cm->cmsg_len > buflen) {1653error = EINVAL;1654break;1655}1656msglen = FREEBSD32_ALIGN(cm->cmsg_len);1657if (msglen < cm->cmsg_len) {1658error = EINVAL;1659break;1660}1661/* The native ABI permits the final padding to be omitted. */1662if (msglen > buflen)1663msglen = buflen;1664buflen -= msglen;16651666in1 = (char *)in1 + msglen;1667outlen += CMSG_ALIGN(sizeof(*cm)) +1668CMSG_ALIGN(msglen - FREEBSD32_ALIGN(sizeof(*cm)));1669}1670if (error != 0)1671goto out;16721673/*1674* Allocate up to MJUMPAGESIZE space for the re-aligned and1675* re-padded control messages. This allows a full MCLBYTES of1676* 32-bit sized and aligned messages to fit and avoids an ABI1677* mismatch with the native implementation.1678*/1679m = m_get2(outlen, M_WAITOK, MT_CONTROL, 0);1680if (m == NULL) {1681error = EINVAL;1682goto out;1683}1684m->m_len = outlen;1685md = mtod(m, void *);16861687/*1688* Make a second pass over input messages, copying them into the output1689* buffer.1690*/1691in1 = in;1692while (outlen > 0) {1693/* Copy the message header and align the length field. */1694cm = md;1695memcpy(cm, in1, sizeof(*cm));1696msglen = cm->cmsg_len - FREEBSD32_ALIGN(sizeof(*cm));1697cm->cmsg_len = CMSG_ALIGN(sizeof(*cm)) + msglen;16981699/* Copy the message body. */1700in1 = (char *)in1 + FREEBSD32_ALIGN(sizeof(*cm));1701md = (char *)md + CMSG_ALIGN(sizeof(*cm));1702memcpy(md, in1, msglen);1703in1 = (char *)in1 + FREEBSD32_ALIGN(msglen);1704md = (char *)md + CMSG_ALIGN(msglen);1705KASSERT(outlen >= CMSG_ALIGN(sizeof(*cm)) + CMSG_ALIGN(msglen),1706("outlen %u underflow, msglen %u", outlen, msglen));1707outlen -= CMSG_ALIGN(sizeof(*cm)) + CMSG_ALIGN(msglen);1708}17091710*mp = m;1711out:1712free(in, M_TEMP);1713return (error);1714}17151716int1717freebsd32_sendmsg(struct thread *td, struct freebsd32_sendmsg_args *uap)1718{1719struct msghdr msg;1720struct iovec *iov;1721struct mbuf *control = NULL;1722struct sockaddr *to = NULL;1723int error;17241725error = freebsd32_copyinmsghdr(uap->msg, &msg);1726if (error)1727return (error);1728error = freebsd32_copyiniov((void *)msg.msg_iov, msg.msg_iovlen, &iov,1729EMSGSIZE);1730if (error)1731return (error);1732msg.msg_iov = iov;1733if (msg.msg_name != NULL) {1734error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);1735if (error) {1736to = NULL;1737goto out;1738}1739msg.msg_name = to;1740}17411742if (msg.msg_control) {1743if (msg.msg_controllen < sizeof(struct cmsghdr)) {1744error = EINVAL;1745goto out;1746}17471748error = freebsd32_copyin_control(&control, msg.msg_control,1749msg.msg_controllen);1750if (error)1751goto out;17521753msg.msg_control = NULL;1754msg.msg_controllen = 0;1755}17561757error = kern_sendit(td, uap->s, &msg, uap->flags, control,1758UIO_USERSPACE);17591760out:1761free(iov, M_IOV);1762if (to)1763free(to, M_SONAME);1764return (error);1765}17661767#ifdef COMPAT_431768int1769ofreebsd32_sendmsg(struct thread *td, struct ofreebsd32_sendmsg_args *uap)1770{1771return (ENOSYS);1772}1773#endif177417751776int1777freebsd32_settimeofday(struct thread *td,1778struct freebsd32_settimeofday_args *uap)1779{1780struct timeval32 tv32;1781struct timeval tv, *tvp;1782struct timezone tz, *tzp;1783int error;17841785if (uap->tv) {1786error = copyin(uap->tv, &tv32, sizeof(tv32));1787if (error)1788return (error);1789CP(tv32, tv, tv_sec);1790CP(tv32, tv, tv_usec);1791tvp = &tv;1792} else1793tvp = NULL;1794if (uap->tzp) {1795error = copyin(uap->tzp, &tz, sizeof(tz));1796if (error)1797return (error);1798tzp = &tz;1799} else1800tzp = NULL;1801return (kern_settimeofday(td, tvp, tzp));1802}18031804int1805freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)1806{1807struct timeval32 s32[2];1808struct timeval s[2], *sp;1809int error;18101811if (uap->tptr != NULL) {1812error = copyin(uap->tptr, s32, sizeof(s32));1813if (error)1814return (error);1815CP(s32[0], s[0], tv_sec);1816CP(s32[0], s[0], tv_usec);1817CP(s32[1], s[1], tv_sec);1818CP(s32[1], s[1], tv_usec);1819sp = s;1820} else1821sp = NULL;1822return (kern_utimesat(td, AT_FDCWD, uap->path, UIO_USERSPACE,1823sp, UIO_SYSSPACE));1824}18251826int1827freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)1828{1829struct timeval32 s32[2];1830struct timeval s[2], *sp;1831int error;18321833if (uap->tptr != NULL) {1834error = copyin(uap->tptr, s32, sizeof(s32));1835if (error)1836return (error);1837CP(s32[0], s[0], tv_sec);1838CP(s32[0], s[0], tv_usec);1839CP(s32[1], s[1], tv_sec);1840CP(s32[1], s[1], tv_usec);1841sp = s;1842} else1843sp = NULL;1844return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));1845}18461847int1848freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)1849{1850struct timeval32 s32[2];1851struct timeval s[2], *sp;1852int error;18531854if (uap->tptr != NULL) {1855error = copyin(uap->tptr, s32, sizeof(s32));1856if (error)1857return (error);1858CP(s32[0], s[0], tv_sec);1859CP(s32[0], s[0], tv_usec);1860CP(s32[1], s[1], tv_sec);1861CP(s32[1], s[1], tv_usec);1862sp = s;1863} else1864sp = NULL;1865return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));1866}18671868int1869freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)1870{1871struct timeval32 s32[2];1872struct timeval s[2], *sp;1873int error;18741875if (uap->times != NULL) {1876error = copyin(uap->times, s32, sizeof(s32));1877if (error)1878return (error);1879CP(s32[0], s[0], tv_sec);1880CP(s32[0], s[0], tv_usec);1881CP(s32[1], s[1], tv_sec);1882CP(s32[1], s[1], tv_usec);1883sp = s;1884} else1885sp = NULL;1886return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,1887sp, UIO_SYSSPACE));1888}18891890int1891freebsd32_futimens(struct thread *td, struct freebsd32_futimens_args *uap)1892{1893struct timespec32 ts32[2];1894struct timespec ts[2], *tsp;1895int error;18961897if (uap->times != NULL) {1898error = copyin(uap->times, ts32, sizeof(ts32));1899if (error)1900return (error);1901CP(ts32[0], ts[0], tv_sec);1902CP(ts32[0], ts[0], tv_nsec);1903CP(ts32[1], ts[1], tv_sec);1904CP(ts32[1], ts[1], tv_nsec);1905tsp = ts;1906} else1907tsp = NULL;1908return (kern_futimens(td, uap->fd, tsp, UIO_SYSSPACE));1909}19101911int1912freebsd32_utimensat(struct thread *td, struct freebsd32_utimensat_args *uap)1913{1914struct timespec32 ts32[2];1915struct timespec ts[2], *tsp;1916int error;19171918if (uap->times != NULL) {1919error = copyin(uap->times, ts32, sizeof(ts32));1920if (error)1921return (error);1922CP(ts32[0], ts[0], tv_sec);1923CP(ts32[0], ts[0], tv_nsec);1924CP(ts32[1], ts[1], tv_sec);1925CP(ts32[1], ts[1], tv_nsec);1926tsp = ts;1927} else1928tsp = NULL;1929return (kern_utimensat(td, uap->fd, uap->path, UIO_USERSPACE,1930tsp, UIO_SYSSPACE, uap->flag));1931}19321933int1934freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)1935{1936struct timeval32 tv32;1937struct timeval delta, olddelta, *deltap;1938int error;19391940if (uap->delta) {1941error = copyin(uap->delta, &tv32, sizeof(tv32));1942if (error)1943return (error);1944CP(tv32, delta, tv_sec);1945CP(tv32, delta, tv_usec);1946deltap = δ1947} else1948deltap = NULL;1949error = kern_adjtime(td, deltap, &olddelta);1950if (uap->olddelta && error == 0) {1951CP(olddelta, tv32, tv_sec);1952CP(olddelta, tv32, tv_usec);1953error = copyout(&tv32, uap->olddelta, sizeof(tv32));1954}1955return (error);1956}19571958#ifdef COMPAT_FREEBSD41959int1960freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)1961{1962struct ostatfs32 s32;1963struct statfs *sp;1964int error;19651966sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);1967error = kern_statfs(td, uap->path, UIO_USERSPACE, 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_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)1980{1981struct ostatfs32 s32;1982struct statfs *sp;1983int error;19841985sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);1986error = kern_fstatfs(td, uap->fd, sp);1987if (error == 0) {1988copy_statfs(sp, &s32);1989error = copyout(&s32, uap->buf, sizeof(s32));1990}1991free(sp, M_STATFS);1992return (error);1993}1994#endif19951996#ifdef COMPAT_FREEBSD41997int1998freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)1999{2000struct ostatfs32 s32;2001struct statfs *sp;2002fhandle_t fh;2003int error;20042005if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)2006return (error);2007sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);2008error = kern_fhstatfs(td, fh, sp);2009if (error == 0) {2010copy_statfs(sp, &s32);2011error = copyout(&s32, uap->buf, sizeof(s32));2012}2013free(sp, M_STATFS);2014return (error);2015}2016#endif20172018int2019freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)2020{20212022return (kern_pread(td, uap->fd, uap->buf, uap->nbyte,2023PAIR32TO64(off_t, uap->offset)));2024}20252026int2027freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)2028{20292030return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte,2031PAIR32TO64(off_t, uap->offset)));2032}20332034#ifdef COMPAT_432035int2036ofreebsd32_lseek(struct thread *td, struct ofreebsd32_lseek_args *uap)2037{20382039return (kern_lseek(td, uap->fd, uap->offset, uap->whence));2040}2041#endif20422043int2044freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)2045{2046int error;2047off_t pos;20482049error = kern_lseek(td, uap->fd, PAIR32TO64(off_t, uap->offset),2050uap->whence);2051/* Expand the quad return into two parts for eax and edx */2052pos = td->td_uretoff.tdu_off;2053td->td_retval[RETVAL_LO] = pos & 0xffffffff; /* %eax */2054td->td_retval[RETVAL_HI] = pos >> 32; /* %edx */2055return error;2056}20572058int2059freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)2060{20612062return (kern_truncate(td, uap->path, UIO_USERSPACE,2063PAIR32TO64(off_t, uap->length)));2064}20652066#ifdef COMPAT_432067int2068ofreebsd32_truncate(struct thread *td, struct ofreebsd32_truncate_args *uap)2069{2070return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));2071}2072#endif20732074int2075freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)2076{20772078return (kern_ftruncate(td, uap->fd, PAIR32TO64(off_t, uap->length)));2079}20802081#ifdef COMPAT_432082int2083ofreebsd32_ftruncate(struct thread *td, struct ofreebsd32_ftruncate_args *uap)2084{2085return (kern_ftruncate(td, uap->fd, uap->length));2086}20872088int2089ofreebsd32_getdirentries(struct thread *td,2090struct ofreebsd32_getdirentries_args *uap)2091{2092struct ogetdirentries_args ap;2093int error;2094long loff;2095int32_t loff_cut;20962097ap.fd = uap->fd;2098ap.buf = uap->buf;2099ap.count = uap->count;2100ap.basep = NULL;2101error = kern_ogetdirentries(td, &ap, &loff);2102if (error == 0) {2103loff_cut = loff;2104error = copyout(&loff_cut, uap->basep, sizeof(int32_t));2105}2106return (error);2107}2108#endif21092110#if defined(COMPAT_FREEBSD11)2111int2112freebsd11_freebsd32_getdirentries(struct thread *td,2113struct freebsd11_freebsd32_getdirentries_args *uap)2114{2115long base;2116int32_t base32;2117int error;21182119error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,2120&base, NULL);2121if (error)2122return (error);2123if (uap->basep != NULL) {2124base32 = base;2125error = copyout(&base32, uap->basep, sizeof(int32_t));2126}2127return (error);2128}2129#endif /* COMPAT_FREEBSD11 */21302131#ifdef COMPAT_FREEBSD62132/* versions with the 'int pad' argument */2133int2134freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)2135{21362137return (kern_pread(td, uap->fd, uap->buf, uap->nbyte,2138PAIR32TO64(off_t, uap->offset)));2139}21402141int2142freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)2143{21442145return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte,2146PAIR32TO64(off_t, uap->offset)));2147}21482149int2150freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)2151{2152int error;2153off_t pos;21542155error = kern_lseek(td, uap->fd, PAIR32TO64(off_t, uap->offset),2156uap->whence);2157/* Expand the quad return into two parts for eax and edx */2158pos = *(off_t *)(td->td_retval);2159td->td_retval[RETVAL_LO] = pos & 0xffffffff; /* %eax */2160td->td_retval[RETVAL_HI] = pos >> 32; /* %edx */2161return error;2162}21632164int2165freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)2166{21672168return (kern_truncate(td, uap->path, UIO_USERSPACE,2169PAIR32TO64(off_t, uap->length)));2170}21712172int2173freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)2174{21752176return (kern_ftruncate(td, uap->fd, PAIR32TO64(off_t, uap->length)));2177}2178#endif /* COMPAT_FREEBSD6 */21792180struct sf_hdtr32 {2181uint32_t headers;2182int hdr_cnt;2183uint32_t trailers;2184int trl_cnt;2185};21862187static int2188freebsd32_do_sendfile(struct thread *td,2189struct freebsd32_sendfile_args *uap, int compat)2190{2191struct sf_hdtr32 hdtr32;2192struct sf_hdtr hdtr;2193struct uio *hdr_uio, *trl_uio;2194struct file *fp;2195cap_rights_t rights;2196struct iovec32 *iov32;2197off_t offset, sbytes;2198int error;21992200offset = PAIR32TO64(off_t, uap->offset);2201if (offset < 0)2202return (EINVAL);22032204hdr_uio = trl_uio = NULL;22052206if (uap->hdtr != NULL) {2207error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));2208if (error)2209goto out;2210PTRIN_CP(hdtr32, hdtr, headers);2211CP(hdtr32, hdtr, hdr_cnt);2212PTRIN_CP(hdtr32, hdtr, trailers);2213CP(hdtr32, hdtr, trl_cnt);22142215if (hdtr.headers != NULL) {2216iov32 = PTRIN(hdtr32.headers);2217error = freebsd32_copyinuio(iov32,2218hdtr32.hdr_cnt, &hdr_uio);2219if (error)2220goto out;2221#ifdef COMPAT_FREEBSD42222/*2223* In FreeBSD < 5.0 the nbytes to send also included2224* the header. If compat is specified subtract the2225* header size from nbytes.2226*/2227if (compat) {2228if (uap->nbytes > hdr_uio->uio_resid)2229uap->nbytes -= hdr_uio->uio_resid;2230else2231uap->nbytes = 0;2232}2233#endif2234}2235if (hdtr.trailers != NULL) {2236iov32 = PTRIN(hdtr32.trailers);2237error = freebsd32_copyinuio(iov32,2238hdtr32.trl_cnt, &trl_uio);2239if (error)2240goto out;2241}2242}22432244AUDIT_ARG_FD(uap->fd);22452246if ((error = fget_read(td, uap->fd,2247cap_rights_init_one(&rights, CAP_PREAD), &fp)) != 0)2248goto out;22492250error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, offset,2251uap->nbytes, &sbytes, uap->flags, td);2252fdrop(fp, td);22532254if (uap->sbytes != NULL)2255(void)copyout(&sbytes, uap->sbytes, sizeof(off_t));22562257out:2258if (hdr_uio)2259freeuio(hdr_uio);2260if (trl_uio)2261freeuio(trl_uio);2262return (error);2263}22642265#ifdef COMPAT_FREEBSD42266int2267freebsd4_freebsd32_sendfile(struct thread *td,2268struct freebsd4_freebsd32_sendfile_args *uap)2269{2270return (freebsd32_do_sendfile(td,2271(struct freebsd32_sendfile_args *)uap, 1));2272}2273#endif22742275int2276freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)2277{22782279return (freebsd32_do_sendfile(td, uap, 0));2280}22812282static void2283copy_stat(struct stat *in, struct stat32 *out)2284{22852286#ifndef __amd64__2287/*2288* 32-bit architectures other than i386 have 64-bit time_t. This2289* results in struct timespec32 with 12 bytes for tv_sec and tv_nsec,2290* and 4 bytes of padding. Zero the padding holes in struct stat32.2291*/2292bzero(&out->st_atim, sizeof(out->st_atim));2293bzero(&out->st_mtim, sizeof(out->st_mtim));2294bzero(&out->st_ctim, sizeof(out->st_ctim));2295bzero(&out->st_birthtim, sizeof(out->st_birthtim));2296#endif2297CP(*in, *out, st_dev);2298CP(*in, *out, st_ino);2299CP(*in, *out, st_mode);2300CP(*in, *out, st_nlink);2301CP(*in, *out, st_uid);2302CP(*in, *out, st_gid);2303CP(*in, *out, st_rdev);2304TS_CP(*in, *out, st_atim);2305TS_CP(*in, *out, st_mtim);2306TS_CP(*in, *out, st_ctim);2307CP(*in, *out, st_size);2308CP(*in, *out, st_blocks);2309CP(*in, *out, st_blksize);2310CP(*in, *out, st_flags);2311CP(*in, *out, st_gen);2312CP(*in, *out, st_filerev);2313CP(*in, *out, st_bsdflags);2314TS_CP(*in, *out, st_birthtim);2315out->st_padding1 = 0;2316#ifdef __STAT32_TIME_T_EXT2317out->st_atim_ext = 0;2318out->st_mtim_ext = 0;2319out->st_ctim_ext = 0;2320out->st_btim_ext = 0;2321#endif2322bzero(out->st_spare, sizeof(out->st_spare));2323}23242325#ifdef COMPAT_432326static void2327copy_ostat(struct stat *in, struct ostat32 *out)2328{23292330bzero(out, sizeof(*out));2331CP(*in, *out, st_dev);2332CP(*in, *out, st_ino);2333CP(*in, *out, st_mode);2334CP(*in, *out, st_nlink);2335CP(*in, *out, st_uid);2336CP(*in, *out, st_gid);2337CP(*in, *out, st_rdev);2338out->st_size = MIN(in->st_size, INT32_MAX);2339TS_CP(*in, *out, st_atim);2340TS_CP(*in, *out, st_mtim);2341TS_CP(*in, *out, st_ctim);2342CP(*in, *out, st_blksize);2343CP(*in, *out, st_blocks);2344CP(*in, *out, st_flags);2345CP(*in, *out, st_gen);2346}2347#endif23482349#ifdef COMPAT_432350int2351ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)2352{2353struct stat sb;2354struct ostat32 sb32;2355int error;23562357error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);2358if (error)2359return (error);2360copy_ostat(&sb, &sb32);2361error = copyout(&sb32, uap->ub, sizeof (sb32));2362return (error);2363}2364#endif23652366int2367freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)2368{2369struct stat ub;2370struct stat32 ub32;2371int error;23722373error = kern_fstat(td, uap->fd, &ub);2374if (error)2375return (error);2376copy_stat(&ub, &ub32);2377error = copyout(&ub32, uap->sb, sizeof(ub32));2378return (error);2379}23802381#ifdef COMPAT_432382int2383ofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap)2384{2385struct stat ub;2386struct ostat32 ub32;2387int error;23882389error = kern_fstat(td, uap->fd, &ub);2390if (error)2391return (error);2392copy_ostat(&ub, &ub32);2393error = copyout(&ub32, uap->sb, sizeof(ub32));2394return (error);2395}2396#endif23972398int2399freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)2400{2401struct stat ub;2402struct stat32 ub32;2403int error;24042405error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE,2406&ub);2407if (error)2408return (error);2409copy_stat(&ub, &ub32);2410error = copyout(&ub32, uap->buf, sizeof(ub32));2411return (error);2412}24132414#ifdef COMPAT_432415int2416ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)2417{2418struct stat sb;2419struct ostat32 sb32;2420int error;24212422error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,2423UIO_USERSPACE, &sb);2424if (error)2425return (error);2426copy_ostat(&sb, &sb32);2427error = copyout(&sb32, uap->ub, sizeof (sb32));2428return (error);2429}2430#endif24312432int2433freebsd32_fhstat(struct thread *td, struct freebsd32_fhstat_args *uap)2434{2435struct stat sb;2436struct stat32 sb32;2437struct fhandle fh;2438int error;24392440error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));2441if (error != 0)2442return (error);2443error = kern_fhstat(td, fh, &sb);2444if (error != 0)2445return (error);2446copy_stat(&sb, &sb32);2447error = copyout(&sb32, uap->sb, sizeof (sb32));2448return (error);2449}24502451#if defined(COMPAT_FREEBSD11)2452extern int ino64_trunc_error;24532454static int2455freebsd11_cvtstat32(struct stat *in, struct freebsd11_stat32 *out)2456{24572458#ifndef __amd64__2459/*2460* 32-bit architectures other than i386 have 64-bit time_t. This2461* results in struct timespec32 with 12 bytes for tv_sec and tv_nsec,2462* and 4 bytes of padding. Zero the padding holes in freebsd11_stat32.2463*/2464bzero(&out->st_atim, sizeof(out->st_atim));2465bzero(&out->st_mtim, sizeof(out->st_mtim));2466bzero(&out->st_ctim, sizeof(out->st_ctim));2467bzero(&out->st_birthtim, sizeof(out->st_birthtim));2468#endif24692470CP(*in, *out, st_ino);2471if (in->st_ino != out->st_ino) {2472switch (ino64_trunc_error) {2473default:2474case 0:2475break;2476case 1:2477return (EOVERFLOW);2478case 2:2479out->st_ino = UINT32_MAX;2480break;2481}2482}2483CP(*in, *out, st_nlink);2484if (in->st_nlink != out->st_nlink) {2485switch (ino64_trunc_error) {2486default:2487case 0:2488break;2489case 1:2490return (EOVERFLOW);2491case 2:2492out->st_nlink = UINT16_MAX;2493break;2494}2495}2496out->st_dev = in->st_dev;2497if (out->st_dev != in->st_dev) {2498switch (ino64_trunc_error) {2499default:2500break;2501case 1:2502return (EOVERFLOW);2503}2504}2505CP(*in, *out, st_mode);2506CP(*in, *out, st_uid);2507CP(*in, *out, st_gid);2508out->st_rdev = in->st_rdev;2509if (out->st_rdev != in->st_rdev) {2510switch (ino64_trunc_error) {2511default:2512break;2513case 1:2514return (EOVERFLOW);2515}2516}2517TS_CP(*in, *out, st_atim);2518TS_CP(*in, *out, st_mtim);2519TS_CP(*in, *out, st_ctim);2520CP(*in, *out, st_size);2521CP(*in, *out, st_blocks);2522CP(*in, *out, st_blksize);2523CP(*in, *out, st_flags);2524CP(*in, *out, st_gen);2525TS_CP(*in, *out, st_birthtim);2526out->st_lspare = 0;2527bzero((char *)&out->st_birthtim + sizeof(out->st_birthtim),2528sizeof(*out) - offsetof(struct freebsd11_stat32,2529st_birthtim) - sizeof(out->st_birthtim));2530return (0);2531}25322533int2534freebsd11_freebsd32_stat(struct thread *td,2535struct freebsd11_freebsd32_stat_args *uap)2536{2537struct stat sb;2538struct freebsd11_stat32 sb32;2539int error;25402541error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);2542if (error != 0)2543return (error);2544error = freebsd11_cvtstat32(&sb, &sb32);2545if (error == 0)2546error = copyout(&sb32, uap->ub, sizeof (sb32));2547return (error);2548}25492550int2551freebsd11_freebsd32_fstat(struct thread *td,2552struct freebsd11_freebsd32_fstat_args *uap)2553{2554struct stat sb;2555struct freebsd11_stat32 sb32;2556int error;25572558error = kern_fstat(td, uap->fd, &sb);2559if (error != 0)2560return (error);2561error = freebsd11_cvtstat32(&sb, &sb32);2562if (error == 0)2563error = copyout(&sb32, uap->sb, sizeof (sb32));2564return (error);2565}25662567int2568freebsd11_freebsd32_fstatat(struct thread *td,2569struct freebsd11_freebsd32_fstatat_args *uap)2570{2571struct stat sb;2572struct freebsd11_stat32 sb32;2573int error;25742575error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE,2576&sb);2577if (error != 0)2578return (error);2579error = freebsd11_cvtstat32(&sb, &sb32);2580if (error == 0)2581error = copyout(&sb32, uap->buf, sizeof (sb32));2582return (error);2583}25842585int2586freebsd11_freebsd32_lstat(struct thread *td,2587struct freebsd11_freebsd32_lstat_args *uap)2588{2589struct stat sb;2590struct freebsd11_stat32 sb32;2591int error;25922593error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,2594UIO_USERSPACE, &sb);2595if (error != 0)2596return (error);2597error = freebsd11_cvtstat32(&sb, &sb32);2598if (error == 0)2599error = copyout(&sb32, uap->ub, sizeof (sb32));2600return (error);2601}26022603int2604freebsd11_freebsd32_fhstat(struct thread *td,2605struct freebsd11_freebsd32_fhstat_args *uap)2606{2607struct stat sb;2608struct freebsd11_stat32 sb32;2609struct fhandle fh;2610int error;26112612error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));2613if (error != 0)2614return (error);2615error = kern_fhstat(td, fh, &sb);2616if (error != 0)2617return (error);2618error = freebsd11_cvtstat32(&sb, &sb32);2619if (error == 0)2620error = copyout(&sb32, uap->sb, sizeof (sb32));2621return (error);2622}26232624static int2625freebsd11_cvtnstat32(struct stat *sb, struct nstat32 *nsb32)2626{2627struct nstat nsb;2628int error;26292630error = freebsd11_cvtnstat(sb, &nsb);2631if (error != 0)2632return (error);26332634bzero(nsb32, sizeof(*nsb32));2635CP(nsb, *nsb32, st_dev);2636CP(nsb, *nsb32, st_ino);2637CP(nsb, *nsb32, st_mode);2638CP(nsb, *nsb32, st_nlink);2639CP(nsb, *nsb32, st_uid);2640CP(nsb, *nsb32, st_gid);2641CP(nsb, *nsb32, st_rdev);2642CP(nsb, *nsb32, st_atim.tv_sec);2643CP(nsb, *nsb32, st_atim.tv_nsec);2644CP(nsb, *nsb32, st_mtim.tv_sec);2645CP(nsb, *nsb32, st_mtim.tv_nsec);2646CP(nsb, *nsb32, st_ctim.tv_sec);2647CP(nsb, *nsb32, st_ctim.tv_nsec);2648CP(nsb, *nsb32, st_size);2649CP(nsb, *nsb32, st_blocks);2650CP(nsb, *nsb32, st_blksize);2651CP(nsb, *nsb32, st_flags);2652CP(nsb, *nsb32, st_gen);2653CP(nsb, *nsb32, st_birthtim.tv_sec);2654CP(nsb, *nsb32, st_birthtim.tv_nsec);2655return (0);2656}26572658int2659freebsd11_freebsd32_nstat(struct thread *td,2660struct freebsd11_freebsd32_nstat_args *uap)2661{2662struct stat sb;2663struct nstat32 nsb;2664int error;26652666error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);2667if (error != 0)2668return (error);2669error = freebsd11_cvtnstat32(&sb, &nsb);2670if (error != 0)2671error = copyout(&nsb, uap->ub, sizeof (nsb));2672return (error);2673}26742675int2676freebsd11_freebsd32_nlstat(struct thread *td,2677struct freebsd11_freebsd32_nlstat_args *uap)2678{2679struct stat sb;2680struct nstat32 nsb;2681int error;26822683error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,2684UIO_USERSPACE, &sb);2685if (error != 0)2686return (error);2687error = freebsd11_cvtnstat32(&sb, &nsb);2688if (error == 0)2689error = copyout(&nsb, uap->ub, sizeof (nsb));2690return (error);2691}26922693int2694freebsd11_freebsd32_nfstat(struct thread *td,2695struct freebsd11_freebsd32_nfstat_args *uap)2696{2697struct nstat32 nub;2698struct stat ub;2699int error;27002701error = kern_fstat(td, uap->fd, &ub);2702if (error != 0)2703return (error);2704error = freebsd11_cvtnstat32(&ub, &nub);2705if (error == 0)2706error = copyout(&nub, uap->sb, sizeof(nub));2707return (error);2708}2709#endif27102711int2712freebsd32___sysctl(struct thread *td, struct freebsd32___sysctl_args *uap)2713{2714int error, name[CTL_MAXNAME];2715size_t j, oldlen;2716uint32_t tmp;27172718if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)2719return (EINVAL);2720error = copyin(uap->name, name, uap->namelen * sizeof(int));2721if (error)2722return (error);2723if (uap->oldlenp) {2724error = fueword32(uap->oldlenp, &tmp);2725oldlen = tmp;2726} else {2727oldlen = 0;2728}2729if (error != 0)2730return (EFAULT);2731error = userland_sysctl(td, name, uap->namelen,2732uap->old, &oldlen, 1,2733uap->new, uap->newlen, &j, SCTL_MASK32);2734if (error)2735return (error);2736if (uap->oldlenp != NULL && suword32(uap->oldlenp, j) != 0)2737error = EFAULT;2738return (error);2739}27402741int2742freebsd32___sysctlbyname(struct thread *td,2743struct freebsd32___sysctlbyname_args *uap)2744{2745size_t oldlen, rv;2746int error;2747uint32_t tmp;27482749if (uap->oldlenp != NULL) {2750error = fueword32(uap->oldlenp, &tmp);2751oldlen = tmp;2752} else {2753error = oldlen = 0;2754}2755if (error != 0)2756return (EFAULT);2757error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,2758&oldlen, uap->new, uap->newlen, &rv, SCTL_MASK32, 1);2759if (error != 0)2760return (error);2761if (uap->oldlenp != NULL && suword32(uap->oldlenp, rv) != 0)2762error = EFAULT;2763return (error);2764}27652766int2767freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)2768{2769uint32_t version;2770int error;2771struct jail j;27722773error = copyin(uap->jail, &version, sizeof(uint32_t));2774if (error)2775return (error);27762777switch (version) {2778case 0:2779{2780/* FreeBSD single IPv4 jails. */2781struct jail32_v0 j32_v0;27822783bzero(&j, sizeof(struct jail));2784error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));2785if (error)2786return (error);2787CP(j32_v0, j, version);2788PTRIN_CP(j32_v0, j, path);2789PTRIN_CP(j32_v0, j, hostname);2790j.ip4s = htonl(j32_v0.ip_number); /* jail_v0 is host order */2791break;2792}27932794case 1:2795/*2796* Version 1 was used by multi-IPv4 jail implementations2797* that never made it into the official kernel.2798*/2799return (EINVAL);28002801case 2: /* JAIL_API_VERSION */2802{2803/* FreeBSD multi-IPv4/IPv6,noIP jails. */2804struct jail32 j32;28052806error = copyin(uap->jail, &j32, sizeof(struct jail32));2807if (error)2808return (error);2809CP(j32, j, version);2810PTRIN_CP(j32, j, path);2811PTRIN_CP(j32, j, hostname);2812PTRIN_CP(j32, j, jailname);2813CP(j32, j, ip4s);2814CP(j32, j, ip6s);2815PTRIN_CP(j32, j, ip4);2816PTRIN_CP(j32, j, ip6);2817break;2818}28192820default:2821/* Sci-Fi jails are not supported, sorry. */2822return (EINVAL);2823}2824return (kern_jail(td, &j));2825}28262827int2828freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)2829{2830struct uio *auio;2831int error;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_set(td, auio, uap->flags);2841freeuio(auio);2842return (error);2843}28442845int2846freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)2847{2848struct iovec32 iov32;2849struct uio *auio;2850int error, i;28512852/* Check that we have an even number of iovecs. */2853if (uap->iovcnt & 1)2854return (EINVAL);28552856error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);2857if (error)2858return (error);2859error = kern_jail_get(td, auio, uap->flags);2860if (error == 0)2861for (i = 0; i < uap->iovcnt; i++) {2862PTROUT_CP(auio->uio_iov[i], iov32, iov_base);2863CP(auio->uio_iov[i], iov32, iov_len);2864error = copyout(&iov32, uap->iovp + i, sizeof(iov32));2865if (error != 0)2866break;2867}2868freeuio(auio);2869return (error);2870}28712872int2873freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)2874{2875struct sigaction32 s32;2876struct sigaction sa, osa, *sap;2877int error;28782879if (uap->act) {2880error = copyin(uap->act, &s32, sizeof(s32));2881if (error)2882return (error);2883sa.sa_handler = PTRIN(s32.sa_u);2884CP(s32, sa, sa_flags);2885CP(s32, sa, sa_mask);2886sap = &sa;2887} else2888sap = NULL;2889error = kern_sigaction(td, uap->sig, sap, &osa, 0);2890if (error == 0 && uap->oact != NULL) {2891s32.sa_u = PTROUT(osa.sa_handler);2892CP(osa, s32, sa_flags);2893CP(osa, s32, sa_mask);2894error = copyout(&s32, uap->oact, sizeof(s32));2895}2896return (error);2897}28982899#ifdef COMPAT_FREEBSD42900int2901freebsd4_freebsd32_sigaction(struct thread *td,2902struct freebsd4_freebsd32_sigaction_args *uap)2903{2904struct sigaction32 s32;2905struct sigaction sa, osa, *sap;2906int error;29072908if (uap->act) {2909error = copyin(uap->act, &s32, sizeof(s32));2910if (error)2911return (error);2912sa.sa_handler = PTRIN(s32.sa_u);2913CP(s32, sa, sa_flags);2914CP(s32, sa, sa_mask);2915sap = &sa;2916} else2917sap = NULL;2918error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);2919if (error == 0 && uap->oact != NULL) {2920s32.sa_u = PTROUT(osa.sa_handler);2921CP(osa, s32, sa_flags);2922CP(osa, s32, sa_mask);2923error = copyout(&s32, uap->oact, sizeof(s32));2924}2925return (error);2926}2927#endif29282929#ifdef COMPAT_432930struct osigaction32 {2931uint32_t sa_u;2932osigset_t sa_mask;2933int sa_flags;2934};29352936#define ONSIG 3229372938int2939ofreebsd32_sigaction(struct thread *td,2940struct ofreebsd32_sigaction_args *uap)2941{2942struct osigaction32 s32;2943struct sigaction sa, osa, *sap;2944int error;29452946if (uap->signum <= 0 || uap->signum >= ONSIG)2947return (EINVAL);29482949if (uap->nsa) {2950error = copyin(uap->nsa, &s32, sizeof(s32));2951if (error)2952return (error);2953sa.sa_handler = PTRIN(s32.sa_u);2954CP(s32, sa, sa_flags);2955OSIG2SIG(s32.sa_mask, sa.sa_mask);2956sap = &sa;2957} else2958sap = NULL;2959error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);2960if (error == 0 && uap->osa != NULL) {2961s32.sa_u = PTROUT(osa.sa_handler);2962CP(osa, s32, sa_flags);2963SIG2OSIG(osa.sa_mask, s32.sa_mask);2964error = copyout(&s32, uap->osa, sizeof(s32));2965}2966return (error);2967}29682969struct sigvec32 {2970uint32_t sv_handler;2971int sv_mask;2972int sv_flags;2973};29742975int2976ofreebsd32_sigvec(struct thread *td,2977struct ofreebsd32_sigvec_args *uap)2978{2979struct sigvec32 vec;2980struct sigaction sa, osa, *sap;2981int error;29822983if (uap->signum <= 0 || uap->signum >= ONSIG)2984return (EINVAL);29852986if (uap->nsv) {2987error = copyin(uap->nsv, &vec, sizeof(vec));2988if (error)2989return (error);2990sa.sa_handler = PTRIN(vec.sv_handler);2991OSIG2SIG(vec.sv_mask, sa.sa_mask);2992sa.sa_flags = vec.sv_flags;2993sa.sa_flags ^= SA_RESTART;2994sap = &sa;2995} else2996sap = NULL;2997error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);2998if (error == 0 && uap->osv != NULL) {2999vec.sv_handler = PTROUT(osa.sa_handler);3000SIG2OSIG(osa.sa_mask, vec.sv_mask);3001vec.sv_flags = osa.sa_flags;3002vec.sv_flags &= ~SA_NOCLDWAIT;3003vec.sv_flags ^= SA_RESTART;3004error = copyout(&vec, uap->osv, sizeof(vec));3005}3006return (error);3007}30083009struct sigstack32 {3010uint32_t ss_sp;3011int ss_onstack;3012};30133014int3015ofreebsd32_sigstack(struct thread *td,3016struct ofreebsd32_sigstack_args *uap)3017{3018struct sigstack32 s32;3019struct sigstack nss, oss;3020int error = 0, unss;30213022if (uap->nss != NULL) {3023error = copyin(uap->nss, &s32, sizeof(s32));3024if (error)3025return (error);3026nss.ss_sp = PTRIN(s32.ss_sp);3027CP(s32, nss, ss_onstack);3028unss = 1;3029} else {3030unss = 0;3031}3032oss.ss_sp = td->td_sigstk.ss_sp;3033oss.ss_onstack = sigonstack(cpu_getstack(td));3034if (unss) {3035td->td_sigstk.ss_sp = nss.ss_sp;3036td->td_sigstk.ss_size = 0;3037td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);3038td->td_pflags |= TDP_ALTSTACK;3039}3040if (uap->oss != NULL) {3041s32.ss_sp = PTROUT(oss.ss_sp);3042CP(oss, s32, ss_onstack);3043error = copyout(&s32, uap->oss, sizeof(s32));3044}3045return (error);3046}3047#endif30483049int3050freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)3051{30523053return (freebsd32_user_clock_nanosleep(td, CLOCK_REALTIME,3054TIMER_RELTIME, uap->rqtp, uap->rmtp));3055}30563057int3058freebsd32_clock_nanosleep(struct thread *td,3059struct freebsd32_clock_nanosleep_args *uap)3060{3061int error;30623063error = freebsd32_user_clock_nanosleep(td, uap->clock_id, uap->flags,3064uap->rqtp, uap->rmtp);3065return (kern_posix_error(td, error));3066}30673068static int3069freebsd32_user_clock_nanosleep(struct thread *td, clockid_t clock_id,3070int flags, const struct timespec32 *ua_rqtp, struct timespec32 *ua_rmtp)3071{3072struct timespec32 rmt32, rqt32;3073struct timespec rmt, rqt;3074int error, error2;30753076error = copyin(ua_rqtp, &rqt32, sizeof(rqt32));3077if (error)3078return (error);30793080CP(rqt32, rqt, tv_sec);3081CP(rqt32, rqt, tv_nsec);30823083error = kern_clock_nanosleep(td, clock_id, flags, &rqt, &rmt);3084if (error == EINTR && ua_rmtp != NULL && (flags & TIMER_ABSTIME) == 0) {3085CP(rmt, rmt32, tv_sec);3086CP(rmt, rmt32, tv_nsec);30873088error2 = copyout(&rmt32, ua_rmtp, sizeof(rmt32));3089if (error2 != 0)3090error = error2;3091}3092return (error);3093}30943095int3096freebsd32_clock_gettime(struct thread *td,3097struct freebsd32_clock_gettime_args *uap)3098{3099struct timespec ats;3100struct timespec32 ats32;3101int error;31023103error = kern_clock_gettime(td, uap->clock_id, &ats);3104if (error == 0) {3105CP(ats, ats32, tv_sec);3106CP(ats, ats32, tv_nsec);3107error = copyout(&ats32, uap->tp, sizeof(ats32));3108}3109return (error);3110}31113112int3113freebsd32_clock_settime(struct thread *td,3114struct freebsd32_clock_settime_args *uap)3115{3116struct timespec ats;3117struct timespec32 ats32;3118int error;31193120error = copyin(uap->tp, &ats32, sizeof(ats32));3121if (error)3122return (error);3123CP(ats32, ats, tv_sec);3124CP(ats32, ats, tv_nsec);31253126return (kern_clock_settime(td, uap->clock_id, &ats));3127}31283129int3130freebsd32_clock_getres(struct thread *td,3131struct freebsd32_clock_getres_args *uap)3132{3133struct timespec ts;3134struct timespec32 ts32;3135int error;31363137if (uap->tp == NULL)3138return (0);3139error = kern_clock_getres(td, uap->clock_id, &ts);3140if (error == 0) {3141CP(ts, ts32, tv_sec);3142CP(ts, ts32, tv_nsec);3143error = copyout(&ts32, uap->tp, sizeof(ts32));3144}3145return (error);3146}31473148int freebsd32_ktimer_create(struct thread *td,3149struct freebsd32_ktimer_create_args *uap)3150{3151struct sigevent32 ev32;3152struct sigevent ev, *evp;3153int error, id;31543155if (uap->evp == NULL) {3156evp = NULL;3157} else {3158evp = &ev;3159error = copyin(uap->evp, &ev32, sizeof(ev32));3160if (error != 0)3161return (error);3162error = convert_sigevent32(&ev32, &ev);3163if (error != 0)3164return (error);3165}3166error = kern_ktimer_create(td, uap->clock_id, evp, &id, -1);3167if (error == 0) {3168error = copyout(&id, uap->timerid, sizeof(int));3169if (error != 0)3170kern_ktimer_delete(td, id);3171}3172return (error);3173}31743175int3176freebsd32_ktimer_settime(struct thread *td,3177struct freebsd32_ktimer_settime_args *uap)3178{3179struct itimerspec32 val32, oval32;3180struct itimerspec val, oval, *ovalp;3181int error;31823183error = copyin(uap->value, &val32, sizeof(val32));3184if (error != 0)3185return (error);3186ITS_CP(val32, val);3187ovalp = uap->ovalue != NULL ? &oval : NULL;3188error = kern_ktimer_settime(td, uap->timerid, uap->flags, &val, ovalp);3189if (error == 0 && uap->ovalue != NULL) {3190ITS_CP(oval, oval32);3191error = copyout(&oval32, uap->ovalue, sizeof(oval32));3192}3193return (error);3194}31953196int3197freebsd32_ktimer_gettime(struct thread *td,3198struct freebsd32_ktimer_gettime_args *uap)3199{3200struct itimerspec32 val32;3201struct itimerspec val;3202int error;32033204error = kern_ktimer_gettime(td, uap->timerid, &val);3205if (error == 0) {3206ITS_CP(val, val32);3207error = copyout(&val32, uap->value, sizeof(val32));3208}3209return (error);3210}32113212int3213freebsd32_timerfd_gettime(struct thread *td,3214struct freebsd32_timerfd_gettime_args *uap)3215{3216struct itimerspec curr_value;3217struct itimerspec32 curr_value32;3218int error;32193220error = kern_timerfd_gettime(td, uap->fd, &curr_value);3221if (error == 0) {3222CP(curr_value, curr_value32, it_value.tv_sec);3223CP(curr_value, curr_value32, it_value.tv_nsec);3224CP(curr_value, curr_value32, it_interval.tv_sec);3225CP(curr_value, curr_value32, it_interval.tv_nsec);3226error = copyout(&curr_value32, uap->curr_value,3227sizeof(curr_value32));3228}32293230return (error);3231}32323233int3234freebsd32_timerfd_settime(struct thread *td,3235struct freebsd32_timerfd_settime_args *uap)3236{3237struct itimerspec new_value, old_value;3238struct itimerspec32 new_value32, old_value32;3239int error;32403241error = copyin(uap->new_value, &new_value32, sizeof(new_value32));3242if (error != 0)3243return (error);3244CP(new_value32, new_value, it_value.tv_sec);3245CP(new_value32, new_value, it_value.tv_nsec);3246CP(new_value32, new_value, it_interval.tv_sec);3247CP(new_value32, new_value, it_interval.tv_nsec);3248if (uap->old_value == NULL) {3249error = kern_timerfd_settime(td, uap->fd, uap->flags,3250&new_value, NULL);3251} else {3252error = kern_timerfd_settime(td, uap->fd, uap->flags,3253&new_value, &old_value);3254if (error == 0) {3255CP(old_value, old_value32, it_value.tv_sec);3256CP(old_value, old_value32, it_value.tv_nsec);3257CP(old_value, old_value32, it_interval.tv_sec);3258CP(old_value, old_value32, it_interval.tv_nsec);3259error = copyout(&old_value32, uap->old_value,3260sizeof(old_value32));3261}3262}3263return (error);3264}32653266int3267freebsd32_clock_getcpuclockid2(struct thread *td,3268struct freebsd32_clock_getcpuclockid2_args *uap)3269{3270clockid_t clk_id;3271int error;32723273error = kern_clock_getcpuclockid2(td, PAIR32TO64(id_t, uap->id),3274uap->which, &clk_id);3275if (error == 0)3276error = copyout(&clk_id, uap->clock_id, sizeof(clockid_t));3277return (error);3278}32793280int3281freebsd32_thr_new(struct thread *td,3282struct freebsd32_thr_new_args *uap)3283{3284struct thr_param32 param32;3285struct thr_param param;3286int error;32873288if (uap->param_size < 0 ||3289uap->param_size > sizeof(struct thr_param32))3290return (EINVAL);3291bzero(¶m, sizeof(struct thr_param));3292bzero(¶m32, sizeof(struct thr_param32));3293error = copyin(uap->param, ¶m32, uap->param_size);3294if (error != 0)3295return (error);3296param.start_func = PTRIN(param32.start_func);3297param.arg = PTRIN(param32.arg);3298param.stack_base = PTRIN(param32.stack_base);3299param.stack_size = param32.stack_size;3300param.tls_base = PTRIN(param32.tls_base);3301param.tls_size = param32.tls_size;3302param.child_tid = PTRIN(param32.child_tid);3303param.parent_tid = PTRIN(param32.parent_tid);3304param.flags = param32.flags;3305param.rtp = PTRIN(param32.rtp);3306param.spare[0] = PTRIN(param32.spare[0]);3307param.spare[1] = PTRIN(param32.spare[1]);3308param.spare[2] = PTRIN(param32.spare[2]);33093310return (kern_thr_new(td, ¶m));3311}33123313int3314freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)3315{3316struct timespec32 ts32;3317struct timespec ts, *tsp;3318int error;33193320error = 0;3321tsp = NULL;3322if (uap->timeout != NULL) {3323error = copyin((const void *)uap->timeout, (void *)&ts32,3324sizeof(struct timespec32));3325if (error != 0)3326return (error);3327ts.tv_sec = ts32.tv_sec;3328ts.tv_nsec = ts32.tv_nsec;3329tsp = &ts;3330}3331return (kern_thr_suspend(td, tsp));3332}33333334void3335siginfo_to_siginfo32(const siginfo_t *src, struct __siginfo32 *dst)3336{3337bzero(dst, sizeof(*dst));3338dst->si_signo = src->si_signo;3339dst->si_errno = src->si_errno;3340dst->si_code = src->si_code;3341dst->si_pid = src->si_pid;3342dst->si_uid = src->si_uid;3343dst->si_status = src->si_status;3344dst->si_addr = (uintptr_t)src->si_addr;3345dst->si_value.sival_int = src->si_value.sival_int;3346dst->si_timerid = src->si_timerid;3347dst->si_overrun = src->si_overrun;3348}33493350#ifndef _FREEBSD32_SYSPROTO_H_3351struct freebsd32_sigqueue_args {3352pid_t pid;3353int signum;3354/* union sigval32 */ int value;3355};3356#endif3357int3358freebsd32_sigqueue(struct thread *td, struct freebsd32_sigqueue_args *uap)3359{3360union sigval sv;33613362/*3363* On 32-bit ABIs, sival_int and sival_ptr are the same.3364* On 64-bit little-endian ABIs, the low bits are the same.3365* In 64-bit big-endian ABIs, sival_int overlaps with3366* sival_ptr's HIGH bits. We choose to support sival_int3367* rather than sival_ptr in this case as it seems to be3368* more common.3369*/3370bzero(&sv, sizeof(sv));3371sv.sival_int = (uint32_t)(uint64_t)uap->value;33723373return (kern_sigqueue(td, uap->pid, uap->signum, &sv));3374}33753376int3377freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)3378{3379struct timespec32 ts32;3380struct timespec ts;3381struct timespec *timeout;3382sigset_t set;3383ksiginfo_t ksi;3384struct __siginfo32 si32;3385int error;33863387if (uap->timeout) {3388error = copyin(uap->timeout, &ts32, sizeof(ts32));3389if (error)3390return (error);3391ts.tv_sec = ts32.tv_sec;3392ts.tv_nsec = ts32.tv_nsec;3393timeout = &ts;3394} else3395timeout = NULL;33963397error = copyin(uap->set, &set, sizeof(set));3398if (error)3399return (error);34003401error = kern_sigtimedwait(td, set, &ksi, timeout);3402if (error)3403return (error);34043405if (uap->info) {3406siginfo_to_siginfo32(&ksi.ksi_info, &si32);3407error = copyout(&si32, uap->info, sizeof(struct __siginfo32));3408}34093410if (error == 0)3411td->td_retval[0] = ksi.ksi_signo;3412return (error);3413}34143415/*3416* MPSAFE3417*/3418int3419freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)3420{3421ksiginfo_t ksi;3422struct __siginfo32 si32;3423sigset_t set;3424int error;34253426error = copyin(uap->set, &set, sizeof(set));3427if (error)3428return (error);34293430error = kern_sigtimedwait(td, set, &ksi, NULL);3431if (error)3432return (error);34333434if (uap->info) {3435siginfo_to_siginfo32(&ksi.ksi_info, &si32);3436error = copyout(&si32, uap->info, sizeof(struct __siginfo32));3437}3438if (error == 0)3439td->td_retval[0] = ksi.ksi_signo;3440return (error);3441}34423443int3444freebsd32_cpuset_setid(struct thread *td,3445struct freebsd32_cpuset_setid_args *uap)3446{34473448return (kern_cpuset_setid(td, uap->which,3449PAIR32TO64(id_t, uap->id), uap->setid));3450}34513452int3453freebsd32_cpuset_getid(struct thread *td,3454struct freebsd32_cpuset_getid_args *uap)3455{34563457return (kern_cpuset_getid(td, uap->level, uap->which,3458PAIR32TO64(id_t, uap->id), uap->setid));3459}34603461static int3462copyin32_set(const void *u, void *k, size_t size)3463{3464#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__3465int rv;3466struct bitset *kb = k;3467int *p;34683469rv = copyin(u, k, size);3470if (rv != 0)3471return (rv);34723473p = (int *)kb->__bits;3474/* Loop through swapping words.3475* `size' is in bytes, we need bits. */3476for (int i = 0; i < __bitset_words(size * 8); i++) {3477int tmp = p[0];3478p[0] = p[1];3479p[1] = tmp;3480p += 2;3481}3482return (0);3483#else3484return (copyin(u, k, size));3485#endif3486}34873488static int3489copyout32_set(const void *k, void *u, size_t size)3490{3491#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__3492const struct bitset *kb = k;3493struct bitset *ub = u;3494const int *kp = (const int *)kb->__bits;3495int *up = (int *)ub->__bits;3496int rv;34973498for (int i = 0; i < __bitset_words(CPU_SETSIZE); i++) {3499/* `size' is in bytes, we need bits. */3500for (int i = 0; i < __bitset_words(size * 8); i++) {3501rv = suword32(up, kp[1]);3502if (rv == 0)3503rv = suword32(up + 1, kp[0]);3504if (rv != 0)3505return (EFAULT);3506}3507}3508return (0);3509#else3510return (copyout(k, u, size));3511#endif3512}35133514static const struct cpuset_copy_cb cpuset_copy32_cb = {3515.cpuset_copyin = copyin32_set,3516.cpuset_copyout = copyout32_set3517};35183519int3520freebsd32_cpuset_getaffinity(struct thread *td,3521struct freebsd32_cpuset_getaffinity_args *uap)3522{35233524return (user_cpuset_getaffinity(td, uap->level, uap->which,3525PAIR32TO64(id_t,uap->id), uap->cpusetsize, uap->mask,3526&cpuset_copy32_cb));3527}35283529int3530freebsd32_cpuset_setaffinity(struct thread *td,3531struct freebsd32_cpuset_setaffinity_args *uap)3532{35333534return (user_cpuset_setaffinity(td, uap->level, uap->which,3535PAIR32TO64(id_t,uap->id), uap->cpusetsize, uap->mask,3536&cpuset_copy32_cb));3537}35383539int3540freebsd32_cpuset_getdomain(struct thread *td,3541struct freebsd32_cpuset_getdomain_args *uap)3542{35433544return (kern_cpuset_getdomain(td, uap->level, uap->which,3545PAIR32TO64(id_t,uap->id), uap->domainsetsize, uap->mask, uap->policy,3546&cpuset_copy32_cb));3547}35483549int3550freebsd32_cpuset_setdomain(struct thread *td,3551struct freebsd32_cpuset_setdomain_args *uap)3552{35533554return (kern_cpuset_setdomain(td, uap->level, uap->which,3555PAIR32TO64(id_t,uap->id), uap->domainsetsize, uap->mask, uap->policy,3556&cpuset_copy32_cb));3557}35583559int3560freebsd32_nmount(struct thread *td,3561struct freebsd32_nmount_args /* {3562struct iovec *iovp;3563unsigned int iovcnt;3564int flags;3565} */ *uap)3566{3567struct uio *auio;3568uint64_t flags;3569int error;35703571/*3572* Mount flags are now 64-bits. On 32-bit archtectures only3573* 32-bits are passed in, but from here on everything handles3574* 64-bit flags correctly.3575*/3576flags = uap->flags;35773578AUDIT_ARG_FFLAGS(flags);35793580/*3581* Filter out MNT_ROOTFS. We do not want clients of nmount() in3582* userspace to set this flag, but we must filter it out if we want3583* MNT_UPDATE on the root file system to work.3584* MNT_ROOTFS should only be set by the kernel when mounting its3585* root file system.3586*/3587flags &= ~MNT_ROOTFS;35883589/*3590* check that we have an even number of iovec's3591* and that we have at least two options.3592*/3593if ((uap->iovcnt & 1) || (uap->iovcnt < 4))3594return (EINVAL);35953596error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);3597if (error)3598return (error);3599error = vfs_donmount(td, flags, auio);36003601freeuio(auio);3602return error;3603}36043605#if 03606int3607freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)3608{3609struct yyy32 *p32, s32;3610struct yyy *p = NULL, s;3611struct xxx_arg ap;3612int error;36133614if (uap->zzz) {3615error = copyin(uap->zzz, &s32, sizeof(s32));3616if (error)3617return (error);3618/* translate in */3619p = &s;3620}3621error = kern_xxx(td, p);3622if (error)3623return (error);3624if (uap->zzz) {3625/* translate out */3626error = copyout(&s32, p32, sizeof(s32));3627}3628return (error);3629}3630#endif36313632int3633syscall32_module_handler(struct module *mod, int what, void *arg)3634{36353636return (kern_syscall_module_handler(freebsd32_sysent, mod, what, arg));3637}36383639int3640syscall32_helper_register(struct syscall_helper_data *sd, int flags)3641{36423643return (kern_syscall_helper_register(freebsd32_sysent, sd, flags));3644}36453646int3647syscall32_helper_unregister(struct syscall_helper_data *sd)3648{36493650return (kern_syscall_helper_unregister(freebsd32_sysent, sd));3651}36523653int3654freebsd32_copyout_strings(struct image_params *imgp, uintptr_t *stack_base)3655{3656struct sysentvec *sysent;3657int argc, envc, i;3658uint32_t *vectp;3659char *stringp;3660uintptr_t destp, ustringp;3661struct freebsd32_ps_strings *arginfo;3662char canary[sizeof(long) * 8];3663int32_t pagesizes32[MAXPAGESIZES];3664size_t execpath_len;3665int error, szsigcode;36663667sysent = imgp->sysent;36683669arginfo = (struct freebsd32_ps_strings *)PROC_PS_STRINGS(imgp->proc);3670imgp->ps_strings = arginfo;3671destp = (uintptr_t)arginfo;36723673/*3674* Install sigcode.3675*/3676if (!PROC_HAS_SHP(imgp->proc)) {3677szsigcode = *sysent->sv_szsigcode;3678destp -= szsigcode;3679destp = rounddown2(destp, sizeof(uint32_t));3680error = copyout(sysent->sv_sigcode, (void *)destp,3681szsigcode);3682if (error != 0)3683return (error);3684}36853686/*3687* Copy the image path for the rtld.3688*/3689if (imgp->execpath != NULL && imgp->auxargs != NULL) {3690execpath_len = strlen(imgp->execpath) + 1;3691destp -= execpath_len;3692imgp->execpathp = (void *)destp;3693error = copyout(imgp->execpath, imgp->execpathp, execpath_len);3694if (error != 0)3695return (error);3696}36973698/*3699* Prepare the canary for SSP.3700*/3701arc4rand(canary, sizeof(canary), 0);3702destp -= sizeof(canary);3703imgp->canary = (void *)destp;3704error = copyout(canary, imgp->canary, sizeof(canary));3705if (error != 0)3706return (error);3707imgp->canarylen = sizeof(canary);37083709/*3710* Prepare the pagesizes array.3711*/3712for (i = 0; i < MAXPAGESIZES; i++)3713pagesizes32[i] = (uint32_t)pagesizes[i];3714destp -= sizeof(pagesizes32);3715destp = rounddown2(destp, sizeof(uint32_t));3716imgp->pagesizes = (void *)destp;3717error = copyout(pagesizes32, imgp->pagesizes, sizeof(pagesizes32));3718if (error != 0)3719return (error);3720imgp->pagesizeslen = sizeof(pagesizes32);37213722/*3723* Allocate room for the argument and environment strings.3724*/3725destp -= ARG_MAX - imgp->args->stringspace;3726destp = rounddown2(destp, sizeof(uint32_t));3727ustringp = destp;37283729if (imgp->auxargs) {3730/*3731* Allocate room on the stack for the ELF auxargs3732* array. It has up to AT_COUNT entries.3733*/3734destp -= AT_COUNT * sizeof(Elf32_Auxinfo);3735destp = rounddown2(destp, sizeof(uint32_t));3736}37373738vectp = (uint32_t *)destp;37393740/*3741* Allocate room for the argv[] and env vectors including the3742* terminating NULL pointers.3743*/3744vectp -= imgp->args->argc + 1 + imgp->args->envc + 1;37453746/*3747* vectp also becomes our initial stack base3748*/3749*stack_base = (uintptr_t)vectp;37503751stringp = imgp->args->begin_argv;3752argc = imgp->args->argc;3753envc = imgp->args->envc;3754/*3755* Copy out strings - arguments and environment.3756*/3757error = copyout(stringp, (void *)ustringp,3758ARG_MAX - imgp->args->stringspace);3759if (error != 0)3760return (error);37613762/*3763* Fill in "ps_strings" struct for ps, w, etc.3764*/3765imgp->argv = vectp;3766if (suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp) != 0 ||3767suword32(&arginfo->ps_nargvstr, argc) != 0)3768return (EFAULT);37693770/*3771* Fill in argument portion of vector table.3772*/3773for (; argc > 0; --argc) {3774if (suword32(vectp++, ustringp) != 0)3775return (EFAULT);3776while (*stringp++ != 0)3777ustringp++;3778ustringp++;3779}37803781/* a null vector table pointer separates the argp's from the envp's */3782if (suword32(vectp++, 0) != 0)3783return (EFAULT);37843785imgp->envv = vectp;3786if (suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp) != 0 ||3787suword32(&arginfo->ps_nenvstr, envc) != 0)3788return (EFAULT);37893790/*3791* Fill in environment portion of vector table.3792*/3793for (; envc > 0; --envc) {3794if (suword32(vectp++, ustringp) != 0)3795return (EFAULT);3796while (*stringp++ != 0)3797ustringp++;3798ustringp++;3799}38003801/* end of vector table is a null pointer */3802if (suword32(vectp, 0) != 0)3803return (EFAULT);38043805if (imgp->auxargs) {3806vectp++;3807error = imgp->sysent->sv_copyout_auxargs(imgp,3808(uintptr_t)vectp);3809if (error != 0)3810return (error);3811}38123813return (0);3814}38153816int3817freebsd32_kldstat(struct thread *td, struct freebsd32_kldstat_args *uap)3818{3819struct kld_file_stat *stat;3820struct kld_file_stat32 *stat32;3821int error, version;38223823if ((error = copyin(&uap->stat->version, &version, sizeof(version)))3824!= 0)3825return (error);3826if (version != sizeof(struct kld_file_stat_1_32) &&3827version != sizeof(struct kld_file_stat32))3828return (EINVAL);38293830stat = malloc(sizeof(*stat), M_TEMP, M_WAITOK | M_ZERO);3831stat32 = malloc(sizeof(*stat32), M_TEMP, M_WAITOK | M_ZERO);3832error = kern_kldstat(td, uap->fileid, stat);3833if (error == 0) {3834bcopy(&stat->name[0], &stat32->name[0], sizeof(stat->name));3835CP(*stat, *stat32, refs);3836CP(*stat, *stat32, id);3837PTROUT_CP(*stat, *stat32, address);3838CP(*stat, *stat32, size);3839bcopy(&stat->pathname[0], &stat32->pathname[0],3840sizeof(stat->pathname));3841stat32->version = version;3842error = copyout(stat32, uap->stat, version);3843}3844free(stat, M_TEMP);3845free(stat32, M_TEMP);3846return (error);3847}38483849int3850freebsd32_posix_fallocate(struct thread *td,3851struct freebsd32_posix_fallocate_args *uap)3852{3853int error;38543855error = kern_posix_fallocate(td, uap->fd,3856PAIR32TO64(off_t, uap->offset), PAIR32TO64(off_t, uap->len));3857return (kern_posix_error(td, error));3858}38593860int3861freebsd32_posix_fadvise(struct thread *td,3862struct freebsd32_posix_fadvise_args *uap)3863{3864int error;38653866error = kern_posix_fadvise(td, uap->fd, PAIR32TO64(off_t, uap->offset),3867PAIR32TO64(off_t, uap->len), uap->advice);3868return (kern_posix_error(td, error));3869}38703871int3872convert_sigevent32(struct sigevent32 *sig32, struct sigevent *sig)3873{38743875CP(*sig32, *sig, sigev_notify);3876switch (sig->sigev_notify) {3877case SIGEV_NONE:3878break;3879case SIGEV_THREAD_ID:3880CP(*sig32, *sig, sigev_notify_thread_id);3881/* FALLTHROUGH */3882case SIGEV_SIGNAL:3883CP(*sig32, *sig, sigev_signo);3884PTRIN_CP(*sig32, *sig, sigev_value.sival_ptr);3885break;3886case SIGEV_KEVENT:3887CP(*sig32, *sig, sigev_notify_kqueue);3888CP(*sig32, *sig, sigev_notify_kevent_flags);3889PTRIN_CP(*sig32, *sig, sigev_value.sival_ptr);3890break;3891default:3892return (EINVAL);3893}3894return (0);3895}38963897int3898freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)3899{3900void *data;3901union {3902struct procctl_reaper_status rs;3903struct procctl_reaper_pids rp;3904struct procctl_reaper_kill rk;3905} x;3906union {3907struct procctl_reaper_pids32 rp;3908} x32;3909int error, error1, flags, signum;39103911if (uap->com >= PROC_PROCCTL_MD_MIN)3912return (cpu_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id),3913uap->com, PTRIN(uap->data)));39143915switch (uap->com) {3916case PROC_ASLR_CTL:3917case PROC_PROTMAX_CTL:3918case PROC_SPROTECT:3919case PROC_STACKGAP_CTL:3920case PROC_TRACE_CTL:3921case PROC_TRAPCAP_CTL:3922case PROC_NO_NEW_PRIVS_CTL:3923case PROC_WXMAP_CTL:3924case PROC_LOGSIGEXIT_CTL:3925error = copyin(PTRIN(uap->data), &flags, sizeof(flags));3926if (error != 0)3927return (error);3928data = &flags;3929break;3930case PROC_REAP_ACQUIRE:3931case PROC_REAP_RELEASE:3932if (uap->data != NULL)3933return (EINVAL);3934data = NULL;3935break;3936case PROC_REAP_STATUS:3937data = &x.rs;3938break;3939case PROC_REAP_GETPIDS:3940error = copyin(uap->data, &x32.rp, sizeof(x32.rp));3941if (error != 0)3942return (error);3943CP(x32.rp, x.rp, rp_count);3944PTRIN_CP(x32.rp, x.rp, rp_pids);3945data = &x.rp;3946break;3947case PROC_REAP_KILL:3948error = copyin(uap->data, &x.rk, sizeof(x.rk));3949if (error != 0)3950return (error);3951data = &x.rk;3952break;3953case PROC_ASLR_STATUS:3954case PROC_PROTMAX_STATUS:3955case PROC_STACKGAP_STATUS:3956case PROC_TRACE_STATUS:3957case PROC_TRAPCAP_STATUS:3958case PROC_NO_NEW_PRIVS_STATUS:3959case PROC_WXMAP_STATUS:3960case PROC_LOGSIGEXIT_STATUS:3961data = &flags;3962break;3963case PROC_PDEATHSIG_CTL:3964error = copyin(uap->data, &signum, sizeof(signum));3965if (error != 0)3966return (error);3967data = &signum;3968break;3969case PROC_PDEATHSIG_STATUS:3970data = &signum;3971break;3972default:3973return (EINVAL);3974}3975error = kern_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id),3976uap->com, data);3977switch (uap->com) {3978case PROC_REAP_STATUS:3979if (error == 0)3980error = copyout(&x.rs, uap->data, sizeof(x.rs));3981break;3982case PROC_REAP_KILL:3983error1 = copyout(&x.rk, uap->data, sizeof(x.rk));3984if (error == 0)3985error = error1;3986break;3987case PROC_ASLR_STATUS:3988case PROC_PROTMAX_STATUS:3989case PROC_STACKGAP_STATUS:3990case PROC_TRACE_STATUS:3991case PROC_TRAPCAP_STATUS:3992case PROC_NO_NEW_PRIVS_STATUS:3993case PROC_WXMAP_STATUS:3994case PROC_LOGSIGEXIT_STATUS:3995if (error == 0)3996error = copyout(&flags, uap->data, sizeof(flags));3997break;3998case PROC_PDEATHSIG_STATUS:3999if (error == 0)4000error = copyout(&signum, uap->data, sizeof(signum));4001break;4002}4003return (error);4004}40054006int4007freebsd32_fcntl(struct thread *td, struct freebsd32_fcntl_args *uap)4008{4009intptr_t tmp;40104011switch (uap->cmd) {4012/*4013* Do unsigned conversion for arg when operation4014* interprets it as flags or pointer.4015*/4016case F_SETLK_REMOTE:4017case F_SETLKW:4018case F_SETLK:4019case F_GETLK:4020case F_SETFD:4021case F_SETFL:4022case F_OGETLK:4023case F_OSETLK:4024case F_OSETLKW:4025case F_KINFO:4026tmp = (unsigned int)(uap->arg);4027break;4028default:4029tmp = uap->arg;4030break;4031}4032return (kern_fcntl_freebsd(td, uap->fd, uap->cmd, tmp));4033}40344035int4036freebsd32_ppoll(struct thread *td, struct freebsd32_ppoll_args *uap)4037{4038struct timespec32 ts32;4039struct timespec ts, *tsp;4040sigset_t set, *ssp;4041int error;40424043if (uap->ts != NULL) {4044error = copyin(uap->ts, &ts32, sizeof(ts32));4045if (error != 0)4046return (error);4047CP(ts32, ts, tv_sec);4048CP(ts32, ts, tv_nsec);4049tsp = &ts;4050} else4051tsp = NULL;4052if (uap->set != NULL) {4053error = copyin(uap->set, &set, sizeof(set));4054if (error != 0)4055return (error);4056ssp = &set;4057} else4058ssp = NULL;40594060return (kern_poll(td, uap->fds, uap->nfds, tsp, ssp));4061}40624063int4064freebsd32_sched_rr_get_interval(struct thread *td,4065struct freebsd32_sched_rr_get_interval_args *uap)4066{4067struct timespec ts;4068struct timespec32 ts32;4069int error;40704071error = kern_sched_rr_get_interval(td, uap->pid, &ts);4072if (error == 0) {4073CP(ts, ts32, tv_sec);4074CP(ts, ts32, tv_nsec);4075error = copyout(&ts32, uap->interval, sizeof(ts32));4076}4077return (error);4078}40794080static void4081timex_to_32(struct timex32 *dst, struct timex *src)4082{4083CP(*src, *dst, modes);4084CP(*src, *dst, offset);4085CP(*src, *dst, freq);4086CP(*src, *dst, maxerror);4087CP(*src, *dst, esterror);4088CP(*src, *dst, status);4089CP(*src, *dst, constant);4090CP(*src, *dst, precision);4091CP(*src, *dst, tolerance);4092CP(*src, *dst, ppsfreq);4093CP(*src, *dst, jitter);4094CP(*src, *dst, shift);4095CP(*src, *dst, stabil);4096CP(*src, *dst, jitcnt);4097CP(*src, *dst, calcnt);4098CP(*src, *dst, errcnt);4099CP(*src, *dst, stbcnt);4100}41014102static void4103timex_from_32(struct timex *dst, struct timex32 *src)4104{4105CP(*src, *dst, modes);4106CP(*src, *dst, offset);4107CP(*src, *dst, freq);4108CP(*src, *dst, maxerror);4109CP(*src, *dst, esterror);4110CP(*src, *dst, status);4111CP(*src, *dst, constant);4112CP(*src, *dst, precision);4113CP(*src, *dst, tolerance);4114CP(*src, *dst, ppsfreq);4115CP(*src, *dst, jitter);4116CP(*src, *dst, shift);4117CP(*src, *dst, stabil);4118CP(*src, *dst, jitcnt);4119CP(*src, *dst, calcnt);4120CP(*src, *dst, errcnt);4121CP(*src, *dst, stbcnt);4122}41234124int4125freebsd32_ntp_adjtime(struct thread *td, struct freebsd32_ntp_adjtime_args *uap)4126{4127struct timex tx;4128struct timex32 tx32;4129int error, retval;41304131error = copyin(uap->tp, &tx32, sizeof(tx32));4132if (error == 0) {4133timex_from_32(&tx, &tx32);4134error = kern_ntp_adjtime(td, &tx, &retval);4135if (error == 0) {4136timex_to_32(&tx32, &tx);4137error = copyout(&tx32, uap->tp, sizeof(tx32));4138if (error == 0)4139td->td_retval[0] = retval;4140}4141}4142return (error);4143}41444145#ifdef FFCLOCK4146extern struct mtx ffclock_mtx;4147extern struct ffclock_estimate ffclock_estimate;4148extern int8_t ffclock_updated;41494150int4151freebsd32_ffclock_setestimate(struct thread *td,4152struct freebsd32_ffclock_setestimate_args *uap)4153{4154struct ffclock_estimate cest;4155struct ffclock_estimate32 cest32;4156int error;41574158/* Reuse of PRIV_CLOCK_SETTIME. */4159if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0)4160return (error);41614162if ((error = copyin(uap->cest, &cest32,4163sizeof(struct ffclock_estimate32))) != 0)4164return (error);41654166CP(cest.update_time, cest32.update_time, sec);4167memcpy(&cest.update_time.frac, &cest32.update_time.frac, sizeof(uint64_t));4168CP(cest, cest32, update_ffcount);4169CP(cest, cest32, leapsec_next);4170CP(cest, cest32, period);4171CP(cest, cest32, errb_abs);4172CP(cest, cest32, errb_rate);4173CP(cest, cest32, status);4174CP(cest, cest32, leapsec_total);4175CP(cest, cest32, leapsec);41764177mtx_lock(&ffclock_mtx);4178memcpy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate));4179ffclock_updated++;4180mtx_unlock(&ffclock_mtx);4181return (error);4182}41834184int4185freebsd32_ffclock_getestimate(struct thread *td,4186struct freebsd32_ffclock_getestimate_args *uap)4187{4188struct ffclock_estimate cest;4189struct ffclock_estimate32 cest32;4190int error;41914192mtx_lock(&ffclock_mtx);4193memcpy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate));4194mtx_unlock(&ffclock_mtx);41954196CP(cest32.update_time, cest.update_time, sec);4197memcpy(&cest32.update_time.frac, &cest.update_time.frac, sizeof(uint64_t));4198CP(cest32, cest, update_ffcount);4199CP(cest32, cest, leapsec_next);4200CP(cest32, cest, period);4201CP(cest32, cest, errb_abs);4202CP(cest32, cest, errb_rate);4203CP(cest32, cest, status);4204CP(cest32, cest, leapsec_total);4205CP(cest32, cest, leapsec);42064207error = copyout(&cest32, uap->cest, sizeof(struct ffclock_estimate32));4208return (error);4209}4210#else /* !FFCLOCK */4211int4212freebsd32_ffclock_setestimate(struct thread *td,4213struct freebsd32_ffclock_setestimate_args *uap)4214{4215return (ENOSYS);4216}42174218int4219freebsd32_ffclock_getestimate(struct thread *td,4220struct freebsd32_ffclock_getestimate_args *uap)4221{4222return (ENOSYS);4223}4224#endif /* FFCLOCK */42254226#ifdef COMPAT_434227int4228ofreebsd32_sethostid(struct thread *td, struct ofreebsd32_sethostid_args *uap)4229{4230int name[] = { CTL_KERN, KERN_HOSTID };4231long hostid;42324233hostid = uap->hostid;4234return (kernel_sysctl(td, name, nitems(name), NULL, NULL, &hostid,4235sizeof(hostid), NULL, 0));4236}4237#endif42384239int4240freebsd32_setcred(struct thread *td, struct freebsd32_setcred_args *uap)4241{4242/* Last argument is 'is_32bit'. */4243return (user_setcred(td, uap->flags, uap->wcred, uap->size, true));4244}424542464247