xref: /freebsd/sys/compat/freebsd32/freebsd32_misc.c (revision ee609560ad2a5fa7cacf06a3879987e118588625)
13ebc1248SPeter Wemm /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
37f2d13d6SPedro F. Giffuni  *
43ebc1248SPeter Wemm  * Copyright (c) 2002 Doug Rabson
53ebc1248SPeter Wemm  * All rights reserved.
63ebc1248SPeter Wemm  *
73ebc1248SPeter Wemm  * Redistribution and use in source and binary forms, with or without
83ebc1248SPeter Wemm  * modification, are permitted provided that the following conditions
93ebc1248SPeter Wemm  * are met:
103ebc1248SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
113ebc1248SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
123ebc1248SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
133ebc1248SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
143ebc1248SPeter Wemm  *    documentation and/or other materials provided with the distribution.
153ebc1248SPeter Wemm  *
163ebc1248SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
173ebc1248SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
183ebc1248SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
193ebc1248SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
203ebc1248SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
213ebc1248SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
223ebc1248SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
233ebc1248SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
243ebc1248SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
253ebc1248SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
263ebc1248SPeter Wemm  * SUCH DAMAGE.
273ebc1248SPeter Wemm  */
283ebc1248SPeter Wemm 
2956ae44c5SDavid E. O'Brien #include <sys/cdefs.h>
30e3e811a3SBrooks Davis #include "opt_ffclock.h"
31b38ff370SJamie Gritton #include "opt_inet.h"
32b38ff370SJamie Gritton #include "opt_inet6.h"
33ffb66079SJohn Baldwin #include "opt_ktrace.h"
34459e3a7aSPeter Wemm 
35841c0c7eSNathan Whitehorn #define __ELF_WORD_SIZE 32
36841c0c7eSNathan Whitehorn 
37ffb66079SJohn Baldwin #ifdef COMPAT_FREEBSD11
38ffb66079SJohn Baldwin #define	_WANT_FREEBSD11_KEVENT
39ffb66079SJohn Baldwin #endif
40ffb66079SJohn Baldwin 
413ebc1248SPeter Wemm #include <sys/param.h>
423ebc1248SPeter Wemm #include <sys/bus.h>
434a144410SRobert Watson #include <sys/capsicum.h>
44f645b0b5SPoul-Henning Kamp #include <sys/clock.h>
453ebc1248SPeter Wemm #include <sys/exec.h>
463ebc1248SPeter Wemm #include <sys/fcntl.h>
473ebc1248SPeter Wemm #include <sys/filedesc.h>
483ebc1248SPeter Wemm #include <sys/imgact.h>
49413628a7SBjoern A. Zeeb #include <sys/jail.h>
503ebc1248SPeter Wemm #include <sys/kernel.h>
51a88d050dSJung-uk Kim #include <sys/limits.h>
5286665509SKonstantin Belousov #include <sys/linker.h>
533ebc1248SPeter Wemm #include <sys/lock.h>
543ebc1248SPeter Wemm #include <sys/malloc.h>
553ebc1248SPeter Wemm #include <sys/file.h>		/* Must come after sys/malloc.h */
56841c0c7eSNathan Whitehorn #include <sys/imgact.h>
57ecc44de7SPaul Saab #include <sys/mbuf.h>
583ebc1248SPeter Wemm #include <sys/mman.h>
593ebc1248SPeter Wemm #include <sys/module.h>
603ebc1248SPeter Wemm #include <sys/mount.h>
613ebc1248SPeter Wemm #include <sys/mutex.h>
62109ea24cSDavid E. O'Brien #include <sys/namei.h>
63e3e811a3SBrooks Davis #include <sys/priv.h>
643ebc1248SPeter Wemm #include <sys/proc.h>
6555648840SJohn Baldwin #include <sys/procctl.h>
6658b552dcSJohn Baldwin #include <sys/ptrace.h>
673ebc1248SPeter Wemm #include <sys/reboot.h>
683ebc1248SPeter Wemm #include <sys/resource.h>
693ebc1248SPeter Wemm #include <sys/resourcevar.h>
703ebc1248SPeter Wemm #include <sys/selinfo.h>
71efe5becaSPaul Saab #include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
723ebc1248SPeter Wemm #include <sys/pipe.h>		/* Must come after sys/selinfo.h */
733ebc1248SPeter Wemm #include <sys/signal.h>
743ebc1248SPeter Wemm #include <sys/signalvar.h>
753ebc1248SPeter Wemm #include <sys/socket.h>
763ebc1248SPeter Wemm #include <sys/socketvar.h>
773ebc1248SPeter Wemm #include <sys/stat.h>
78f2107e8dSJohn Baldwin #include <sys/syscall.h>
79fe8cdcaeSJohn Baldwin #include <sys/syscallsubr.h>
803ebc1248SPeter Wemm #include <sys/sysctl.h>
813ebc1248SPeter Wemm #include <sys/sysent.h>
823ebc1248SPeter Wemm #include <sys/sysproto.h>
83109ea24cSDavid E. O'Brien #include <sys/systm.h>
84cda9a0d1SDavid Xu #include <sys/thr.h>
85918966a2SJake Freeland #include <sys/timerfd.h>
8631df9c26SKonstantin Belousov #include <sys/timex.h>
873ebc1248SPeter Wemm #include <sys/unistd.h>
88cda9a0d1SDavid Xu #include <sys/ucontext.h>
89ddb3eb4eSOlivier Certner #include <sys/ucred.h>
903ebc1248SPeter Wemm #include <sys/vnode.h>
91b7e23e82SJohn Baldwin #include <sys/wait.h>
92fbb273bcSPaul Saab #include <sys/ipc.h>
933c39e0d8SJohn Baldwin #include <sys/msg.h>
943c39e0d8SJohn Baldwin #include <sys/sem.h>
95fbb273bcSPaul Saab #include <sys/shm.h>
96e3e811a3SBrooks Davis #include <sys/timeffc.h>
97ffb66079SJohn Baldwin #ifdef KTRACE
98ffb66079SJohn Baldwin #include <sys/ktrace.h>
99ffb66079SJohn Baldwin #endif
1003ebc1248SPeter Wemm 
101b38ff370SJamie Gritton #ifdef INET
102b38ff370SJamie Gritton #include <netinet/in.h>
103b38ff370SJamie Gritton #endif
104b38ff370SJamie Gritton 
1053ebc1248SPeter Wemm #include <vm/vm.h>
1063ebc1248SPeter Wemm #include <vm/vm_param.h>
1073ebc1248SPeter Wemm #include <vm/pmap.h>
1083ebc1248SPeter Wemm #include <vm/vm_map.h>
1093ebc1248SPeter Wemm #include <vm/vm_object.h>
1103ebc1248SPeter Wemm #include <vm/vm_extern.h>
1113ebc1248SPeter Wemm 
112e7abd4a0SPaul Saab #include <machine/cpu.h>
113841c0c7eSNathan Whitehorn #include <machine/elf.h>
114a7f67facSKonstantin Belousov #ifdef __amd64__
115a7f67facSKonstantin Belousov #include <machine/md_var.h>
116a7f67facSKonstantin Belousov #endif
117e7abd4a0SPaul Saab 
1186e6049e9SDavid E. O'Brien #include <security/audit/audit.h>
119ddb3eb4eSOlivier Certner #include <security/mac/mac_syscalls.h>
1206e6049e9SDavid E. O'Brien 
1211c7abef7SPeter Wemm #include <compat/freebsd32/freebsd32_util.h>
1221c7abef7SPeter Wemm #include <compat/freebsd32/freebsd32.h>
123d43c6fa4SJohn Baldwin #include <compat/freebsd32/freebsd32_ipc.h>
124d6f6b876SPawel Jakub Dawidek #include <compat/freebsd32/freebsd32_misc.h>
125c6511aeaSDavid Xu #include <compat/freebsd32/freebsd32_signal.h>
1261c7abef7SPeter Wemm #include <compat/freebsd32/freebsd32_proto.h>
1273ebc1248SPeter Wemm 
1285a2bbaceSKonstantin Belousov int compat_freebsd_32bit = 1;
1295a2bbaceSKonstantin Belousov 
1305a2bbaceSKonstantin Belousov static void
register_compat32_feature(void * arg)1315a2bbaceSKonstantin Belousov register_compat32_feature(void *arg)
1325a2bbaceSKonstantin Belousov {
1335a2bbaceSKonstantin Belousov 	if (!compat_freebsd_32bit)
1345a2bbaceSKonstantin Belousov 		return;
1355a2bbaceSKonstantin Belousov 
136bddc7a8aSKonstantin Belousov 	FEATURE_ADD("compat_freebsd32", "Compatible with 32-bit FreeBSD");
137bddc7a8aSKonstantin Belousov 	FEATURE_ADD("compat_freebsd_32bit",
138bddc7a8aSKonstantin Belousov 	    "Compatible with 32-bit FreeBSD (legacy feature name)");
1395a2bbaceSKonstantin Belousov }
1405a2bbaceSKonstantin Belousov SYSINIT(freebsd32, SI_SUB_EXEC, SI_ORDER_ANY, register_compat32_feature,
1415a2bbaceSKonstantin Belousov     NULL);
1421f4e9654SDavid E. O'Brien 
14358b552dcSJohn Baldwin struct ptrace_io_desc32 {
14458b552dcSJohn Baldwin 	int		piod_op;
14558b552dcSJohn Baldwin 	uint32_t	piod_offs;
14658b552dcSJohn Baldwin 	uint32_t	piod_addr;
14758b552dcSJohn Baldwin 	uint32_t	piod_len;
14858b552dcSJohn Baldwin };
14958b552dcSJohn Baldwin 
15058b552dcSJohn Baldwin struct ptrace_vm_entry32 {
15158b552dcSJohn Baldwin 	int		pve_entry;
15258b552dcSJohn Baldwin 	int		pve_timestamp;
15358b552dcSJohn Baldwin 	uint32_t	pve_start;
15458b552dcSJohn Baldwin 	uint32_t	pve_end;
15558b552dcSJohn Baldwin 	uint32_t	pve_offset;
15658b552dcSJohn Baldwin 	u_int		pve_prot;
15758b552dcSJohn Baldwin 	u_int		pve_pathlen;
15858b552dcSJohn Baldwin 	int32_t		pve_fileid;
15958b552dcSJohn Baldwin 	u_int		pve_fsid;
16058b552dcSJohn Baldwin 	uint32_t	pve_path;
16158b552dcSJohn Baldwin };
16258b552dcSJohn Baldwin 
163b4366092SJustin Hibbits #ifdef __amd64__
16460a8c422SPeter Wemm CTASSERT(sizeof(struct timeval32) == 8);
16560a8c422SPeter Wemm CTASSERT(sizeof(struct timespec32) == 8);
16674427aa4SJohn Baldwin CTASSERT(sizeof(struct itimerval32) == 16);
167afbd12c1SMaxim Sobolev CTASSERT(sizeof(struct bintime32) == 12);
1688299f9a5SEd Maste #else
1698299f9a5SEd Maste CTASSERT(sizeof(struct timeval32) == 16);
1708299f9a5SEd Maste CTASSERT(sizeof(struct timespec32) == 16);
1718299f9a5SEd Maste CTASSERT(sizeof(struct itimerval32) == 32);
1728299f9a5SEd Maste CTASSERT(sizeof(struct bintime32) == 16);
1739624d947SJuli Mallett #endif
1742e89f95dSBrooks Davis CTASSERT(sizeof(struct ostatfs32) == 256);
175b4366092SJustin Hibbits #ifdef __amd64__
17660a8c422SPeter Wemm CTASSERT(sizeof(struct rusage32) == 72);
1778299f9a5SEd Maste #else
1788299f9a5SEd Maste CTASSERT(sizeof(struct rusage32) == 88);
1799624d947SJuli Mallett #endif
18074427aa4SJohn Baldwin CTASSERT(sizeof(struct sigaltstack32) == 12);
181aef2a6a7SKonstantin Belousov #ifdef __amd64__
1822b34e843SKonstantin Belousov CTASSERT(sizeof(struct kevent32) == 56);
183aef2a6a7SKonstantin Belousov #else
184aef2a6a7SKonstantin Belousov CTASSERT(sizeof(struct kevent32) == 64);
185cfb2d93bSKonstantin Belousov #endif
18674427aa4SJohn Baldwin CTASSERT(sizeof(struct iovec32) == 8);
18774427aa4SJohn Baldwin CTASSERT(sizeof(struct msghdr32) == 28);
18869921123SKonstantin Belousov #ifdef __amd64__
18969921123SKonstantin Belousov CTASSERT(sizeof(struct stat32) == 208);
19069921123SKonstantin Belousov CTASSERT(sizeof(struct freebsd11_stat32) == 96);
1918299f9a5SEd Maste #else
1928299f9a5SEd Maste CTASSERT(sizeof(struct stat32) == 224);
1938299f9a5SEd Maste CTASSERT(sizeof(struct freebsd11_stat32) == 120);
1949624d947SJuli Mallett #endif
19574427aa4SJohn Baldwin CTASSERT(sizeof(struct sigaction32) == 24);
19674427aa4SJohn Baldwin 
19774427aa4SJohn Baldwin static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
19874427aa4SJohn Baldwin static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
1993f8455b0SEric van Gyzen static int freebsd32_user_clock_nanosleep(struct thread *td, clockid_t clock_id,
2003f8455b0SEric van Gyzen     int flags, const struct timespec32 *ua_rqtp, struct timespec32 *ua_rmtp);
20160a8c422SPeter Wemm 
2029847e91bSKonstantin Belousov void
freebsd32_rusage_out(const struct rusage * s,struct rusage32 * s32)2039847e91bSKonstantin Belousov freebsd32_rusage_out(const struct rusage *s, struct rusage32 *s32)
2049847e91bSKonstantin Belousov {
2059847e91bSKonstantin Belousov 
2069847e91bSKonstantin Belousov 	TV_CP(*s, *s32, ru_utime);
2079847e91bSKonstantin Belousov 	TV_CP(*s, *s32, ru_stime);
2089847e91bSKonstantin Belousov 	CP(*s, *s32, ru_maxrss);
2099847e91bSKonstantin Belousov 	CP(*s, *s32, ru_ixrss);
2109847e91bSKonstantin Belousov 	CP(*s, *s32, ru_idrss);
2119847e91bSKonstantin Belousov 	CP(*s, *s32, ru_isrss);
2129847e91bSKonstantin Belousov 	CP(*s, *s32, ru_minflt);
2139847e91bSKonstantin Belousov 	CP(*s, *s32, ru_majflt);
2149847e91bSKonstantin Belousov 	CP(*s, *s32, ru_nswap);
2159847e91bSKonstantin Belousov 	CP(*s, *s32, ru_inblock);
2169847e91bSKonstantin Belousov 	CP(*s, *s32, ru_oublock);
2179847e91bSKonstantin Belousov 	CP(*s, *s32, ru_msgsnd);
2189847e91bSKonstantin Belousov 	CP(*s, *s32, ru_msgrcv);
2199847e91bSKonstantin Belousov 	CP(*s, *s32, ru_nsignals);
2209847e91bSKonstantin Belousov 	CP(*s, *s32, ru_nvcsw);
2219847e91bSKonstantin Belousov 	CP(*s, *s32, ru_nivcsw);
2229847e91bSKonstantin Belousov }
2239847e91bSKonstantin Belousov 
2243ebc1248SPeter Wemm int
freebsd32_wait4(struct thread * td,struct freebsd32_wait4_args * uap)2251c7abef7SPeter Wemm freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
2263ebc1248SPeter Wemm {
227b7e23e82SJohn Baldwin 	int error, status;
228b7e23e82SJohn Baldwin 	struct rusage32 ru32;
22978c85e8dSJohn Baldwin 	struct rusage ru, *rup;
2303ebc1248SPeter Wemm 
23178c85e8dSJohn Baldwin 	if (uap->rusage != NULL)
23278c85e8dSJohn Baldwin 		rup = &ru;
23378c85e8dSJohn Baldwin 	else
23478c85e8dSJohn Baldwin 		rup = NULL;
23578c85e8dSJohn Baldwin 	error = kern_wait(td, uap->pid, &status, uap->options, rup);
2363ebc1248SPeter Wemm 	if (error)
2373ebc1248SPeter Wemm 		return (error);
238b7e23e82SJohn Baldwin 	if (uap->status != NULL)
239b7e23e82SJohn Baldwin 		error = copyout(&status, uap->status, sizeof(status));
240b7e23e82SJohn Baldwin 	if (uap->rusage != NULL && error == 0) {
2419847e91bSKonstantin Belousov 		freebsd32_rusage_out(&ru, &ru32);
242b7e23e82SJohn Baldwin 		error = copyout(&ru32, uap->rusage, sizeof(ru32));
2433ebc1248SPeter Wemm 	}
2443ebc1248SPeter Wemm 	return (error);
2453ebc1248SPeter Wemm }
2463ebc1248SPeter Wemm 
247f13b5a0fSKonstantin Belousov int
freebsd32_wait6(struct thread * td,struct freebsd32_wait6_args * uap)248f13b5a0fSKonstantin Belousov freebsd32_wait6(struct thread *td, struct freebsd32_wait6_args *uap)
249f13b5a0fSKonstantin Belousov {
250b35c2bcaSBrooks Davis 	struct __wrusage32 wru32;
251f13b5a0fSKonstantin Belousov 	struct __wrusage wru, *wrup;
252d060b420SBrooks Davis 	struct __siginfo32 si32;
253f13b5a0fSKonstantin Belousov 	struct __siginfo si, *sip;
254f13b5a0fSKonstantin Belousov 	int error, status;
255f13b5a0fSKonstantin Belousov 
256f13b5a0fSKonstantin Belousov 	if (uap->wrusage != NULL)
257f13b5a0fSKonstantin Belousov 		wrup = &wru;
258f13b5a0fSKonstantin Belousov 	else
259f13b5a0fSKonstantin Belousov 		wrup = NULL;
260f13b5a0fSKonstantin Belousov 	if (uap->info != NULL) {
261f13b5a0fSKonstantin Belousov 		sip = &si;
262f13b5a0fSKonstantin Belousov 		bzero(sip, sizeof(*sip));
263f13b5a0fSKonstantin Belousov 	} else
264f13b5a0fSKonstantin Belousov 		sip = NULL;
26548947eccSKonstantin Belousov 	error = kern_wait6(td, uap->idtype, PAIR32TO64(id_t, uap->id),
26648947eccSKonstantin Belousov 	    &status, uap->options, wrup, sip);
267f13b5a0fSKonstantin Belousov 	if (error != 0)
268f13b5a0fSKonstantin Belousov 		return (error);
269f13b5a0fSKonstantin Belousov 	if (uap->status != NULL)
270f13b5a0fSKonstantin Belousov 		error = copyout(&status, uap->status, sizeof(status));
271f13b5a0fSKonstantin Belousov 	if (uap->wrusage != NULL && error == 0) {
272f13b5a0fSKonstantin Belousov 		freebsd32_rusage_out(&wru.wru_self, &wru32.wru_self);
273f13b5a0fSKonstantin Belousov 		freebsd32_rusage_out(&wru.wru_children, &wru32.wru_children);
274f13b5a0fSKonstantin Belousov 		error = copyout(&wru32, uap->wrusage, sizeof(wru32));
275f13b5a0fSKonstantin Belousov 	}
276f13b5a0fSKonstantin Belousov 	if (uap->info != NULL && error == 0) {
277f13b5a0fSKonstantin Belousov 		siginfo_to_siginfo32 (&si, &si32);
278f13b5a0fSKonstantin Belousov 		error = copyout(&si32, uap->info, sizeof(si32));
279f13b5a0fSKonstantin Belousov 	}
280f13b5a0fSKonstantin Belousov 	return (error);
281f13b5a0fSKonstantin Belousov }
282f13b5a0fSKonstantin Belousov 
283c050455eSMarcel Moolenaar #ifdef COMPAT_FREEBSD4
2840a635741SJohn Baldwin static void
copy_statfs(struct statfs * in,struct ostatfs32 * out)2852e89f95dSBrooks Davis copy_statfs(struct statfs *in, struct ostatfs32 *out)
2863ebc1248SPeter Wemm {
2876308f39dSPaul Saab 
2887815c9e2SScott Long 	statfs_scale_blocks(in, INT32_MAX);
2896308f39dSPaul Saab 	bzero(out, sizeof(*out));
2903ebc1248SPeter Wemm 	CP(*in, *out, f_bsize);
291cc479ddaSJohn Baldwin 	out->f_iosize = MIN(in->f_iosize, INT32_MAX);
2923ebc1248SPeter Wemm 	CP(*in, *out, f_blocks);
2933ebc1248SPeter Wemm 	CP(*in, *out, f_bfree);
2943ebc1248SPeter Wemm 	CP(*in, *out, f_bavail);
295cc479ddaSJohn Baldwin 	out->f_files = MIN(in->f_files, INT32_MAX);
296cc479ddaSJohn Baldwin 	out->f_ffree = MIN(in->f_ffree, INT32_MAX);
2973ebc1248SPeter Wemm 	CP(*in, *out, f_fsid);
2983ebc1248SPeter Wemm 	CP(*in, *out, f_owner);
2993ebc1248SPeter Wemm 	CP(*in, *out, f_type);
3003ebc1248SPeter Wemm 	CP(*in, *out, f_flags);
3010a635741SJohn Baldwin 	out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
3020a635741SJohn Baldwin 	out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
3036308f39dSPaul Saab 	strlcpy(out->f_fstypename,
3046308f39dSPaul Saab 	      in->f_fstypename, MFSNAMELEN);
3056308f39dSPaul Saab 	strlcpy(out->f_mntonname,
3062e89f95dSBrooks Davis 	      in->f_mntonname, min(MNAMELEN, FREEBSD4_OMNAMELEN));
3070a635741SJohn Baldwin 	out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
3080a635741SJohn Baldwin 	out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
3096308f39dSPaul Saab 	strlcpy(out->f_mntfromname,
3102e89f95dSBrooks Davis 	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_OMNAMELEN));
3113ebc1248SPeter Wemm }
312c050455eSMarcel Moolenaar #endif
3133ebc1248SPeter Wemm 
3142b9d052dSBrooks Davis int
freebsd32_getfsstat(struct thread * td,struct freebsd32_getfsstat_args * uap)3152b9d052dSBrooks Davis freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)
3162b9d052dSBrooks Davis {
3172b9d052dSBrooks Davis 	size_t count;
3182b9d052dSBrooks Davis 	int error;
3192b9d052dSBrooks Davis 
3202b9d052dSBrooks Davis 	if (uap->bufsize < 0 || uap->bufsize > SIZE_MAX)
3212b9d052dSBrooks Davis 		return (EINVAL);
3222b9d052dSBrooks Davis 	error = kern_getfsstat(td, &uap->buf, uap->bufsize, &count,
3232b9d052dSBrooks Davis 	    UIO_USERSPACE, uap->mode);
3242b9d052dSBrooks Davis 	if (error == 0)
3252b9d052dSBrooks Davis 		td->td_retval[0] = count;
3262b9d052dSBrooks Davis 	return (error);
3272b9d052dSBrooks Davis }
3282b9d052dSBrooks Davis 
329c050455eSMarcel Moolenaar #ifdef COMPAT_FREEBSD4
3303ebc1248SPeter Wemm int
freebsd4_freebsd32_getfsstat(struct thread * td,struct freebsd4_freebsd32_getfsstat_args * uap)331607fa849SKonstantin Belousov freebsd4_freebsd32_getfsstat(struct thread *td,
332607fa849SKonstantin Belousov     struct freebsd4_freebsd32_getfsstat_args *uap)
3333ebc1248SPeter Wemm {
33413a82b96SPawel Jakub Dawidek 	struct statfs *buf, *sp;
3352e89f95dSBrooks Davis 	struct ostatfs32 stat32;
33676cd2549SPeter Wemm 	size_t count, size, copycount;
3373ebc1248SPeter Wemm 	int error;
3383ebc1248SPeter Wemm 
3392e89f95dSBrooks Davis 	count = uap->bufsize / sizeof(struct ostatfs32);
34013a82b96SPawel Jakub Dawidek 	size = count * sizeof(struct statfs);
34134ed0c63SJohn Baldwin 	error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE, uap->mode);
3423a996d6eSPawel Jakub Dawidek 	if (size > 0) {
34313a82b96SPawel Jakub Dawidek 		sp = buf;
34476cd2549SPeter Wemm 		copycount = count;
34576cd2549SPeter Wemm 		while (copycount > 0 && error == 0) {
3460a635741SJohn Baldwin 			copy_statfs(sp, &stat32);
34713a82b96SPawel Jakub Dawidek 			error = copyout(&stat32, uap->buf, sizeof(stat32));
34813a82b96SPawel Jakub Dawidek 			sp++;
34913a82b96SPawel Jakub Dawidek 			uap->buf++;
35076cd2549SPeter Wemm 			copycount--;
3513ebc1248SPeter Wemm 		}
3522f304845SKonstantin Belousov 		free(buf, M_STATFS);
3533ebc1248SPeter Wemm 	}
3541c73bcabSEdward Tomasz Napierala 	if (error == 0)
3551c73bcabSEdward Tomasz Napierala 		td->td_retval[0] = count;
3563ebc1248SPeter Wemm 	return (error);
3573ebc1248SPeter Wemm }
358c050455eSMarcel Moolenaar #endif
3593ebc1248SPeter Wemm 
3602b9d052dSBrooks Davis #ifdef COMPAT_FREEBSD11
3612b9d052dSBrooks Davis int
freebsd11_freebsd32_getfsstat(struct thread * td,struct freebsd11_freebsd32_getfsstat_args * uap)3622b9d052dSBrooks Davis freebsd11_freebsd32_getfsstat(struct thread *td,
3632b9d052dSBrooks Davis     struct freebsd11_freebsd32_getfsstat_args *uap)
3642b9d052dSBrooks Davis {
3652b9d052dSBrooks Davis 	return(kern_freebsd11_getfsstat(td, uap->buf, uap->bufsize,
3662b9d052dSBrooks Davis 	    uap->mode));
3672b9d052dSBrooks Davis }
3682b9d052dSBrooks Davis #endif
3692b9d052dSBrooks Davis 
3703ebc1248SPeter Wemm int
freebsd32_sigaltstack(struct thread * td,struct freebsd32_sigaltstack_args * uap)3711c7abef7SPeter Wemm freebsd32_sigaltstack(struct thread *td,
3721c7abef7SPeter Wemm 		      struct freebsd32_sigaltstack_args *uap)
3733ebc1248SPeter Wemm {
374fe8cdcaeSJohn Baldwin 	struct sigaltstack32 s32;
375fe8cdcaeSJohn Baldwin 	struct sigaltstack ss, oss, *ssp;
3763ebc1248SPeter Wemm 	int error;
3773ebc1248SPeter Wemm 
378fe8cdcaeSJohn Baldwin 	if (uap->ss != NULL) {
379fe8cdcaeSJohn Baldwin 		error = copyin(uap->ss, &s32, sizeof(s32));
3803ebc1248SPeter Wemm 		if (error)
3813ebc1248SPeter Wemm 			return (error);
382fe8cdcaeSJohn Baldwin 		PTRIN_CP(s32, ss, ss_sp);
383fe8cdcaeSJohn Baldwin 		CP(s32, ss, ss_size);
384fe8cdcaeSJohn Baldwin 		CP(s32, ss, ss_flags);
385fe8cdcaeSJohn Baldwin 		ssp = &ss;
386fe8cdcaeSJohn Baldwin 	} else
387fe8cdcaeSJohn Baldwin 		ssp = NULL;
388fe8cdcaeSJohn Baldwin 	error = kern_sigaltstack(td, ssp, &oss);
389fe8cdcaeSJohn Baldwin 	if (error == 0 && uap->oss != NULL) {
390fe8cdcaeSJohn Baldwin 		PTROUT_CP(oss, s32, ss_sp);
391fe8cdcaeSJohn Baldwin 		CP(oss, s32, ss_size);
392fe8cdcaeSJohn Baldwin 		CP(oss, s32, ss_flags);
393fe8cdcaeSJohn Baldwin 		error = copyout(&s32, uap->oss, sizeof(s32));
3943ebc1248SPeter Wemm 	}
3953ebc1248SPeter Wemm 	return (error);
3963ebc1248SPeter Wemm }
3973ebc1248SPeter Wemm 
39838765a31SJohn Baldwin /*
39938765a31SJohn Baldwin  * Custom version of exec_copyin_args() so that we can translate
40038765a31SJohn Baldwin  * the pointers.
40138765a31SJohn Baldwin  */
4020b53d156SKonstantin Belousov int
freebsd32_exec_copyin_args(struct image_args * args,const char * fname,uint32_t * argv,uint32_t * envv)40312e69f96SBrooks Davis freebsd32_exec_copyin_args(struct image_args *args, const char *fname,
40415581af7SWuyang Chung     uint32_t *argv, uint32_t *envv)
40538765a31SJohn Baldwin {
40638765a31SJohn Baldwin 	char *argp, *envp;
407cc5aa0a4SJohn Baldwin 	uint32_t *p32, arg;
40838765a31SJohn Baldwin 	int error;
40938765a31SJohn Baldwin 
41038765a31SJohn Baldwin 	bzero(args, sizeof(*args));
41138765a31SJohn Baldwin 	if (argv == NULL)
41238765a31SJohn Baldwin 		return (EFAULT);
41338765a31SJohn Baldwin 
41438765a31SJohn Baldwin 	/*
4152af6e14dSAlan Cox 	 * Allocate demand-paged memory for the file name, argument, and
4162af6e14dSAlan Cox 	 * environment strings.
41738765a31SJohn Baldwin 	 */
4182af6e14dSAlan Cox 	error = exec_alloc_args(args);
4192af6e14dSAlan Cox 	if (error != 0)
4202af6e14dSAlan Cox 		return (error);
42138765a31SJohn Baldwin 
42238765a31SJohn Baldwin 	/*
42338765a31SJohn Baldwin 	 * Copy the file name.
42438765a31SJohn Baldwin 	 */
42515581af7SWuyang Chung 	error = exec_args_add_fname(args, fname, UIO_USERSPACE);
42638765a31SJohn Baldwin 	if (error != 0)
42768ff3c24SStephan Uphoff 		goto err_exit;
42838765a31SJohn Baldwin 
42938765a31SJohn Baldwin 	/*
43038765a31SJohn Baldwin 	 * extract arguments first
43138765a31SJohn Baldwin 	 */
43238765a31SJohn Baldwin 	p32 = argv;
43338765a31SJohn Baldwin 	for (;;) {
43438765a31SJohn Baldwin 		error = copyin(p32++, &arg, sizeof(arg));
43538765a31SJohn Baldwin 		if (error)
43668ff3c24SStephan Uphoff 			goto err_exit;
43738765a31SJohn Baldwin 		if (arg == 0)
43838765a31SJohn Baldwin 			break;
43938765a31SJohn Baldwin 		argp = PTRIN(arg);
440f373437aSBrooks Davis 		error = exec_args_add_arg(args, argp, UIO_USERSPACE);
441f373437aSBrooks Davis 		if (error != 0)
44268ff3c24SStephan Uphoff 			goto err_exit;
44338765a31SJohn Baldwin 	}
44438765a31SJohn Baldwin 
44538765a31SJohn Baldwin 	/*
44638765a31SJohn Baldwin 	 * extract environment strings
44738765a31SJohn Baldwin 	 */
44838765a31SJohn Baldwin 	if (envv) {
44938765a31SJohn Baldwin 		p32 = envv;
45038765a31SJohn Baldwin 		for (;;) {
45138765a31SJohn Baldwin 			error = copyin(p32++, &arg, sizeof(arg));
45238765a31SJohn Baldwin 			if (error)
45368ff3c24SStephan Uphoff 				goto err_exit;
45438765a31SJohn Baldwin 			if (arg == 0)
45538765a31SJohn Baldwin 				break;
45638765a31SJohn Baldwin 			envp = PTRIN(arg);
457f373437aSBrooks Davis 			error = exec_args_add_env(args, envp, UIO_USERSPACE);
458f373437aSBrooks Davis 			if (error != 0)
45968ff3c24SStephan Uphoff 				goto err_exit;
46038765a31SJohn Baldwin 		}
46138765a31SJohn Baldwin 	}
46238765a31SJohn Baldwin 
46338765a31SJohn Baldwin 	return (0);
46468ff3c24SStephan Uphoff 
46568ff3c24SStephan Uphoff err_exit:
46669a8f9e3SAlan Cox 	exec_free_args(args);
46768ff3c24SStephan Uphoff 	return (error);
46838765a31SJohn Baldwin }
46938765a31SJohn Baldwin 
4703ebc1248SPeter Wemm int
freebsd32_execve(struct thread * td,struct freebsd32_execve_args * uap)4711c7abef7SPeter Wemm freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
4723ebc1248SPeter Wemm {
47338765a31SJohn Baldwin 	struct image_args eargs;
4747b445033SKonstantin Belousov 	struct vmspace *oldvmspace;
4753ebc1248SPeter Wemm 	int error;
4763ebc1248SPeter Wemm 
4777b445033SKonstantin Belousov 	error = pre_execve(td, &oldvmspace);
4787b445033SKonstantin Belousov 	if (error != 0)
4797b445033SKonstantin Belousov 		return (error);
48015581af7SWuyang Chung 	error = freebsd32_exec_copyin_args(&eargs, uap->fname, uap->argv,
48115581af7SWuyang Chung 	    uap->envv);
48238765a31SJohn Baldwin 	if (error == 0)
483aaf78c16SKonstantin Belousov 		error = kern_execve(td, &eargs, NULL, oldvmspace);
4847b445033SKonstantin Belousov 	post_execve(td, error, oldvmspace);
485275c821dSKyle Evans 	AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td);
48638765a31SJohn Baldwin 	return (error);
4873ebc1248SPeter Wemm }
4883ebc1248SPeter Wemm 
4894f1e7213SKonstantin Belousov int
freebsd32_fexecve(struct thread * td,struct freebsd32_fexecve_args * uap)4904f1e7213SKonstantin Belousov freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
4914f1e7213SKonstantin Belousov {
4924f1e7213SKonstantin Belousov 	struct image_args eargs;
4937b445033SKonstantin Belousov 	struct vmspace *oldvmspace;
4944f1e7213SKonstantin Belousov 	int error;
4954f1e7213SKonstantin Belousov 
4967b445033SKonstantin Belousov 	error = pre_execve(td, &oldvmspace);
4977b445033SKonstantin Belousov 	if (error != 0)
4987b445033SKonstantin Belousov 		return (error);
49915581af7SWuyang Chung 	error = freebsd32_exec_copyin_args(&eargs, NULL, uap->argv, uap->envv);
5004f1e7213SKonstantin Belousov 	if (error == 0) {
5014f1e7213SKonstantin Belousov 		eargs.fd = uap->fd;
502aaf78c16SKonstantin Belousov 		error = kern_execve(td, &eargs, NULL, oldvmspace);
5034f1e7213SKonstantin Belousov 	}
5047b445033SKonstantin Belousov 	post_execve(td, error, oldvmspace);
505275c821dSKyle Evans 	AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td);
5064f1e7213SKonstantin Belousov 	return (error);
5074f1e7213SKonstantin Belousov }
5084f1e7213SKonstantin Belousov 
50969921123SKonstantin Belousov int
freebsd32_mknodat(struct thread * td,struct freebsd32_mknodat_args * uap)5109a38df59SBrooks Davis freebsd32_mknodat(struct thread *td, struct freebsd32_mknodat_args *uap)
51169921123SKonstantin Belousov {
51269921123SKonstantin Belousov 
5139a38df59SBrooks Davis 	return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE,
5149a38df59SBrooks Davis 	    uap->mode, PAIR32TO64(dev_t, uap->dev)));
51569921123SKonstantin Belousov }
51669921123SKonstantin Belousov 
5173ebc1248SPeter Wemm int
freebsd32_mprotect(struct thread * td,struct freebsd32_mprotect_args * uap)518f8244106SMarcel Moolenaar freebsd32_mprotect(struct thread *td, struct freebsd32_mprotect_args *uap)
519f8244106SMarcel Moolenaar {
52069cdfcefSEdward Tomasz Napierala 	int prot;
521f8244106SMarcel Moolenaar 
52269cdfcefSEdward Tomasz Napierala 	prot = uap->prot;
523e7d939bdSMarcel Moolenaar #if defined(__amd64__)
52469cdfcefSEdward Tomasz Napierala 	if (i386_read_exec && (prot & PROT_READ) != 0)
52569cdfcefSEdward Tomasz Napierala 		prot |= PROT_EXEC;
526f8244106SMarcel Moolenaar #endif
527496ab053SKonstantin Belousov 	return (kern_mprotect(td, (uintptr_t)PTRIN(uap->addr), uap->len,
5289b65fa69SKonstantin Belousov 	    prot, 0));
529f8244106SMarcel Moolenaar }
530f8244106SMarcel Moolenaar 
531f8244106SMarcel Moolenaar int
freebsd32_mmap(struct thread * td,struct freebsd32_mmap_args * uap)5321c7abef7SPeter Wemm freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
5333ebc1248SPeter Wemm {
53469cdfcefSEdward Tomasz Napierala 	int prot;
5353ebc1248SPeter Wemm 
53669cdfcefSEdward Tomasz Napierala 	prot = uap->prot;
537e7d939bdSMarcel Moolenaar #if defined(__amd64__)
538126b36a2SKonstantin Belousov 	if (i386_read_exec && (prot & PROT_READ))
539488a1605SMarcel Moolenaar 		prot |= PROT_EXEC;
540488a1605SMarcel Moolenaar #endif
541488a1605SMarcel Moolenaar 
5427a1591c1SBrooks Davis 	return (kern_mmap(td, &(struct mmap_req){
5437a1591c1SBrooks Davis 		.mr_hint = (uintptr_t)uap->addr,
5447a1591c1SBrooks Davis 		.mr_len = uap->len,
5457a1591c1SBrooks Davis 		.mr_prot = prot,
5467a1591c1SBrooks Davis 		.mr_flags = uap->flags,
5477a1591c1SBrooks Davis 		.mr_fd = uap->fd,
5487a1591c1SBrooks Davis 		.mr_pos = PAIR32TO64(off_t, uap->pos),
5497a1591c1SBrooks Davis 	    }));
5503ebc1248SPeter Wemm }
5513ebc1248SPeter Wemm 
5525aa69f9cSPeter Wemm #ifdef COMPAT_FREEBSD6
5535aa69f9cSPeter Wemm int
freebsd6_freebsd32_mmap(struct thread * td,struct freebsd6_freebsd32_mmap_args * uap)554995b8f4fSKonstantin Belousov freebsd6_freebsd32_mmap(struct thread *td,
555995b8f4fSKonstantin Belousov     struct freebsd6_freebsd32_mmap_args *uap)
5565aa69f9cSPeter Wemm {
557496ab053SKonstantin Belousov 	int prot;
5585aa69f9cSPeter Wemm 
559496ab053SKonstantin Belousov 	prot = uap->prot;
560496ab053SKonstantin Belousov #if defined(__amd64__)
561496ab053SKonstantin Belousov 	if (i386_read_exec && (prot & PROT_READ))
562496ab053SKonstantin Belousov 		prot |= PROT_EXEC;
563496ab053SKonstantin Belousov #endif
5645aa69f9cSPeter Wemm 
5657a1591c1SBrooks Davis 	return (kern_mmap(td, &(struct mmap_req){
5667a1591c1SBrooks Davis 		.mr_hint = (uintptr_t)uap->addr,
5677a1591c1SBrooks Davis 		.mr_len = uap->len,
5687a1591c1SBrooks Davis 		.mr_prot = prot,
5697a1591c1SBrooks Davis 		.mr_flags = uap->flags,
5707a1591c1SBrooks Davis 		.mr_fd = uap->fd,
5717a1591c1SBrooks Davis 		.mr_pos = PAIR32TO64(off_t, uap->pos),
5727a1591c1SBrooks Davis 	    }));
5735aa69f9cSPeter Wemm }
5745aa69f9cSPeter Wemm #endif
5755aa69f9cSPeter Wemm 
57601ce7fcaSBrooks Davis #ifdef COMPAT_43
57701ce7fcaSBrooks Davis int
ofreebsd32_mmap(struct thread * td,struct ofreebsd32_mmap_args * uap)57801ce7fcaSBrooks Davis ofreebsd32_mmap(struct thread *td, struct ofreebsd32_mmap_args *uap)
57901ce7fcaSBrooks Davis {
58001ce7fcaSBrooks Davis 	return (kern_ommap(td, (uintptr_t)uap->addr, uap->len, uap->prot,
58101ce7fcaSBrooks Davis 	    uap->flags, uap->fd, uap->pos));
58201ce7fcaSBrooks Davis }
58301ce7fcaSBrooks Davis #endif
58401ce7fcaSBrooks Davis 
5853ebc1248SPeter Wemm int
freebsd32_setitimer(struct thread * td,struct freebsd32_setitimer_args * uap)5861c7abef7SPeter Wemm freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
5873ebc1248SPeter Wemm {
58838765a31SJohn Baldwin 	struct itimerval itv, oitv, *itvp;
58938765a31SJohn Baldwin 	struct itimerval32 i32;
5903ebc1248SPeter Wemm 	int error;
5913ebc1248SPeter Wemm 
59238765a31SJohn Baldwin 	if (uap->itv != NULL) {
59338765a31SJohn Baldwin 		error = copyin(uap->itv, &i32, sizeof(i32));
5943ebc1248SPeter Wemm 		if (error)
5953ebc1248SPeter Wemm 			return (error);
59638765a31SJohn Baldwin 		TV_CP(i32, itv, it_interval);
59738765a31SJohn Baldwin 		TV_CP(i32, itv, it_value);
59838765a31SJohn Baldwin 		itvp = &itv;
59938765a31SJohn Baldwin 	} else
60038765a31SJohn Baldwin 		itvp = NULL;
60138765a31SJohn Baldwin 	error = kern_setitimer(td, uap->which, itvp, &oitv);
60238765a31SJohn Baldwin 	if (error || uap->oitv == NULL)
6033ebc1248SPeter Wemm 		return (error);
60438765a31SJohn Baldwin 	TV_CP(oitv, i32, it_interval);
60538765a31SJohn Baldwin 	TV_CP(oitv, i32, it_value);
60638765a31SJohn Baldwin 	return (copyout(&i32, uap->oitv, sizeof(i32)));
6073ebc1248SPeter Wemm }
6083ebc1248SPeter Wemm 
6093ebc1248SPeter Wemm int
freebsd32_getitimer(struct thread * td,struct freebsd32_getitimer_args * uap)610996a568eSPeter Wemm freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
611996a568eSPeter Wemm {
61238765a31SJohn Baldwin 	struct itimerval itv;
61338765a31SJohn Baldwin 	struct itimerval32 i32;
614996a568eSPeter Wemm 	int error;
615996a568eSPeter Wemm 
61638765a31SJohn Baldwin 	error = kern_getitimer(td, uap->which, &itv);
61738765a31SJohn Baldwin 	if (error || uap->itv == NULL)
618996a568eSPeter Wemm 		return (error);
61938765a31SJohn Baldwin 	TV_CP(itv, i32, it_interval);
62038765a31SJohn Baldwin 	TV_CP(itv, i32, it_value);
62138765a31SJohn Baldwin 	return (copyout(&i32, uap->itv, sizeof(i32)));
622996a568eSPeter Wemm }
623996a568eSPeter Wemm 
624996a568eSPeter Wemm int
freebsd32_select(struct thread * td,struct freebsd32_select_args * uap)6251c7abef7SPeter Wemm freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
6263ebc1248SPeter Wemm {
62738765a31SJohn Baldwin 	struct timeval32 tv32;
62838765a31SJohn Baldwin 	struct timeval tv, *tvp;
6293ebc1248SPeter Wemm 	int error;
6303ebc1248SPeter Wemm 
63138765a31SJohn Baldwin 	if (uap->tv != NULL) {
63238765a31SJohn Baldwin 		error = copyin(uap->tv, &tv32, sizeof(tv32));
6333ebc1248SPeter Wemm 		if (error)
6343ebc1248SPeter Wemm 			return (error);
63538765a31SJohn Baldwin 		CP(tv32, tv, tv_sec);
63638765a31SJohn Baldwin 		CP(tv32, tv, tv_usec);
63738765a31SJohn Baldwin 		tvp = &tv;
63838765a31SJohn Baldwin 	} else
63938765a31SJohn Baldwin 		tvp = NULL;
6403ebc1248SPeter Wemm 	/*
64138765a31SJohn Baldwin 	 * XXX Do pointers need PTRIN()?
6423ebc1248SPeter Wemm 	 */
643b55ef216SKonstantin Belousov 	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
644b55ef216SKonstantin Belousov 	    sizeof(int32_t) * 8));
6453ebc1248SPeter Wemm }
6463ebc1248SPeter Wemm 
647066d836bSKonstantin Belousov int
freebsd32_pselect(struct thread * td,struct freebsd32_pselect_args * uap)648066d836bSKonstantin Belousov freebsd32_pselect(struct thread *td, struct freebsd32_pselect_args *uap)
649066d836bSKonstantin Belousov {
650066d836bSKonstantin Belousov 	struct timespec32 ts32;
651066d836bSKonstantin Belousov 	struct timespec ts;
652066d836bSKonstantin Belousov 	struct timeval tv, *tvp;
653066d836bSKonstantin Belousov 	sigset_t set, *uset;
654066d836bSKonstantin Belousov 	int error;
655066d836bSKonstantin Belousov 
656066d836bSKonstantin Belousov 	if (uap->ts != NULL) {
657066d836bSKonstantin Belousov 		error = copyin(uap->ts, &ts32, sizeof(ts32));
658066d836bSKonstantin Belousov 		if (error != 0)
659066d836bSKonstantin Belousov 			return (error);
660066d836bSKonstantin Belousov 		CP(ts32, ts, tv_sec);
661066d836bSKonstantin Belousov 		CP(ts32, ts, tv_nsec);
662066d836bSKonstantin Belousov 		TIMESPEC_TO_TIMEVAL(&tv, &ts);
663066d836bSKonstantin Belousov 		tvp = &tv;
664066d836bSKonstantin Belousov 	} else
665066d836bSKonstantin Belousov 		tvp = NULL;
666066d836bSKonstantin Belousov 	if (uap->sm != NULL) {
667066d836bSKonstantin Belousov 		error = copyin(uap->sm, &set, sizeof(set));
668066d836bSKonstantin Belousov 		if (error != 0)
669066d836bSKonstantin Belousov 			return (error);
670066d836bSKonstantin Belousov 		uset = &set;
671066d836bSKonstantin Belousov 	} else
672066d836bSKonstantin Belousov 		uset = NULL;
673066d836bSKonstantin Belousov 	/*
674066d836bSKonstantin Belousov 	 * XXX Do pointers need PTRIN()?
675066d836bSKonstantin Belousov 	 */
676066d836bSKonstantin Belousov 	error = kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
677066d836bSKonstantin Belousov 	    uset, sizeof(int32_t) * 8);
678066d836bSKonstantin Belousov 	return (error);
679066d836bSKonstantin Belousov }
680066d836bSKonstantin Belousov 
6816534c173SKonstantin Belousov static void
freebsd32_kevent_to_kevent32(const struct kevent * kevp,struct kevent32 * ks32)6826534c173SKonstantin Belousov freebsd32_kevent_to_kevent32(const struct kevent *kevp, struct kevent32 *ks32)
6836534c173SKonstantin Belousov {
6846534c173SKonstantin Belousov 	uint64_t e;
6856534c173SKonstantin Belousov 	int j;
6866534c173SKonstantin Belousov 
6876534c173SKonstantin Belousov 	CP(*kevp, *ks32, ident);
6886534c173SKonstantin Belousov 	CP(*kevp, *ks32, filter);
6896534c173SKonstantin Belousov 	CP(*kevp, *ks32, flags);
6906534c173SKonstantin Belousov 	CP(*kevp, *ks32, fflags);
6916534c173SKonstantin Belousov #if BYTE_ORDER == LITTLE_ENDIAN
6926534c173SKonstantin Belousov 	ks32->data1 = kevp->data;
6936534c173SKonstantin Belousov 	ks32->data2 = kevp->data >> 32;
6946534c173SKonstantin Belousov #else
6956534c173SKonstantin Belousov 	ks32->data1 = kevp->data >> 32;
6966534c173SKonstantin Belousov 	ks32->data2 = kevp->data;
6976534c173SKonstantin Belousov #endif
6986534c173SKonstantin Belousov 	PTROUT_CP(*kevp, *ks32, udata);
6996534c173SKonstantin Belousov 	for (j = 0; j < nitems(kevp->ext); j++) {
7006534c173SKonstantin Belousov 		e = kevp->ext[j];
7016534c173SKonstantin Belousov #if BYTE_ORDER == LITTLE_ENDIAN
7026534c173SKonstantin Belousov 		ks32->ext64[2 * j] = e;
7036534c173SKonstantin Belousov 		ks32->ext64[2 * j + 1] = e >> 32;
7046534c173SKonstantin Belousov #else
7056534c173SKonstantin Belousov 		ks32->ext64[2 * j] = e >> 32;
7066534c173SKonstantin Belousov 		ks32->ext64[2 * j + 1] = e;
7076534c173SKonstantin Belousov #endif
7086534c173SKonstantin Belousov 	}
7096534c173SKonstantin Belousov }
7106534c173SKonstantin Belousov 
711fa8fdd80SKonstantin Belousov void
freebsd32_kinfo_knote_to_32(const struct kinfo_knote * kin,struct kinfo_knote32 * kin32)712fa8fdd80SKonstantin Belousov freebsd32_kinfo_knote_to_32(const struct kinfo_knote *kin,
713fa8fdd80SKonstantin Belousov     struct kinfo_knote32 *kin32)
714fa8fdd80SKonstantin Belousov {
715fa8fdd80SKonstantin Belousov 	memset(kin32, 0, sizeof(*kin32));
716fa8fdd80SKonstantin Belousov 	CP(*kin, *kin32, knt_kq_fd);
717fa8fdd80SKonstantin Belousov 	freebsd32_kevent_to_kevent32(&kin->knt_event, &kin32->knt_event);
718fa8fdd80SKonstantin Belousov 	CP(*kin, *kin32, knt_status);
719fa8fdd80SKonstantin Belousov 	CP(*kin, *kin32, knt_extdata);
720fa8fdd80SKonstantin Belousov 	switch (kin->knt_extdata) {
721fa8fdd80SKonstantin Belousov 	case KNOTE_EXTDATA_NONE:
722fa8fdd80SKonstantin Belousov 		break;
723fa8fdd80SKonstantin Belousov 	case KNOTE_EXTDATA_VNODE:
724fa8fdd80SKonstantin Belousov 		CP(*kin, *kin32, knt_vnode.knt_vnode_type);
725fa8fdd80SKonstantin Belousov #if BYTE_ORDER == LITTLE_ENDIAN
726fa8fdd80SKonstantin Belousov 		kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.
727fa8fdd80SKonstantin Belousov 		    knt_vnode_fsid;
728fa8fdd80SKonstantin Belousov 		kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.
729fa8fdd80SKonstantin Belousov 		    knt_vnode_fsid >> 32;
730fa8fdd80SKonstantin Belousov 		kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.
731fa8fdd80SKonstantin Belousov 		    knt_vnode_fileid;
732fa8fdd80SKonstantin Belousov 		kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.
733fa8fdd80SKonstantin Belousov 		    knt_vnode_fileid >> 32;
734fa8fdd80SKonstantin Belousov #else
735fa8fdd80SKonstantin Belousov 		kin32->knt_vnode.knt_vnode_fsid[1] = kin->knt_vnode.
736fa8fdd80SKonstantin Belousov 		    knt_vnode_fsid;
737fa8fdd80SKonstantin Belousov 		kin32->knt_vnode.knt_vnode_fsid[0] = kin->knt_vnode.
738fa8fdd80SKonstantin Belousov 		    knt_vnode_fsid >> 32;
739fa8fdd80SKonstantin Belousov 		kin32->knt_vnode.knt_vnode_fileid[1] = kin->knt_vnode.
740fa8fdd80SKonstantin Belousov 		    knt_vnode_fileid;
741fa8fdd80SKonstantin Belousov 		kin32->knt_vnode.knt_vnode_fileid[0] = kin->knt_vnode.
742fa8fdd80SKonstantin Belousov 		    knt_vnode_fileid >> 32;
743fa8fdd80SKonstantin Belousov #endif
744fa8fdd80SKonstantin Belousov 		memcpy(kin32->knt_vnode.knt_vnode_fullpath,
745fa8fdd80SKonstantin Belousov 		    kin->knt_vnode.knt_vnode_fullpath, PATH_MAX);
746fa8fdd80SKonstantin Belousov 		break;
747fa8fdd80SKonstantin Belousov 	case KNOTE_EXTDATA_PIPE:
748fa8fdd80SKonstantin Belousov #if BYTE_ORDER == LITTLE_ENDIAN
749fa8fdd80SKonstantin Belousov 		kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.knt_pipe_ino;
750fa8fdd80SKonstantin Belousov 		kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.
751fa8fdd80SKonstantin Belousov 		    knt_pipe_ino >> 32;
752fa8fdd80SKonstantin Belousov #else
753fa8fdd80SKonstantin Belousov 		kin32->knt_pipe.knt_pipe_ino[1] = kin->knt_pipe.knt_pipe_ino;
754fa8fdd80SKonstantin Belousov 		kin32->knt_pipe.knt_pipe_ino[0] = kin->knt_pipe.
755fa8fdd80SKonstantin Belousov 		    knt_pipe_ino >> 32;
756fa8fdd80SKonstantin Belousov #endif
757fa8fdd80SKonstantin Belousov 		break;
758fa8fdd80SKonstantin Belousov 	}
759fa8fdd80SKonstantin Belousov }
760fa8fdd80SKonstantin Belousov 
761efe5becaSPaul Saab /*
762efe5becaSPaul Saab  * Copy 'count' items into the destination list pointed to by uap->eventlist.
763efe5becaSPaul Saab  */
764efe5becaSPaul Saab static int
freebsd32_kevent_copyout(void * arg,struct kevent * kevp,int count)765efe5becaSPaul Saab freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
766efe5becaSPaul Saab {
767efe5becaSPaul Saab 	struct freebsd32_kevent_args *uap;
768efe5becaSPaul Saab 	struct kevent32	ks32[KQ_NEVENTS];
7696534c173SKonstantin Belousov 	int i, error;
770efe5becaSPaul Saab 
771efe5becaSPaul Saab 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
772efe5becaSPaul Saab 	uap = (struct freebsd32_kevent_args *)arg;
773efe5becaSPaul Saab 
7746534c173SKonstantin Belousov 	for (i = 0; i < count; i++)
7756534c173SKonstantin Belousov 		freebsd32_kevent_to_kevent32(&kevp[i], &ks32[i]);
7762b34e843SKonstantin Belousov 	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
7772b34e843SKonstantin Belousov 	if (error == 0)
7782b34e843SKonstantin Belousov 		uap->eventlist += count;
7792b34e843SKonstantin Belousov 	return (error);
7802b34e843SKonstantin Belousov }
7812b34e843SKonstantin Belousov 
7822b34e843SKonstantin Belousov /*
7832b34e843SKonstantin Belousov  * Copy 'count' items from the list pointed to by uap->changelist.
7842b34e843SKonstantin Belousov  */
7852b34e843SKonstantin Belousov static int
freebsd32_kevent_copyin(void * arg,struct kevent * kevp,int count)7862b34e843SKonstantin Belousov freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
7872b34e843SKonstantin Belousov {
7882b34e843SKonstantin Belousov 	struct freebsd32_kevent_args *uap;
7892b34e843SKonstantin Belousov 	struct kevent32	ks32[KQ_NEVENTS];
7902b34e843SKonstantin Belousov 	uint64_t e;
7912b34e843SKonstantin Belousov 	int i, j, error;
7922b34e843SKonstantin Belousov 
7932b34e843SKonstantin Belousov 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
7942b34e843SKonstantin Belousov 	uap = (struct freebsd32_kevent_args *)arg;
7952b34e843SKonstantin Belousov 
7962b34e843SKonstantin Belousov 	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
7972b34e843SKonstantin Belousov 	if (error)
7982b34e843SKonstantin Belousov 		goto done;
7992b34e843SKonstantin Belousov 	uap->changelist += count;
8002b34e843SKonstantin Belousov 
8012b34e843SKonstantin Belousov 	for (i = 0; i < count; i++) {
8022b34e843SKonstantin Belousov 		CP(ks32[i], kevp[i], ident);
8032b34e843SKonstantin Belousov 		CP(ks32[i], kevp[i], filter);
8042b34e843SKonstantin Belousov 		CP(ks32[i], kevp[i], flags);
8052b34e843SKonstantin Belousov 		CP(ks32[i], kevp[i], fflags);
8062b34e843SKonstantin Belousov 		kevp[i].data = PAIR32TO64(uint64_t, ks32[i].data);
8072b34e843SKonstantin Belousov 		PTRIN_CP(ks32[i], kevp[i], udata);
8082b34e843SKonstantin Belousov 		for (j = 0; j < nitems(kevp->ext); j++) {
8092b34e843SKonstantin Belousov #if BYTE_ORDER == LITTLE_ENDIAN
8102b34e843SKonstantin Belousov 			e = ks32[i].ext64[2 * j + 1];
8112b34e843SKonstantin Belousov 			e <<= 32;
8122b34e843SKonstantin Belousov 			e += ks32[i].ext64[2 * j];
8132b34e843SKonstantin Belousov #else
8142b34e843SKonstantin Belousov 			e = ks32[i].ext64[2 * j];
8152b34e843SKonstantin Belousov 			e <<= 32;
8162b34e843SKonstantin Belousov 			e += ks32[i].ext64[2 * j + 1];
8172b34e843SKonstantin Belousov #endif
8182b34e843SKonstantin Belousov 			kevp[i].ext[j] = e;
8192b34e843SKonstantin Belousov 		}
8202b34e843SKonstantin Belousov 	}
8212b34e843SKonstantin Belousov done:
8222b34e843SKonstantin Belousov 	return (error);
8232b34e843SKonstantin Belousov }
8242b34e843SKonstantin Belousov 
8252b34e843SKonstantin Belousov int
freebsd32_kevent(struct thread * td,struct freebsd32_kevent_args * uap)8262b34e843SKonstantin Belousov freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
8272b34e843SKonstantin Belousov {
8282b34e843SKonstantin Belousov 	struct timespec32 ts32;
8292b34e843SKonstantin Belousov 	struct timespec ts, *tsp;
8302b34e843SKonstantin Belousov 	struct kevent_copyops k_ops = {
8312b34e843SKonstantin Belousov 		.arg = uap,
8322b34e843SKonstantin Belousov 		.k_copyout = freebsd32_kevent_copyout,
8332b34e843SKonstantin Belousov 		.k_copyin = freebsd32_kevent_copyin,
8342b34e843SKonstantin Belousov 	};
835ffb66079SJohn Baldwin #ifdef KTRACE
836ffb66079SJohn Baldwin 	struct kevent32 *eventlist = uap->eventlist;
837ffb66079SJohn Baldwin #endif
8382b34e843SKonstantin Belousov 	int error;
8392b34e843SKonstantin Belousov 
8402b34e843SKonstantin Belousov 	if (uap->timeout) {
8412b34e843SKonstantin Belousov 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
8422b34e843SKonstantin Belousov 		if (error)
8432b34e843SKonstantin Belousov 			return (error);
8442b34e843SKonstantin Belousov 		CP(ts32, ts, tv_sec);
8452b34e843SKonstantin Belousov 		CP(ts32, ts, tv_nsec);
8462b34e843SKonstantin Belousov 		tsp = &ts;
8472b34e843SKonstantin Belousov 	} else
8482b34e843SKonstantin Belousov 		tsp = NULL;
849ffb66079SJohn Baldwin #ifdef KTRACE
850ffb66079SJohn Baldwin 	if (KTRPOINT(td, KTR_STRUCT_ARRAY))
851ffb66079SJohn Baldwin 		ktrstructarray("kevent32", UIO_USERSPACE, uap->changelist,
852ffb66079SJohn Baldwin 		    uap->nchanges, sizeof(struct kevent32));
853ffb66079SJohn Baldwin #endif
8542b34e843SKonstantin Belousov 	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
8552b34e843SKonstantin Belousov 	    &k_ops, tsp);
856ffb66079SJohn Baldwin #ifdef KTRACE
857ffb66079SJohn Baldwin 	if (error == 0 && KTRPOINT(td, KTR_STRUCT_ARRAY))
858ffb66079SJohn Baldwin 		ktrstructarray("kevent32", UIO_USERSPACE, eventlist,
859ffb66079SJohn Baldwin 		    td->td_retval[0], sizeof(struct kevent32));
860ffb66079SJohn Baldwin #endif
8612b34e843SKonstantin Belousov 	return (error);
8622b34e843SKonstantin Belousov }
8632b34e843SKonstantin Belousov 
8642b34e843SKonstantin Belousov #ifdef COMPAT_FREEBSD11
8652b34e843SKonstantin Belousov static int
freebsd32_kevent11_copyout(void * arg,struct kevent * kevp,int count)8662b34e843SKonstantin Belousov freebsd32_kevent11_copyout(void *arg, struct kevent *kevp, int count)
8672b34e843SKonstantin Belousov {
8682b34e843SKonstantin Belousov 	struct freebsd11_freebsd32_kevent_args *uap;
8698e4a3addSBrooks Davis 	struct freebsd11_kevent32 ks32[KQ_NEVENTS];
8702b34e843SKonstantin Belousov 	int i, error;
8712b34e843SKonstantin Belousov 
8722b34e843SKonstantin Belousov 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
8732b34e843SKonstantin Belousov 	uap = (struct freebsd11_freebsd32_kevent_args *)arg;
8742b34e843SKonstantin Belousov 
8752b34e843SKonstantin Belousov 	for (i = 0; i < count; i++) {
8762b34e843SKonstantin Belousov 		CP(kevp[i], ks32[i], ident);
8772b34e843SKonstantin Belousov 		CP(kevp[i], ks32[i], filter);
8782b34e843SKonstantin Belousov 		CP(kevp[i], ks32[i], flags);
8792b34e843SKonstantin Belousov 		CP(kevp[i], ks32[i], fflags);
880efe5becaSPaul Saab 		CP(kevp[i], ks32[i], data);
881efe5becaSPaul Saab 		PTROUT_CP(kevp[i], ks32[i], udata);
882efe5becaSPaul Saab 	}
883efe5becaSPaul Saab 	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
884efe5becaSPaul Saab 	if (error == 0)
885efe5becaSPaul Saab 		uap->eventlist += count;
886efe5becaSPaul Saab 	return (error);
887efe5becaSPaul Saab }
888efe5becaSPaul Saab 
889efe5becaSPaul Saab /*
890efe5becaSPaul Saab  * Copy 'count' items from the list pointed to by uap->changelist.
891efe5becaSPaul Saab  */
892efe5becaSPaul Saab static int
freebsd32_kevent11_copyin(void * arg,struct kevent * kevp,int count)8932b34e843SKonstantin Belousov freebsd32_kevent11_copyin(void *arg, struct kevent *kevp, int count)
894efe5becaSPaul Saab {
8952b34e843SKonstantin Belousov 	struct freebsd11_freebsd32_kevent_args *uap;
8968e4a3addSBrooks Davis 	struct freebsd11_kevent32 ks32[KQ_NEVENTS];
8972b34e843SKonstantin Belousov 	int i, j, error;
898efe5becaSPaul Saab 
899efe5becaSPaul Saab 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
9002b34e843SKonstantin Belousov 	uap = (struct freebsd11_freebsd32_kevent_args *)arg;
901efe5becaSPaul Saab 
902efe5becaSPaul Saab 	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
903efe5becaSPaul Saab 	if (error)
904efe5becaSPaul Saab 		goto done;
905efe5becaSPaul Saab 	uap->changelist += count;
906efe5becaSPaul Saab 
907efe5becaSPaul Saab 	for (i = 0; i < count; i++) {
908efe5becaSPaul Saab 		CP(ks32[i], kevp[i], ident);
909efe5becaSPaul Saab 		CP(ks32[i], kevp[i], filter);
910efe5becaSPaul Saab 		CP(ks32[i], kevp[i], flags);
911efe5becaSPaul Saab 		CP(ks32[i], kevp[i], fflags);
912efe5becaSPaul Saab 		CP(ks32[i], kevp[i], data);
913efe5becaSPaul Saab 		PTRIN_CP(ks32[i], kevp[i], udata);
9142b34e843SKonstantin Belousov 		for (j = 0; j < nitems(kevp->ext); j++)
9152b34e843SKonstantin Belousov 			kevp[i].ext[j] = 0;
916efe5becaSPaul Saab 	}
917efe5becaSPaul Saab done:
918efe5becaSPaul Saab 	return (error);
919efe5becaSPaul Saab }
92060a8c422SPeter Wemm 
921d85631c4SPeter Wemm int
freebsd11_freebsd32_kevent(struct thread * td,struct freebsd11_freebsd32_kevent_args * uap)9222b34e843SKonstantin Belousov freebsd11_freebsd32_kevent(struct thread *td,
9232b34e843SKonstantin Belousov     struct freebsd11_freebsd32_kevent_args *uap)
924d85631c4SPeter Wemm {
925d85631c4SPeter Wemm 	struct timespec32 ts32;
926b8a4edc1SPaul Saab 	struct timespec ts, *tsp;
92701feb4c3SKonstantin Belousov 	struct kevent_copyops k_ops = {
92801feb4c3SKonstantin Belousov 		.arg = uap,
9292b34e843SKonstantin Belousov 		.k_copyout = freebsd32_kevent11_copyout,
9302b34e843SKonstantin Belousov 		.k_copyin = freebsd32_kevent11_copyin,
93101feb4c3SKonstantin Belousov 	};
932ffb66079SJohn Baldwin #ifdef KTRACE
9338e4a3addSBrooks Davis 	struct freebsd11_kevent32 *eventlist = uap->eventlist;
934ffb66079SJohn Baldwin #endif
935efe5becaSPaul Saab 	int error;
936d85631c4SPeter Wemm 
937d85631c4SPeter Wemm 	if (uap->timeout) {
938d85631c4SPeter Wemm 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
939d85631c4SPeter Wemm 		if (error)
940d85631c4SPeter Wemm 			return (error);
941d85631c4SPeter Wemm 		CP(ts32, ts, tv_sec);
942d85631c4SPeter Wemm 		CP(ts32, ts, tv_nsec);
943b8a4edc1SPaul Saab 		tsp = &ts;
944b8a4edc1SPaul Saab 	} else
945b8a4edc1SPaul Saab 		tsp = NULL;
946ffb66079SJohn Baldwin #ifdef KTRACE
947ffb66079SJohn Baldwin 	if (KTRPOINT(td, KTR_STRUCT_ARRAY))
9488e4a3addSBrooks Davis 		ktrstructarray("freebsd11_kevent32", UIO_USERSPACE,
949ffb66079SJohn Baldwin 		    uap->changelist, uap->nchanges,
9508e4a3addSBrooks Davis 		    sizeof(struct freebsd11_kevent32));
951ffb66079SJohn Baldwin #endif
952efe5becaSPaul Saab 	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
953efe5becaSPaul Saab 	    &k_ops, tsp);
954ffb66079SJohn Baldwin #ifdef KTRACE
955ffb66079SJohn Baldwin 	if (error == 0 && KTRPOINT(td, KTR_STRUCT_ARRAY))
9568e4a3addSBrooks Davis 		ktrstructarray("freebsd11_kevent32", UIO_USERSPACE,
957ffb66079SJohn Baldwin 		    eventlist, td->td_retval[0],
9588e4a3addSBrooks Davis 		    sizeof(struct freebsd11_kevent32));
959ffb66079SJohn Baldwin #endif
960d85631c4SPeter Wemm 	return (error);
961d85631c4SPeter Wemm }
9622b34e843SKonstantin Belousov #endif
963d85631c4SPeter Wemm 
9643ebc1248SPeter Wemm int
freebsd32_gettimeofday(struct thread * td,struct freebsd32_gettimeofday_args * uap)9651c7abef7SPeter Wemm freebsd32_gettimeofday(struct thread *td,
9661c7abef7SPeter Wemm 		       struct freebsd32_gettimeofday_args *uap)
9673ebc1248SPeter Wemm {
9684eeb271aSPeter Wemm 	struct timeval atv;
9694eeb271aSPeter Wemm 	struct timeval32 atv32;
9704eeb271aSPeter Wemm 	struct timezone rtz;
9714eeb271aSPeter Wemm 	int error = 0;
9723ebc1248SPeter Wemm 
9734eeb271aSPeter Wemm 	if (uap->tp) {
9744eeb271aSPeter Wemm 		microtime(&atv);
9754eeb271aSPeter Wemm 		CP(atv, atv32, tv_sec);
9764eeb271aSPeter Wemm 		CP(atv, atv32, tv_usec);
9774eeb271aSPeter Wemm 		error = copyout(&atv32, uap->tp, sizeof (atv32));
9783ebc1248SPeter Wemm 	}
9794eeb271aSPeter Wemm 	if (error == 0 && uap->tzp != NULL) {
980329f0aa9SWarner Losh 		rtz.tz_minuteswest = 0;
981329f0aa9SWarner Losh 		rtz.tz_dsttime = 0;
9824eeb271aSPeter Wemm 		error = copyout(&rtz, uap->tzp, sizeof (rtz));
9833ebc1248SPeter Wemm 	}
9843ebc1248SPeter Wemm 	return (error);
9853ebc1248SPeter Wemm }
9863ebc1248SPeter Wemm 
9873ebc1248SPeter Wemm int
freebsd32_getrusage(struct thread * td,struct freebsd32_getrusage_args * uap)9881c7abef7SPeter Wemm freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
9893ebc1248SPeter Wemm {
99078c85e8dSJohn Baldwin 	struct rusage32 s32;
99178c85e8dSJohn Baldwin 	struct rusage s;
9923ebc1248SPeter Wemm 	int error;
9933ebc1248SPeter Wemm 
99478c85e8dSJohn Baldwin 	error = kern_getrusage(td, uap->who, &s);
9959dea3ac8SAlan Somers 	if (error == 0) {
9969847e91bSKonstantin Belousov 		freebsd32_rusage_out(&s, &s32);
99778c85e8dSJohn Baldwin 		error = copyout(&s32, uap->rusage, sizeof(s32));
9989dea3ac8SAlan Somers 	}
9993ebc1248SPeter Wemm 	return (error);
10003ebc1248SPeter Wemm }
10013ebc1248SPeter Wemm 
100258b552dcSJohn Baldwin static void
ptrace_lwpinfo_to32(const struct ptrace_lwpinfo * pl,struct ptrace_lwpinfo32 * pl32)100358b552dcSJohn Baldwin ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,
100458b552dcSJohn Baldwin     struct ptrace_lwpinfo32 *pl32)
100558b552dcSJohn Baldwin {
100658b552dcSJohn Baldwin 
100758b552dcSJohn Baldwin 	bzero(pl32, sizeof(*pl32));
100858b552dcSJohn Baldwin 	pl32->pl_lwpid = pl->pl_lwpid;
100958b552dcSJohn Baldwin 	pl32->pl_event = pl->pl_event;
101058b552dcSJohn Baldwin 	pl32->pl_flags = pl->pl_flags;
101158b552dcSJohn Baldwin 	pl32->pl_sigmask = pl->pl_sigmask;
101258b552dcSJohn Baldwin 	pl32->pl_siglist = pl->pl_siglist;
101358b552dcSJohn Baldwin 	siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);
101458b552dcSJohn Baldwin 	strcpy(pl32->pl_tdname, pl->pl_tdname);
101558b552dcSJohn Baldwin 	pl32->pl_child_pid = pl->pl_child_pid;
101658b552dcSJohn Baldwin 	pl32->pl_syscall_code = pl->pl_syscall_code;
101758b552dcSJohn Baldwin 	pl32->pl_syscall_narg = pl->pl_syscall_narg;
101858b552dcSJohn Baldwin }
101958b552dcSJohn Baldwin 
102058b552dcSJohn Baldwin static void
ptrace_sc_ret_to32(const struct ptrace_sc_ret * psr,struct ptrace_sc_ret32 * psr32)102158b552dcSJohn Baldwin ptrace_sc_ret_to32(const struct ptrace_sc_ret *psr,
102258b552dcSJohn Baldwin     struct ptrace_sc_ret32 *psr32)
102358b552dcSJohn Baldwin {
102458b552dcSJohn Baldwin 
102558b552dcSJohn Baldwin 	bzero(psr32, sizeof(*psr32));
102658b552dcSJohn Baldwin 	psr32->sr_retval[0] = psr->sr_retval[0];
102758b552dcSJohn Baldwin 	psr32->sr_retval[1] = psr->sr_retval[1];
102858b552dcSJohn Baldwin 	psr32->sr_error = psr->sr_error;
102958b552dcSJohn Baldwin }
103058b552dcSJohn Baldwin 
103158b552dcSJohn Baldwin int
freebsd32_ptrace(struct thread * td,struct freebsd32_ptrace_args * uap)103258b552dcSJohn Baldwin freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)
103358b552dcSJohn Baldwin {
103458b552dcSJohn Baldwin 	union {
103558b552dcSJohn Baldwin 		struct ptrace_io_desc piod;
103658b552dcSJohn Baldwin 		struct ptrace_lwpinfo pl;
103758b552dcSJohn Baldwin 		struct ptrace_vm_entry pve;
103887a64872SKonstantin Belousov 		struct ptrace_coredump pc;
1039140ceb5dSKonstantin Belousov 		struct ptrace_sc_remote sr;
104058b552dcSJohn Baldwin 		struct dbreg32 dbreg;
104158b552dcSJohn Baldwin 		struct fpreg32 fpreg;
104258b552dcSJohn Baldwin 		struct reg32 reg;
1043548a2ec4SAndrew Turner 		struct iovec vec;
104458b552dcSJohn Baldwin 		register_t args[nitems(td->td_sa.args)];
104558b552dcSJohn Baldwin 		struct ptrace_sc_ret psr;
104658b552dcSJohn Baldwin 		int ptevents;
104758b552dcSJohn Baldwin 	} r;
104858b552dcSJohn Baldwin 	union {
104958b552dcSJohn Baldwin 		struct ptrace_io_desc32 piod;
105058b552dcSJohn Baldwin 		struct ptrace_lwpinfo32 pl;
105158b552dcSJohn Baldwin 		struct ptrace_vm_entry32 pve;
105287a64872SKonstantin Belousov 		struct ptrace_coredump32 pc;
1053140ceb5dSKonstantin Belousov 		struct ptrace_sc_remote32 sr;
105458b552dcSJohn Baldwin 		uint32_t args[nitems(td->td_sa.args)];
105558b552dcSJohn Baldwin 		struct ptrace_sc_ret32 psr;
1056548a2ec4SAndrew Turner 		struct iovec32 vec;
105758b552dcSJohn Baldwin 	} r32;
1058140ceb5dSKonstantin Belousov 	syscallarg_t pscr_args[nitems(td->td_sa.args)];
1059140ceb5dSKonstantin Belousov 	u_int pscr_args32[nitems(td->td_sa.args)];
106058b552dcSJohn Baldwin 	void *addr;
1061fe6db727SKonstantin Belousov 	int data, error, i;
1062fe6db727SKonstantin Belousov 
1063fe6db727SKonstantin Belousov 	if (!allow_ptrace)
1064fe6db727SKonstantin Belousov 		return (ENOSYS);
1065fe6db727SKonstantin Belousov 	error = 0;
106658b552dcSJohn Baldwin 
106758b552dcSJohn Baldwin 	AUDIT_ARG_PID(uap->pid);
106858b552dcSJohn Baldwin 	AUDIT_ARG_CMD(uap->req);
106958b552dcSJohn Baldwin 	AUDIT_ARG_VALUE(uap->data);
107058b552dcSJohn Baldwin 	addr = &r;
107158b552dcSJohn Baldwin 	data = uap->data;
107258b552dcSJohn Baldwin 	switch (uap->req) {
107358b552dcSJohn Baldwin 	case PT_GET_EVENT_MASK:
107458b552dcSJohn Baldwin 	case PT_GET_SC_ARGS:
107558b552dcSJohn Baldwin 	case PT_GET_SC_RET:
107658b552dcSJohn Baldwin 		break;
107758b552dcSJohn Baldwin 	case PT_LWPINFO:
107858b552dcSJohn Baldwin 		if (uap->data > sizeof(r32.pl))
107958b552dcSJohn Baldwin 			return (EINVAL);
108058b552dcSJohn Baldwin 
108158b552dcSJohn Baldwin 		/*
108258b552dcSJohn Baldwin 		 * Pass size of native structure in 'data'.  Truncate
108358b552dcSJohn Baldwin 		 * if necessary to avoid siginfo.
108458b552dcSJohn Baldwin 		 */
108558b552dcSJohn Baldwin 		data = sizeof(r.pl);
108658b552dcSJohn Baldwin 		if (uap->data < offsetof(struct ptrace_lwpinfo32, pl_siginfo) +
1087d060b420SBrooks Davis 		    sizeof(struct __siginfo32))
108858b552dcSJohn Baldwin 			data = offsetof(struct ptrace_lwpinfo, pl_siginfo);
108958b552dcSJohn Baldwin 		break;
109058b552dcSJohn Baldwin 	case PT_GETREGS:
109158b552dcSJohn Baldwin 		bzero(&r.reg, sizeof(r.reg));
109258b552dcSJohn Baldwin 		break;
109358b552dcSJohn Baldwin 	case PT_GETFPREGS:
109458b552dcSJohn Baldwin 		bzero(&r.fpreg, sizeof(r.fpreg));
109558b552dcSJohn Baldwin 		break;
109658b552dcSJohn Baldwin 	case PT_GETDBREGS:
109758b552dcSJohn Baldwin 		bzero(&r.dbreg, sizeof(r.dbreg));
109858b552dcSJohn Baldwin 		break;
109958b552dcSJohn Baldwin 	case PT_SETREGS:
110058b552dcSJohn Baldwin 		error = copyin(uap->addr, &r.reg, sizeof(r.reg));
110158b552dcSJohn Baldwin 		break;
110258b552dcSJohn Baldwin 	case PT_SETFPREGS:
110358b552dcSJohn Baldwin 		error = copyin(uap->addr, &r.fpreg, sizeof(r.fpreg));
110458b552dcSJohn Baldwin 		break;
110558b552dcSJohn Baldwin 	case PT_SETDBREGS:
110658b552dcSJohn Baldwin 		error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg));
110758b552dcSJohn Baldwin 		break;
1108548a2ec4SAndrew Turner 	case PT_GETREGSET:
1109949e3959SJohn Baldwin 	case PT_SETREGSET:
1110548a2ec4SAndrew Turner 		error = copyin(uap->addr, &r32.vec, sizeof(r32.vec));
1111548a2ec4SAndrew Turner 		if (error != 0)
1112548a2ec4SAndrew Turner 			break;
1113548a2ec4SAndrew Turner 
1114548a2ec4SAndrew Turner 		r.vec.iov_len = r32.vec.iov_len;
1115548a2ec4SAndrew Turner 		r.vec.iov_base = PTRIN(r32.vec.iov_base);
1116548a2ec4SAndrew Turner 		break;
111758b552dcSJohn Baldwin 	case PT_SET_EVENT_MASK:
111858b552dcSJohn Baldwin 		if (uap->data != sizeof(r.ptevents))
111958b552dcSJohn Baldwin 			error = EINVAL;
112058b552dcSJohn Baldwin 		else
112158b552dcSJohn Baldwin 			error = copyin(uap->addr, &r.ptevents, uap->data);
112258b552dcSJohn Baldwin 		break;
112358b552dcSJohn Baldwin 	case PT_IO:
112458b552dcSJohn Baldwin 		error = copyin(uap->addr, &r32.piod, sizeof(r32.piod));
112558b552dcSJohn Baldwin 		if (error)
112658b552dcSJohn Baldwin 			break;
112758b552dcSJohn Baldwin 		CP(r32.piod, r.piod, piod_op);
112858b552dcSJohn Baldwin 		PTRIN_CP(r32.piod, r.piod, piod_offs);
112958b552dcSJohn Baldwin 		PTRIN_CP(r32.piod, r.piod, piod_addr);
113058b552dcSJohn Baldwin 		CP(r32.piod, r.piod, piod_len);
113158b552dcSJohn Baldwin 		break;
113258b552dcSJohn Baldwin 	case PT_VM_ENTRY:
113358b552dcSJohn Baldwin 		error = copyin(uap->addr, &r32.pve, sizeof(r32.pve));
113458b552dcSJohn Baldwin 		if (error)
113558b552dcSJohn Baldwin 			break;
113658b552dcSJohn Baldwin 
113758b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_entry);
113858b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_timestamp);
113958b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_start);
114058b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_end);
114158b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_offset);
114258b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_prot);
114358b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_pathlen);
114458b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_fileid);
114558b552dcSJohn Baldwin 		CP(r32.pve, r.pve, pve_fsid);
114658b552dcSJohn Baldwin 		PTRIN_CP(r32.pve, r.pve, pve_path);
114758b552dcSJohn Baldwin 		break;
114887a64872SKonstantin Belousov 	case PT_COREDUMP:
114987a64872SKonstantin Belousov 		if (uap->data != sizeof(r32.pc))
115087a64872SKonstantin Belousov 			error = EINVAL;
115187a64872SKonstantin Belousov 		else
115287a64872SKonstantin Belousov 			error = copyin(uap->addr, &r32.pc, uap->data);
115387a64872SKonstantin Belousov 		CP(r32.pc, r.pc, pc_fd);
115487a64872SKonstantin Belousov 		CP(r32.pc, r.pc, pc_flags);
115587a64872SKonstantin Belousov 		r.pc.pc_limit = PAIR32TO64(off_t, r32.pc.pc_limit);
115687a64872SKonstantin Belousov 		data = sizeof(r.pc);
115787a64872SKonstantin Belousov 		break;
1158140ceb5dSKonstantin Belousov 	case PT_SC_REMOTE:
1159140ceb5dSKonstantin Belousov 		if (uap->data != sizeof(r32.sr)) {
1160140ceb5dSKonstantin Belousov 			error = EINVAL;
1161140ceb5dSKonstantin Belousov 			break;
1162140ceb5dSKonstantin Belousov 		}
1163140ceb5dSKonstantin Belousov 		error = copyin(uap->addr, &r32.sr, uap->data);
1164140ceb5dSKonstantin Belousov 		if (error != 0)
1165140ceb5dSKonstantin Belousov 			break;
1166140ceb5dSKonstantin Belousov 		CP(r32.sr, r.sr, pscr_syscall);
1167140ceb5dSKonstantin Belousov 		CP(r32.sr, r.sr, pscr_nargs);
1168140ceb5dSKonstantin Belousov 		if (r.sr.pscr_nargs > nitems(td->td_sa.args)) {
1169140ceb5dSKonstantin Belousov 			error = EINVAL;
1170140ceb5dSKonstantin Belousov 			break;
1171140ceb5dSKonstantin Belousov 		}
1172140ceb5dSKonstantin Belousov 		error = copyin(PTRIN(r32.sr.pscr_args), pscr_args32,
1173140ceb5dSKonstantin Belousov 		    sizeof(u_int) * r32.sr.pscr_nargs);
1174140ceb5dSKonstantin Belousov 		if (error != 0)
1175140ceb5dSKonstantin Belousov 			break;
1176140ceb5dSKonstantin Belousov 		for (i = 0; i < r32.sr.pscr_nargs; i++)
1177140ceb5dSKonstantin Belousov 			pscr_args[i] = pscr_args32[i];
1178140ceb5dSKonstantin Belousov 		r.sr.pscr_args = pscr_args;
1179140ceb5dSKonstantin Belousov 		break;
1180*ee609560SMark Johnston 	case PTINTERNAL_FIRST ... PTINTERNAL_LAST:
118148a656c5SMark Johnston 		error = EINVAL;
118248a656c5SMark Johnston 		break;
118358b552dcSJohn Baldwin 	default:
118458b552dcSJohn Baldwin 		addr = uap->addr;
118558b552dcSJohn Baldwin 		break;
118658b552dcSJohn Baldwin 	}
118758b552dcSJohn Baldwin 	if (error)
118858b552dcSJohn Baldwin 		return (error);
118958b552dcSJohn Baldwin 
119058b552dcSJohn Baldwin 	error = kern_ptrace(td, uap->req, uap->pid, addr, data);
119158b552dcSJohn Baldwin 	if (error)
119258b552dcSJohn Baldwin 		return (error);
119358b552dcSJohn Baldwin 
119458b552dcSJohn Baldwin 	switch (uap->req) {
119558b552dcSJohn Baldwin 	case PT_VM_ENTRY:
119658b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_entry);
119758b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_timestamp);
119858b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_start);
119958b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_end);
120058b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_offset);
120158b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_prot);
120258b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_pathlen);
120358b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_fileid);
120458b552dcSJohn Baldwin 		CP(r.pve, r32.pve, pve_fsid);
120558b552dcSJohn Baldwin 		error = copyout(&r32.pve, uap->addr, sizeof(r32.pve));
120658b552dcSJohn Baldwin 		break;
120758b552dcSJohn Baldwin 	case PT_IO:
120858b552dcSJohn Baldwin 		CP(r.piod, r32.piod, piod_len);
120958b552dcSJohn Baldwin 		error = copyout(&r32.piod, uap->addr, sizeof(r32.piod));
121058b552dcSJohn Baldwin 		break;
121158b552dcSJohn Baldwin 	case PT_GETREGS:
121258b552dcSJohn Baldwin 		error = copyout(&r.reg, uap->addr, sizeof(r.reg));
121358b552dcSJohn Baldwin 		break;
121458b552dcSJohn Baldwin 	case PT_GETFPREGS:
121558b552dcSJohn Baldwin 		error = copyout(&r.fpreg, uap->addr, sizeof(r.fpreg));
121658b552dcSJohn Baldwin 		break;
121758b552dcSJohn Baldwin 	case PT_GETDBREGS:
121858b552dcSJohn Baldwin 		error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));
121958b552dcSJohn Baldwin 		break;
1220548a2ec4SAndrew Turner 	case PT_GETREGSET:
1221548a2ec4SAndrew Turner 		r32.vec.iov_len = r.vec.iov_len;
1222548a2ec4SAndrew Turner 		error = copyout(&r32.vec, uap->addr, sizeof(r32.vec));
1223548a2ec4SAndrew Turner 		break;
122458b552dcSJohn Baldwin 	case PT_GET_EVENT_MASK:
122558b552dcSJohn Baldwin 		/* NB: The size in uap->data is validated in kern_ptrace(). */
122658b552dcSJohn Baldwin 		error = copyout(&r.ptevents, uap->addr, uap->data);
122758b552dcSJohn Baldwin 		break;
122858b552dcSJohn Baldwin 	case PT_LWPINFO:
122958b552dcSJohn Baldwin 		ptrace_lwpinfo_to32(&r.pl, &r32.pl);
123058b552dcSJohn Baldwin 		error = copyout(&r32.pl, uap->addr, uap->data);
123158b552dcSJohn Baldwin 		break;
123258b552dcSJohn Baldwin 	case PT_GET_SC_ARGS:
123358b552dcSJohn Baldwin 		for (i = 0; i < nitems(r.args); i++)
123458b552dcSJohn Baldwin 			r32.args[i] = (uint32_t)r.args[i];
123558b552dcSJohn Baldwin 		error = copyout(r32.args, uap->addr, MIN(uap->data,
123658b552dcSJohn Baldwin 		    sizeof(r32.args)));
123758b552dcSJohn Baldwin 		break;
123858b552dcSJohn Baldwin 	case PT_GET_SC_RET:
123958b552dcSJohn Baldwin 		ptrace_sc_ret_to32(&r.psr, &r32.psr);
124058b552dcSJohn Baldwin 		error = copyout(&r32.psr, uap->addr, MIN(uap->data,
124158b552dcSJohn Baldwin 		    sizeof(r32.psr)));
124258b552dcSJohn Baldwin 		break;
1243140ceb5dSKonstantin Belousov 	case PT_SC_REMOTE:
1244140ceb5dSKonstantin Belousov 		ptrace_sc_ret_to32(&r.sr.pscr_ret, &r32.sr.pscr_ret);
1245140ceb5dSKonstantin Belousov 		error = copyout(&r32.sr.pscr_ret, uap->addr +
1246140ceb5dSKonstantin Belousov 		    offsetof(struct ptrace_sc_remote32, pscr_ret),
1247140ceb5dSKonstantin Belousov 		    sizeof(r32.psr));
1248140ceb5dSKonstantin Belousov 		break;
124958b552dcSJohn Baldwin 	}
125058b552dcSJohn Baldwin 
125158b552dcSJohn Baldwin 	return (error);
125258b552dcSJohn Baldwin }
125358b552dcSJohn Baldwin 
1254022ca2fcSAlan Somers int
freebsd32_copyinuio(const struct iovec32 * iovp,u_int iovcnt,struct uio ** uiop)1255694ef157SBrooks Davis freebsd32_copyinuio(const struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
125648052f99SJohn Baldwin {
125748052f99SJohn Baldwin 	struct iovec32 iov32;
125848052f99SJohn Baldwin 	struct iovec *iov;
125948052f99SJohn Baldwin 	struct uio *uio;
126048052f99SJohn Baldwin 	int error, i;
126148052f99SJohn Baldwin 
126248052f99SJohn Baldwin 	*uiop = NULL;
126348052f99SJohn Baldwin 	if (iovcnt > UIO_MAXIOV)
126448052f99SJohn Baldwin 		return (EINVAL);
126561cc4830SAlfredo Mazzinghi 	uio = allocuio(iovcnt);
126661cc4830SAlfredo Mazzinghi 	iov = uio->uio_iov;
126748052f99SJohn Baldwin 	for (i = 0; i < iovcnt; i++) {
126848052f99SJohn Baldwin 		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
126948052f99SJohn Baldwin 		if (error) {
127061cc4830SAlfredo Mazzinghi 			freeuio(uio);
127148052f99SJohn Baldwin 			return (error);
127248052f99SJohn Baldwin 		}
127348052f99SJohn Baldwin 		iov[i].iov_base = PTRIN(iov32.iov_base);
127448052f99SJohn Baldwin 		iov[i].iov_len = iov32.iov_len;
127548052f99SJohn Baldwin 	}
127648052f99SJohn Baldwin 	uio->uio_iovcnt = iovcnt;
127748052f99SJohn Baldwin 	uio->uio_segflg = UIO_USERSPACE;
127848052f99SJohn Baldwin 	uio->uio_offset = -1;
127948052f99SJohn Baldwin 	uio->uio_resid = 0;
128048052f99SJohn Baldwin 	for (i = 0; i < iovcnt; i++) {
128148052f99SJohn Baldwin 		if (iov->iov_len > INT_MAX - uio->uio_resid) {
128261cc4830SAlfredo Mazzinghi 			freeuio(uio);
128348052f99SJohn Baldwin 			return (EINVAL);
128448052f99SJohn Baldwin 		}
128548052f99SJohn Baldwin 		uio->uio_resid += iov->iov_len;
128648052f99SJohn Baldwin 		iov++;
128748052f99SJohn Baldwin 	}
128848052f99SJohn Baldwin 	*uiop = uio;
128948052f99SJohn Baldwin 	return (0);
129048052f99SJohn Baldwin }
129148052f99SJohn Baldwin 
12923ebc1248SPeter Wemm int
freebsd32_readv(struct thread * td,struct freebsd32_readv_args * uap)12931c7abef7SPeter Wemm freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
12943ebc1248SPeter Wemm {
129548052f99SJohn Baldwin 	struct uio *auio;
129648052f99SJohn Baldwin 	int error;
12973ebc1248SPeter Wemm 
129848052f99SJohn Baldwin 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
129948052f99SJohn Baldwin 	if (error)
130048052f99SJohn Baldwin 		return (error);
130148052f99SJohn Baldwin 	error = kern_readv(td, uap->fd, auio);
130261cc4830SAlfredo Mazzinghi 	freeuio(auio);
13033ebc1248SPeter Wemm 	return (error);
13043ebc1248SPeter Wemm }
13053ebc1248SPeter Wemm 
13063ebc1248SPeter Wemm int
freebsd32_writev(struct thread * td,struct freebsd32_writev_args * uap)13071c7abef7SPeter Wemm freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
13083ebc1248SPeter Wemm {
130948052f99SJohn Baldwin 	struct uio *auio;
131048052f99SJohn Baldwin 	int error;
13113ebc1248SPeter Wemm 
131248052f99SJohn Baldwin 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
131348052f99SJohn Baldwin 	if (error)
131448052f99SJohn Baldwin 		return (error);
131548052f99SJohn Baldwin 	error = kern_writev(td, uap->fd, auio);
131661cc4830SAlfredo Mazzinghi 	freeuio(auio);
13173ebc1248SPeter Wemm 	return (error);
13183ebc1248SPeter Wemm }
13193ebc1248SPeter Wemm 
13203ebc1248SPeter Wemm int
freebsd32_preadv(struct thread * td,struct freebsd32_preadv_args * uap)1321bcd9e0ddSJohn Baldwin freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
1322bcd9e0ddSJohn Baldwin {
1323bcd9e0ddSJohn Baldwin 	struct uio *auio;
1324bcd9e0ddSJohn Baldwin 	int error;
1325bcd9e0ddSJohn Baldwin 
1326bcd9e0ddSJohn Baldwin 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
1327bcd9e0ddSJohn Baldwin 	if (error)
1328bcd9e0ddSJohn Baldwin 		return (error);
1329841c0c7eSNathan Whitehorn 	error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
133061cc4830SAlfredo Mazzinghi 	freeuio(auio);
1331bcd9e0ddSJohn Baldwin 	return (error);
1332bcd9e0ddSJohn Baldwin }
1333bcd9e0ddSJohn Baldwin 
1334bcd9e0ddSJohn Baldwin int
freebsd32_pwritev(struct thread * td,struct freebsd32_pwritev_args * uap)1335bcd9e0ddSJohn Baldwin freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
1336bcd9e0ddSJohn Baldwin {
1337bcd9e0ddSJohn Baldwin 	struct uio *auio;
1338bcd9e0ddSJohn Baldwin 	int error;
1339bcd9e0ddSJohn Baldwin 
1340bcd9e0ddSJohn Baldwin 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
1341bcd9e0ddSJohn Baldwin 	if (error)
1342bcd9e0ddSJohn Baldwin 		return (error);
1343841c0c7eSNathan Whitehorn 	error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
134461cc4830SAlfredo Mazzinghi 	freeuio(auio);
1345bcd9e0ddSJohn Baldwin 	return (error);
1346bcd9e0ddSJohn Baldwin }
1347bcd9e0ddSJohn Baldwin 
1348c5e4763dSKonstantin Belousov int
freebsd32_copyiniov(struct iovec32 * iovp32,u_int iovcnt,struct iovec ** iovp,int error)1349ecc44de7SPaul Saab freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
1350ecc44de7SPaul Saab     int error)
1351ecc44de7SPaul Saab {
1352ecc44de7SPaul Saab 	struct iovec32 iov32;
1353ecc44de7SPaul Saab 	struct iovec *iov;
1354ecc44de7SPaul Saab 	u_int iovlen;
1355ecc44de7SPaul Saab 	int i;
1356ecc44de7SPaul Saab 
1357ecc44de7SPaul Saab 	*iovp = NULL;
1358ecc44de7SPaul Saab 	if (iovcnt > UIO_MAXIOV)
1359ecc44de7SPaul Saab 		return (error);
1360ecc44de7SPaul Saab 	iovlen = iovcnt * sizeof(struct iovec);
1361ecc44de7SPaul Saab 	iov = malloc(iovlen, M_IOV, M_WAITOK);
1362ecc44de7SPaul Saab 	for (i = 0; i < iovcnt; i++) {
1363ecc44de7SPaul Saab 		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
1364ecc44de7SPaul Saab 		if (error) {
1365ecc44de7SPaul Saab 			free(iov, M_IOV);
1366ecc44de7SPaul Saab 			return (error);
1367ecc44de7SPaul Saab 		}
1368ecc44de7SPaul Saab 		iov[i].iov_base = PTRIN(iov32.iov_base);
1369ecc44de7SPaul Saab 		iov[i].iov_len = iov32.iov_len;
1370ecc44de7SPaul Saab 	}
1371ecc44de7SPaul Saab 	*iovp = iov;
1372ecc44de7SPaul Saab 	return (0);
1373ecc44de7SPaul Saab }
1374ecc44de7SPaul Saab 
1375a372f822SPaul Saab static int
freebsd32_copyinmsghdr(const struct msghdr32 * msg32,struct msghdr * msg)1376a944d28dSBrooks Davis freebsd32_copyinmsghdr(const struct msghdr32 *msg32, struct msghdr *msg)
1377a372f822SPaul Saab {
1378a372f822SPaul Saab 	struct msghdr32 m32;
1379a372f822SPaul Saab 	int error;
1380a372f822SPaul Saab 
1381a372f822SPaul Saab 	error = copyin(msg32, &m32, sizeof(m32));
1382a372f822SPaul Saab 	if (error)
1383a372f822SPaul Saab 		return (error);
1384a372f822SPaul Saab 	msg->msg_name = PTRIN(m32.msg_name);
1385a372f822SPaul Saab 	msg->msg_namelen = m32.msg_namelen;
1386a372f822SPaul Saab 	msg->msg_iov = PTRIN(m32.msg_iov);
1387a372f822SPaul Saab 	msg->msg_iovlen = m32.msg_iovlen;
1388a372f822SPaul Saab 	msg->msg_control = PTRIN(m32.msg_control);
1389a372f822SPaul Saab 	msg->msg_controllen = m32.msg_controllen;
1390a372f822SPaul Saab 	msg->msg_flags = m32.msg_flags;
1391ecc44de7SPaul Saab 	return (0);
1392a372f822SPaul Saab }
1393a372f822SPaul Saab 
1394a372f822SPaul Saab static int
freebsd32_copyoutmsghdr(struct msghdr * msg,struct msghdr32 * msg32)1395a372f822SPaul Saab freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
1396a372f822SPaul Saab {
1397a372f822SPaul Saab 	struct msghdr32 m32;
1398a372f822SPaul Saab 	int error;
1399a372f822SPaul Saab 
1400a372f822SPaul Saab 	m32.msg_name = PTROUT(msg->msg_name);
1401a372f822SPaul Saab 	m32.msg_namelen = msg->msg_namelen;
1402a372f822SPaul Saab 	m32.msg_iov = PTROUT(msg->msg_iov);
1403a372f822SPaul Saab 	m32.msg_iovlen = msg->msg_iovlen;
1404a372f822SPaul Saab 	m32.msg_control = PTROUT(msg->msg_control);
1405a372f822SPaul Saab 	m32.msg_controllen = msg->msg_controllen;
1406a372f822SPaul Saab 	m32.msg_flags = msg->msg_flags;
1407a372f822SPaul Saab 	error = copyout(&m32, msg32, sizeof(m32));
1408a372f822SPaul Saab 	return (error);
1409a372f822SPaul Saab }
1410a372f822SPaul Saab 
1411ecc44de7SPaul Saab #define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
1412ecc44de7SPaul Saab #define FREEBSD32_ALIGN(p)	\
1413ecc44de7SPaul Saab 	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
1414ecc44de7SPaul Saab #define	FREEBSD32_CMSG_SPACE(l)	\
1415ecc44de7SPaul Saab 	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
1416ecc44de7SPaul Saab 
1417ecc44de7SPaul Saab #define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
1418ecc44de7SPaul Saab 				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
1419afbd12c1SMaxim Sobolev 
1420afbd12c1SMaxim Sobolev static size_t
freebsd32_cmsg_convert(const struct cmsghdr * cm,void * data,socklen_t datalen)1421c7902fbeSMark Johnston freebsd32_cmsg_convert(const struct cmsghdr *cm, void *data, socklen_t datalen)
1422afbd12c1SMaxim Sobolev {
1423afbd12c1SMaxim Sobolev 	size_t copylen;
1424afbd12c1SMaxim Sobolev 	union {
1425afbd12c1SMaxim Sobolev 		struct timespec32 ts;
1426afbd12c1SMaxim Sobolev 		struct timeval32 tv;
1427afbd12c1SMaxim Sobolev 		struct bintime32 bt;
1428afbd12c1SMaxim Sobolev 	} tmp32;
1429afbd12c1SMaxim Sobolev 
1430afbd12c1SMaxim Sobolev 	union {
1431afbd12c1SMaxim Sobolev 		struct timespec ts;
1432afbd12c1SMaxim Sobolev 		struct timeval tv;
1433afbd12c1SMaxim Sobolev 		struct bintime bt;
1434afbd12c1SMaxim Sobolev 	} *in;
1435afbd12c1SMaxim Sobolev 
1436afbd12c1SMaxim Sobolev 	in = data;
1437afbd12c1SMaxim Sobolev 	copylen = 0;
1438afbd12c1SMaxim Sobolev 	switch (cm->cmsg_level) {
1439afbd12c1SMaxim Sobolev 	case SOL_SOCKET:
1440afbd12c1SMaxim Sobolev 		switch (cm->cmsg_type) {
1441afbd12c1SMaxim Sobolev 		case SCM_TIMESTAMP:
1442afbd12c1SMaxim Sobolev 			TV_CP(*in, tmp32, tv);
1443afbd12c1SMaxim Sobolev 			copylen = sizeof(tmp32.tv);
1444afbd12c1SMaxim Sobolev 			break;
1445afbd12c1SMaxim Sobolev 
1446afbd12c1SMaxim Sobolev 		case SCM_BINTIME:
1447afbd12c1SMaxim Sobolev 			BT_CP(*in, tmp32, bt);
1448afbd12c1SMaxim Sobolev 			copylen = sizeof(tmp32.bt);
1449afbd12c1SMaxim Sobolev 			break;
1450afbd12c1SMaxim Sobolev 
1451afbd12c1SMaxim Sobolev 		case SCM_REALTIME:
1452afbd12c1SMaxim Sobolev 		case SCM_MONOTONIC:
1453afbd12c1SMaxim Sobolev 			TS_CP(*in, tmp32, ts);
1454afbd12c1SMaxim Sobolev 			copylen = sizeof(tmp32.ts);
1455afbd12c1SMaxim Sobolev 			break;
1456afbd12c1SMaxim Sobolev 
1457afbd12c1SMaxim Sobolev 		default:
1458afbd12c1SMaxim Sobolev 			break;
1459afbd12c1SMaxim Sobolev 		}
1460afbd12c1SMaxim Sobolev 
1461afbd12c1SMaxim Sobolev 	default:
1462afbd12c1SMaxim Sobolev 		break;
1463afbd12c1SMaxim Sobolev 	}
1464afbd12c1SMaxim Sobolev 
1465afbd12c1SMaxim Sobolev 	if (copylen == 0)
1466afbd12c1SMaxim Sobolev 		return (datalen);
1467afbd12c1SMaxim Sobolev 
1468afbd12c1SMaxim Sobolev 	KASSERT((datalen >= copylen), ("corrupted cmsghdr"));
1469afbd12c1SMaxim Sobolev 
1470afbd12c1SMaxim Sobolev 	bcopy(&tmp32, data, copylen);
1471afbd12c1SMaxim Sobolev 	return (copylen);
1472afbd12c1SMaxim Sobolev }
1473afbd12c1SMaxim Sobolev 
1474ecc44de7SPaul Saab static int
freebsd32_copy_msg_out(struct msghdr * msg,struct mbuf * control)1475ecc44de7SPaul Saab freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
1476ecc44de7SPaul Saab {
1477ecc44de7SPaul Saab 	struct cmsghdr *cm;
1478ecc44de7SPaul Saab 	void *data;
1479c7902fbeSMark Johnston 	socklen_t clen, datalen, datalen_out, oldclen;
1480ecc44de7SPaul Saab 	int error;
1481ecc44de7SPaul Saab 	caddr_t ctlbuf;
14821caaf555SMateusz Guzik 	int len, copylen;
1483ecc44de7SPaul Saab 	struct mbuf *m;
1484ecc44de7SPaul Saab 	error = 0;
1485ecc44de7SPaul Saab 
1486ecc44de7SPaul Saab 	len    = msg->msg_controllen;
1487ecc44de7SPaul Saab 	msg->msg_controllen = 0;
1488ecc44de7SPaul Saab 
1489ecc44de7SPaul Saab 	ctlbuf = msg->msg_control;
1490c7902fbeSMark Johnston 	for (m = control; m != NULL && len > 0; m = m->m_next) {
1491ecc44de7SPaul Saab 		cm = mtod(m, struct cmsghdr *);
1492ecc44de7SPaul Saab 		clen = m->m_len;
1493ecc44de7SPaul Saab 		while (cm != NULL) {
1494ecc44de7SPaul Saab 			if (sizeof(struct cmsghdr) > clen ||
1495ecc44de7SPaul Saab 			    cm->cmsg_len > clen) {
1496ecc44de7SPaul Saab 				error = EINVAL;
1497ecc44de7SPaul Saab 				break;
1498ecc44de7SPaul Saab 			}
1499ecc44de7SPaul Saab 
1500ecc44de7SPaul Saab 			data   = CMSG_DATA(cm);
1501ecc44de7SPaul Saab 			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1502afbd12c1SMaxim Sobolev 			datalen_out = freebsd32_cmsg_convert(cm, data, datalen);
1503ecc44de7SPaul Saab 
1504c7902fbeSMark Johnston 			/*
1505c7902fbeSMark Johnston 			 * Copy out the message header.  Preserve the native
1506c7902fbeSMark Johnston 			 * message size in case we need to inspect the message
1507c7902fbeSMark Johnston 			 * contents later.
1508c7902fbeSMark Johnston 			 */
1509ecc44de7SPaul Saab 			copylen = sizeof(struct cmsghdr);
1510ecc44de7SPaul Saab 			if (len < copylen) {
1511ecc44de7SPaul Saab 				msg->msg_flags |= MSG_CTRUNC;
1512c7902fbeSMark Johnston 				m_dispose_extcontrolm(m);
1513c7902fbeSMark Johnston 				goto exit;
1514ecc44de7SPaul Saab 			}
1515c7902fbeSMark Johnston 			oldclen = cm->cmsg_len;
1516c7902fbeSMark Johnston 			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
1517c7902fbeSMark Johnston 			    datalen_out;
1518ecc44de7SPaul Saab 			error = copyout(cm, ctlbuf, copylen);
1519c7902fbeSMark Johnston 			cm->cmsg_len = oldclen;
1520c7902fbeSMark Johnston 			if (error != 0)
1521ecc44de7SPaul Saab 				goto exit;
1522ecc44de7SPaul Saab 
1523ecc44de7SPaul Saab 			ctlbuf += FREEBSD32_ALIGN(copylen);
1524ecc44de7SPaul Saab 			len    -= FREEBSD32_ALIGN(copylen);
1525ecc44de7SPaul Saab 
1526afbd12c1SMaxim Sobolev 			copylen = datalen_out;
1527ecc44de7SPaul Saab 			if (len < copylen) {
1528ecc44de7SPaul Saab 				msg->msg_flags |= MSG_CTRUNC;
1529c7902fbeSMark Johnston 				m_dispose_extcontrolm(m);
1530c7902fbeSMark Johnston 				break;
1531ecc44de7SPaul Saab 			}
1532ecc44de7SPaul Saab 
1533c7902fbeSMark Johnston 			/* Copy out the message data. */
1534ecc44de7SPaul Saab 			error = copyout(data, ctlbuf, copylen);
1535ecc44de7SPaul Saab 			if (error)
1536ecc44de7SPaul Saab 				goto exit;
1537ecc44de7SPaul Saab 
1538ecc44de7SPaul Saab 			ctlbuf += FREEBSD32_ALIGN(copylen);
1539ecc44de7SPaul Saab 			len    -= FREEBSD32_ALIGN(copylen);
1540ecc44de7SPaul Saab 
1541ecc44de7SPaul Saab 			if (CMSG_SPACE(datalen) < clen) {
1542ecc44de7SPaul Saab 				clen -= CMSG_SPACE(datalen);
1543ecc44de7SPaul Saab 				cm = (struct cmsghdr *)
1544ecc44de7SPaul Saab 				    ((caddr_t)cm + CMSG_SPACE(datalen));
1545ecc44de7SPaul Saab 			} else {
1546ecc44de7SPaul Saab 				clen = 0;
1547ecc44de7SPaul Saab 				cm = NULL;
1548ecc44de7SPaul Saab 			}
1549ecc44de7SPaul Saab 
1550f0645b3aSJason A. Harmening 			msg->msg_controllen +=
1551f0645b3aSJason A. Harmening 			    FREEBSD32_CMSG_SPACE(datalen_out);
1552c7902fbeSMark Johnston 		}
1553c7902fbeSMark Johnston 	}
1554c7902fbeSMark Johnston 	if (len == 0 && m != NULL) {
1555c7902fbeSMark Johnston 		msg->msg_flags |= MSG_CTRUNC;
1556c7902fbeSMark Johnston 		m_dispose_extcontrolm(m);
1557c7902fbeSMark Johnston 	}
1558ecc44de7SPaul Saab 
1559ecc44de7SPaul Saab exit:
1560ecc44de7SPaul Saab 	return (error);
1561ecc44de7SPaul Saab }
1562ecc44de7SPaul Saab 
1563a372f822SPaul Saab int
freebsd32_recvmsg(struct thread * td,struct freebsd32_recvmsg_args * uap)15644bda16ffSMark Johnston freebsd32_recvmsg(struct thread *td, struct freebsd32_recvmsg_args *uap)
1565a372f822SPaul Saab {
1566a372f822SPaul Saab 	struct msghdr msg;
1567a372f822SPaul Saab 	struct iovec *uiov, *iov;
1568ecc44de7SPaul Saab 	struct mbuf *control = NULL;
1569ecc44de7SPaul Saab 	struct mbuf **controlp;
1570ecc44de7SPaul Saab 	int error;
1571fea1a98eSMark Johnston 
1572a372f822SPaul Saab 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1573a372f822SPaul Saab 	if (error)
1574a372f822SPaul Saab 		return (error);
1575fea1a98eSMark Johnston 	error = freebsd32_copyiniov((void *)msg.msg_iov, msg.msg_iovlen, &iov,
1576acdd09f9SJohn Baldwin 	    EMSGSIZE);
1577a372f822SPaul Saab 	if (error)
1578a372f822SPaul Saab 		return (error);
1579a372f822SPaul Saab 	msg.msg_flags = uap->flags;
1580a372f822SPaul Saab 	uiov = msg.msg_iov;
1581a372f822SPaul Saab 	msg.msg_iov = iov;
1582ecc44de7SPaul Saab 
1583ecc44de7SPaul Saab 	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1584c870740eSJohn Baldwin 	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1585a372f822SPaul Saab 	if (error == 0) {
1586a372f822SPaul Saab 		msg.msg_iov = uiov;
1587ecc44de7SPaul Saab 
1588ecc44de7SPaul Saab 		if (control != NULL)
1589ecc44de7SPaul Saab 			error = freebsd32_copy_msg_out(&msg, control);
159034ab36a3SKonstantin Belousov 		else
159134ab36a3SKonstantin Belousov 			msg.msg_controllen = 0;
1592ecc44de7SPaul Saab 
1593ecc44de7SPaul Saab 		if (error == 0)
1594a372f822SPaul Saab 			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1595a372f822SPaul Saab 	}
1596a372f822SPaul Saab 	free(iov, M_IOV);
1597ecc44de7SPaul Saab 
1598c7902fbeSMark Johnston 	if (control != NULL) {
1599c7902fbeSMark Johnston 		if (error != 0)
1600c7902fbeSMark Johnston 			m_dispose_extcontrolm(control);
1601ecc44de7SPaul Saab 		m_freem(control);
1602c7902fbeSMark Johnston 	}
1603ecc44de7SPaul Saab 
1604a372f822SPaul Saab 	return (error);
1605a372f822SPaul Saab }
1606a372f822SPaul Saab 
1607f089a2f3SBrooks Davis #ifdef COMPAT_43
1608f089a2f3SBrooks Davis int
ofreebsd32_recvmsg(struct thread * td,struct ofreebsd32_recvmsg_args * uap)1609f089a2f3SBrooks Davis ofreebsd32_recvmsg(struct thread *td, struct ofreebsd32_recvmsg_args *uap)
1610f089a2f3SBrooks Davis {
1611f089a2f3SBrooks Davis 	return (ENOSYS);
1612f089a2f3SBrooks Davis }
1613f089a2f3SBrooks Davis #endif
1614f089a2f3SBrooks Davis 
16150fa211beSMarcel Moolenaar /*
16160fa211beSMarcel Moolenaar  * Copy-in the array of control messages constructed using alignment
16170fa211beSMarcel Moolenaar  * and padding suitable for a 32-bit environment and construct an
16180fa211beSMarcel Moolenaar  * mbuf using alignment and padding suitable for a 64-bit kernel.
16190fa211beSMarcel Moolenaar  * The alignment and padding are defined indirectly by CMSG_DATA(),
16200fa211beSMarcel Moolenaar  * CMSG_SPACE() and CMSG_LEN().
16210fa211beSMarcel Moolenaar  */
1622ecc44de7SPaul Saab static int
freebsd32_copyin_control(struct mbuf ** mp,caddr_t buf,u_int buflen)16230fa211beSMarcel Moolenaar freebsd32_copyin_control(struct mbuf **mp, caddr_t buf, u_int buflen)
1624ecc44de7SPaul Saab {
16251b1428dcSMark Johnston 	struct cmsghdr *cm;
16260fa211beSMarcel Moolenaar 	struct mbuf *m;
16271b1428dcSMark Johnston 	void *in, *in1, *md;
16281b1428dcSMark Johnston 	u_int msglen, outlen;
1629ecc44de7SPaul Saab 	int error;
1630ecc44de7SPaul Saab 
1631c46697b9SBrooks Davis 	/* Enforce the size limit of the native implementation. */
16320fa211beSMarcel Moolenaar 	if (buflen > MCLBYTES)
16330fa211beSMarcel Moolenaar 		return (EINVAL);
16340fa211beSMarcel Moolenaar 
16351b1428dcSMark Johnston 	in = malloc(buflen, M_TEMP, M_WAITOK);
16361b1428dcSMark Johnston 	error = copyin(buf, in, buflen);
16371b1428dcSMark Johnston 	if (error != 0)
16381b1428dcSMark Johnston 		goto out;
16391b1428dcSMark Johnston 
16400fa211beSMarcel Moolenaar 	/*
16411b1428dcSMark Johnston 	 * Make a pass over the input buffer to determine the amount of space
16421b1428dcSMark Johnston 	 * required for 64 bit-aligned copies of the control messages.
16430fa211beSMarcel Moolenaar 	 */
16441b1428dcSMark Johnston 	in1 = in;
16451b1428dcSMark Johnston 	outlen = 0;
16460fa211beSMarcel Moolenaar 	while (buflen > 0) {
16471b1428dcSMark Johnston 		if (buflen < sizeof(*cm)) {
16481b1428dcSMark Johnston 			error = EINVAL;
1649ecc44de7SPaul Saab 			break;
16501b1428dcSMark Johnston 		}
16511b1428dcSMark Johnston 		cm = (struct cmsghdr *)in1;
16527b673a2cSJessica Clarke 		if (cm->cmsg_len < FREEBSD32_ALIGN(sizeof(*cm)) ||
16537b673a2cSJessica Clarke 		    cm->cmsg_len > buflen) {
16541b1428dcSMark Johnston 			error = EINVAL;
16550fa211beSMarcel Moolenaar 			break;
16561b1428dcSMark Johnston 		}
16571b1428dcSMark Johnston 		msglen = FREEBSD32_ALIGN(cm->cmsg_len);
16587b673a2cSJessica Clarke 		if (msglen < cm->cmsg_len) {
16591b1428dcSMark Johnston 			error = EINVAL;
16601b1428dcSMark Johnston 			break;
16611b1428dcSMark Johnston 		}
16627b673a2cSJessica Clarke 		/* The native ABI permits the final padding to be omitted. */
16637b673a2cSJessica Clarke 		if (msglen > buflen)
16647b673a2cSJessica Clarke 			msglen = buflen;
16650fa211beSMarcel Moolenaar 		buflen -= msglen;
16661b1428dcSMark Johnston 
16671b1428dcSMark Johnston 		in1 = (char *)in1 + msglen;
16681b1428dcSMark Johnston 		outlen += CMSG_ALIGN(sizeof(*cm)) +
16691b1428dcSMark Johnston 		    CMSG_ALIGN(msglen - FREEBSD32_ALIGN(sizeof(*cm)));
1670ecc44de7SPaul Saab 	}
16711b1428dcSMark Johnston 	if (error != 0)
16721b1428dcSMark Johnston 		goto out;
16731b1428dcSMark Johnston 
1674c46697b9SBrooks Davis 	/*
1675c46697b9SBrooks Davis 	 * Allocate up to MJUMPAGESIZE space for the re-aligned and
1676c46697b9SBrooks Davis 	 * re-padded control messages.  This allows a full MCLBYTES of
1677c46697b9SBrooks Davis 	 * 32-bit sized and aligned messages to fit and avoids an ABI
1678c46697b9SBrooks Davis 	 * mismatch with the native implementation.
1679c46697b9SBrooks Davis 	 */
16801b1428dcSMark Johnston 	m = m_get2(outlen, M_WAITOK, MT_CONTROL, 0);
1681c46697b9SBrooks Davis 	if (m == NULL) {
1682c46697b9SBrooks Davis 		error = EINVAL;
1683c46697b9SBrooks Davis 		goto out;
1684c46697b9SBrooks Davis 	}
16851b1428dcSMark Johnston 	m->m_len = outlen;
16861b1428dcSMark Johnston 	md = mtod(m, void *);
16871b1428dcSMark Johnston 
16881b1428dcSMark Johnston 	/*
16891b1428dcSMark Johnston 	 * Make a second pass over input messages, copying them into the output
16901b1428dcSMark Johnston 	 * buffer.
16911b1428dcSMark Johnston 	 */
16921b1428dcSMark Johnston 	in1 = in;
16931b1428dcSMark Johnston 	while (outlen > 0) {
16941b1428dcSMark Johnston 		/* Copy the message header and align the length field. */
16951b1428dcSMark Johnston 		cm = md;
16961b1428dcSMark Johnston 		memcpy(cm, in1, sizeof(*cm));
16971b1428dcSMark Johnston 		msglen = cm->cmsg_len - FREEBSD32_ALIGN(sizeof(*cm));
16981b1428dcSMark Johnston 		cm->cmsg_len = CMSG_ALIGN(sizeof(*cm)) + msglen;
16991b1428dcSMark Johnston 
17001b1428dcSMark Johnston 		/* Copy the message body. */
17011b1428dcSMark Johnston 		in1 = (char *)in1 + FREEBSD32_ALIGN(sizeof(*cm));
17021b1428dcSMark Johnston 		md = (char *)md + CMSG_ALIGN(sizeof(*cm));
17031b1428dcSMark Johnston 		memcpy(md, in1, msglen);
17041b1428dcSMark Johnston 		in1 = (char *)in1 + FREEBSD32_ALIGN(msglen);
17051b1428dcSMark Johnston 		md = (char *)md + CMSG_ALIGN(msglen);
17061b1428dcSMark Johnston 		KASSERT(outlen >= CMSG_ALIGN(sizeof(*cm)) + CMSG_ALIGN(msglen),
17071b1428dcSMark Johnston 		    ("outlen %u underflow, msglen %u", outlen, msglen));
17081b1428dcSMark Johnston 		outlen -= CMSG_ALIGN(sizeof(*cm)) + CMSG_ALIGN(msglen);
1709ecc44de7SPaul Saab 	}
1710ecc44de7SPaul Saab 
17110fa211beSMarcel Moolenaar 	*mp = m;
17121b1428dcSMark Johnston out:
17131b1428dcSMark Johnston 	free(in, M_TEMP);
1714ecc44de7SPaul Saab 	return (error);
1715ecc44de7SPaul Saab }
1716ecc44de7SPaul Saab 
1717a372f822SPaul Saab int
freebsd32_sendmsg(struct thread * td,struct freebsd32_sendmsg_args * uap)17184bda16ffSMark Johnston freebsd32_sendmsg(struct thread *td, struct freebsd32_sendmsg_args *uap)
1719a372f822SPaul Saab {
1720a372f822SPaul Saab 	struct msghdr msg;
1721a372f822SPaul Saab 	struct iovec *iov;
1722ecc44de7SPaul Saab 	struct mbuf *control = NULL;
1723ecc44de7SPaul Saab 	struct sockaddr *to = NULL;
1724a372f822SPaul Saab 	int error;
1725a372f822SPaul Saab 
1726a372f822SPaul Saab 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1727a372f822SPaul Saab 	if (error)
1728a372f822SPaul Saab 		return (error);
1729fea1a98eSMark Johnston 	error = freebsd32_copyiniov((void *)msg.msg_iov, msg.msg_iovlen, &iov,
1730acdd09f9SJohn Baldwin 	    EMSGSIZE);
1731a372f822SPaul Saab 	if (error)
1732a372f822SPaul Saab 		return (error);
1733a372f822SPaul Saab 	msg.msg_iov = iov;
1734ecc44de7SPaul Saab 	if (msg.msg_name != NULL) {
1735ecc44de7SPaul Saab 		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1736ecc44de7SPaul Saab 		if (error) {
1737ecc44de7SPaul Saab 			to = NULL;
1738ecc44de7SPaul Saab 			goto out;
1739ecc44de7SPaul Saab 		}
1740ecc44de7SPaul Saab 		msg.msg_name = to;
1741ecc44de7SPaul Saab 	}
1742ecc44de7SPaul Saab 
1743ecc44de7SPaul Saab 	if (msg.msg_control) {
1744ecc44de7SPaul Saab 		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1745ecc44de7SPaul Saab 			error = EINVAL;
1746ecc44de7SPaul Saab 			goto out;
1747ecc44de7SPaul Saab 		}
1748ecc44de7SPaul Saab 
17490fa211beSMarcel Moolenaar 		error = freebsd32_copyin_control(&control, msg.msg_control,
17500fa211beSMarcel Moolenaar 		    msg.msg_controllen);
1751ecc44de7SPaul Saab 		if (error)
1752ecc44de7SPaul Saab 			goto out;
1753ecc44de7SPaul Saab 
17540fa211beSMarcel Moolenaar 		msg.msg_control = NULL;
17550fa211beSMarcel Moolenaar 		msg.msg_controllen = 0;
1756ecc44de7SPaul Saab 	}
1757ecc44de7SPaul Saab 
1758ecc44de7SPaul Saab 	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1759ecc44de7SPaul Saab 	    UIO_USERSPACE);
1760ecc44de7SPaul Saab 
1761ecc44de7SPaul Saab out:
1762a372f822SPaul Saab 	free(iov, M_IOV);
1763ecc44de7SPaul Saab 	if (to)
1764ecc44de7SPaul Saab 		free(to, M_SONAME);
1765a372f822SPaul Saab 	return (error);
1766a372f822SPaul Saab }
1767a372f822SPaul Saab 
1768f089a2f3SBrooks Davis #ifdef COMPAT_43
1769f089a2f3SBrooks Davis int
ofreebsd32_sendmsg(struct thread * td,struct ofreebsd32_sendmsg_args * uap)1770f089a2f3SBrooks Davis ofreebsd32_sendmsg(struct thread *td, struct ofreebsd32_sendmsg_args *uap)
1771f089a2f3SBrooks Davis {
1772f089a2f3SBrooks Davis 	return (ENOSYS);
1773f089a2f3SBrooks Davis }
1774f089a2f3SBrooks Davis #endif
1775f089a2f3SBrooks Davis 
1776f089a2f3SBrooks Davis 
1777a372f822SPaul Saab int
freebsd32_settimeofday(struct thread * td,struct freebsd32_settimeofday_args * uap)17781c7abef7SPeter Wemm freebsd32_settimeofday(struct thread *td,
17791c7abef7SPeter Wemm 		       struct freebsd32_settimeofday_args *uap)
17803ebc1248SPeter Wemm {
178148052f99SJohn Baldwin 	struct timeval32 tv32;
178248052f99SJohn Baldwin 	struct timeval tv, *tvp;
178348052f99SJohn Baldwin 	struct timezone tz, *tzp;
17843ebc1248SPeter Wemm 	int error;
17853ebc1248SPeter Wemm 
178648052f99SJohn Baldwin 	if (uap->tv) {
178748052f99SJohn Baldwin 		error = copyin(uap->tv, &tv32, sizeof(tv32));
17883ebc1248SPeter Wemm 		if (error)
17893ebc1248SPeter Wemm 			return (error);
179048052f99SJohn Baldwin 		CP(tv32, tv, tv_sec);
179148052f99SJohn Baldwin 		CP(tv32, tv, tv_usec);
179248052f99SJohn Baldwin 		tvp = &tv;
179348052f99SJohn Baldwin 	} else
179448052f99SJohn Baldwin 		tvp = NULL;
179548052f99SJohn Baldwin 	if (uap->tzp) {
179648052f99SJohn Baldwin 		error = copyin(uap->tzp, &tz, sizeof(tz));
17973ebc1248SPeter Wemm 		if (error)
17983ebc1248SPeter Wemm 			return (error);
179948052f99SJohn Baldwin 		tzp = &tz;
180048052f99SJohn Baldwin 	} else
180148052f99SJohn Baldwin 		tzp = NULL;
180248052f99SJohn Baldwin 	return (kern_settimeofday(td, tvp, tzp));
18033ebc1248SPeter Wemm }
18043ebc1248SPeter Wemm 
18053ebc1248SPeter Wemm int
freebsd32_utimes(struct thread * td,struct freebsd32_utimes_args * uap)18061c7abef7SPeter Wemm freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
18073ebc1248SPeter Wemm {
180838765a31SJohn Baldwin 	struct timeval32 s32[2];
180938765a31SJohn Baldwin 	struct timeval s[2], *sp;
18103ebc1248SPeter Wemm 	int error;
18113ebc1248SPeter Wemm 
181238765a31SJohn Baldwin 	if (uap->tptr != NULL) {
181338765a31SJohn Baldwin 		error = copyin(uap->tptr, s32, sizeof(s32));
18143ebc1248SPeter Wemm 		if (error)
18153ebc1248SPeter Wemm 			return (error);
18163ebc1248SPeter Wemm 		CP(s32[0], s[0], tv_sec);
18173ebc1248SPeter Wemm 		CP(s32[0], s[0], tv_usec);
18183ebc1248SPeter Wemm 		CP(s32[1], s[1], tv_sec);
18193ebc1248SPeter Wemm 		CP(s32[1], s[1], tv_usec);
182038765a31SJohn Baldwin 		sp = s;
182138765a31SJohn Baldwin 	} else
182238765a31SJohn Baldwin 		sp = NULL;
18236e646651SKonstantin Belousov 	return (kern_utimesat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
18246e646651SKonstantin Belousov 	    sp, UIO_SYSSPACE));
18253ebc1248SPeter Wemm }
18263ebc1248SPeter Wemm 
18273ebc1248SPeter Wemm int
freebsd32_lutimes(struct thread * td,struct freebsd32_lutimes_args * uap)182808a3081dSDoug Ambrisko freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
182908a3081dSDoug Ambrisko {
183008a3081dSDoug Ambrisko 	struct timeval32 s32[2];
183108a3081dSDoug Ambrisko 	struct timeval s[2], *sp;
183208a3081dSDoug Ambrisko 	int error;
183308a3081dSDoug Ambrisko 
183408a3081dSDoug Ambrisko 	if (uap->tptr != NULL) {
183508a3081dSDoug Ambrisko 		error = copyin(uap->tptr, s32, sizeof(s32));
183608a3081dSDoug Ambrisko 		if (error)
183708a3081dSDoug Ambrisko 			return (error);
183808a3081dSDoug Ambrisko 		CP(s32[0], s[0], tv_sec);
183908a3081dSDoug Ambrisko 		CP(s32[0], s[0], tv_usec);
184008a3081dSDoug Ambrisko 		CP(s32[1], s[1], tv_sec);
184108a3081dSDoug Ambrisko 		CP(s32[1], s[1], tv_usec);
184208a3081dSDoug Ambrisko 		sp = s;
184308a3081dSDoug Ambrisko 	} else
184408a3081dSDoug Ambrisko 		sp = NULL;
184508a3081dSDoug Ambrisko 	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
184608a3081dSDoug Ambrisko }
184708a3081dSDoug Ambrisko 
184808a3081dSDoug Ambrisko int
freebsd32_futimes(struct thread * td,struct freebsd32_futimes_args * uap)18498e7604dbSDoug Ambrisko freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
18508e7604dbSDoug Ambrisko {
18518e7604dbSDoug Ambrisko 	struct timeval32 s32[2];
18528e7604dbSDoug Ambrisko 	struct timeval s[2], *sp;
18538e7604dbSDoug Ambrisko 	int error;
18548e7604dbSDoug Ambrisko 
18558e7604dbSDoug Ambrisko 	if (uap->tptr != NULL) {
18568e7604dbSDoug Ambrisko 		error = copyin(uap->tptr, s32, sizeof(s32));
18578e7604dbSDoug Ambrisko 		if (error)
18588e7604dbSDoug Ambrisko 			return (error);
18598e7604dbSDoug Ambrisko 		CP(s32[0], s[0], tv_sec);
18608e7604dbSDoug Ambrisko 		CP(s32[0], s[0], tv_usec);
18618e7604dbSDoug Ambrisko 		CP(s32[1], s[1], tv_sec);
18628e7604dbSDoug Ambrisko 		CP(s32[1], s[1], tv_usec);
18638e7604dbSDoug Ambrisko 		sp = s;
18648e7604dbSDoug Ambrisko 	} else
18658e7604dbSDoug Ambrisko 		sp = NULL;
18668e7604dbSDoug Ambrisko 	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
18678e7604dbSDoug Ambrisko }
18688e7604dbSDoug Ambrisko 
18694f1e7213SKonstantin Belousov int
freebsd32_futimesat(struct thread * td,struct freebsd32_futimesat_args * uap)18704f1e7213SKonstantin Belousov freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
18714f1e7213SKonstantin Belousov {
18724f1e7213SKonstantin Belousov 	struct timeval32 s32[2];
18734f1e7213SKonstantin Belousov 	struct timeval s[2], *sp;
18744f1e7213SKonstantin Belousov 	int error;
18754f1e7213SKonstantin Belousov 
18764f1e7213SKonstantin Belousov 	if (uap->times != NULL) {
18774f1e7213SKonstantin Belousov 		error = copyin(uap->times, s32, sizeof(s32));
18784f1e7213SKonstantin Belousov 		if (error)
18794f1e7213SKonstantin Belousov 			return (error);
18804f1e7213SKonstantin Belousov 		CP(s32[0], s[0], tv_sec);
18814f1e7213SKonstantin Belousov 		CP(s32[0], s[0], tv_usec);
18824f1e7213SKonstantin Belousov 		CP(s32[1], s[1], tv_sec);
18834f1e7213SKonstantin Belousov 		CP(s32[1], s[1], tv_usec);
18844f1e7213SKonstantin Belousov 		sp = s;
18854f1e7213SKonstantin Belousov 	} else
18864f1e7213SKonstantin Belousov 		sp = NULL;
18874f1e7213SKonstantin Belousov 	return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
18884f1e7213SKonstantin Belousov 		sp, UIO_SYSSPACE));
18894f1e7213SKonstantin Belousov }
18908e7604dbSDoug Ambrisko 
18918e7604dbSDoug Ambrisko int
freebsd32_futimens(struct thread * td,struct freebsd32_futimens_args * uap)18922205e0d1SJilles Tjoelker freebsd32_futimens(struct thread *td, struct freebsd32_futimens_args *uap)
18932205e0d1SJilles Tjoelker {
18942205e0d1SJilles Tjoelker 	struct timespec32 ts32[2];
18952205e0d1SJilles Tjoelker 	struct timespec ts[2], *tsp;
18962205e0d1SJilles Tjoelker 	int error;
18972205e0d1SJilles Tjoelker 
18982205e0d1SJilles Tjoelker 	if (uap->times != NULL) {
18992205e0d1SJilles Tjoelker 		error = copyin(uap->times, ts32, sizeof(ts32));
19002205e0d1SJilles Tjoelker 		if (error)
19012205e0d1SJilles Tjoelker 			return (error);
19022205e0d1SJilles Tjoelker 		CP(ts32[0], ts[0], tv_sec);
19032205e0d1SJilles Tjoelker 		CP(ts32[0], ts[0], tv_nsec);
19042205e0d1SJilles Tjoelker 		CP(ts32[1], ts[1], tv_sec);
19052205e0d1SJilles Tjoelker 		CP(ts32[1], ts[1], tv_nsec);
19062205e0d1SJilles Tjoelker 		tsp = ts;
19072205e0d1SJilles Tjoelker 	} else
19082205e0d1SJilles Tjoelker 		tsp = NULL;
19092205e0d1SJilles Tjoelker 	return (kern_futimens(td, uap->fd, tsp, UIO_SYSSPACE));
19102205e0d1SJilles Tjoelker }
19112205e0d1SJilles Tjoelker 
19122205e0d1SJilles Tjoelker int
freebsd32_utimensat(struct thread * td,struct freebsd32_utimensat_args * uap)19132205e0d1SJilles Tjoelker freebsd32_utimensat(struct thread *td, struct freebsd32_utimensat_args *uap)
19142205e0d1SJilles Tjoelker {
19152205e0d1SJilles Tjoelker 	struct timespec32 ts32[2];
19162205e0d1SJilles Tjoelker 	struct timespec ts[2], *tsp;
19172205e0d1SJilles Tjoelker 	int error;
19182205e0d1SJilles Tjoelker 
19192205e0d1SJilles Tjoelker 	if (uap->times != NULL) {
19202205e0d1SJilles Tjoelker 		error = copyin(uap->times, ts32, sizeof(ts32));
19212205e0d1SJilles Tjoelker 		if (error)
19222205e0d1SJilles Tjoelker 			return (error);
19232205e0d1SJilles Tjoelker 		CP(ts32[0], ts[0], tv_sec);
19242205e0d1SJilles Tjoelker 		CP(ts32[0], ts[0], tv_nsec);
19252205e0d1SJilles Tjoelker 		CP(ts32[1], ts[1], tv_sec);
19262205e0d1SJilles Tjoelker 		CP(ts32[1], ts[1], tv_nsec);
19272205e0d1SJilles Tjoelker 		tsp = ts;
19282205e0d1SJilles Tjoelker 	} else
19292205e0d1SJilles Tjoelker 		tsp = NULL;
19302205e0d1SJilles Tjoelker 	return (kern_utimensat(td, uap->fd, uap->path, UIO_USERSPACE,
19312205e0d1SJilles Tjoelker 	    tsp, UIO_SYSSPACE, uap->flag));
19322205e0d1SJilles Tjoelker }
19332205e0d1SJilles Tjoelker 
19342205e0d1SJilles Tjoelker int
freebsd32_adjtime(struct thread * td,struct freebsd32_adjtime_args * uap)19351c7abef7SPeter Wemm freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
19363ebc1248SPeter Wemm {
193748052f99SJohn Baldwin 	struct timeval32 tv32;
193848052f99SJohn Baldwin 	struct timeval delta, olddelta, *deltap;
19393ebc1248SPeter Wemm 	int error;
19403ebc1248SPeter Wemm 
194148052f99SJohn Baldwin 	if (uap->delta) {
194248052f99SJohn Baldwin 		error = copyin(uap->delta, &tv32, sizeof(tv32));
19433ebc1248SPeter Wemm 		if (error)
19443ebc1248SPeter Wemm 			return (error);
194548052f99SJohn Baldwin 		CP(tv32, delta, tv_sec);
194648052f99SJohn Baldwin 		CP(tv32, delta, tv_usec);
194748052f99SJohn Baldwin 		deltap = &delta;
194848052f99SJohn Baldwin 	} else
194948052f99SJohn Baldwin 		deltap = NULL;
195048052f99SJohn Baldwin 	error = kern_adjtime(td, deltap, &olddelta);
195148052f99SJohn Baldwin 	if (uap->olddelta && error == 0) {
195248052f99SJohn Baldwin 		CP(olddelta, tv32, tv_sec);
195348052f99SJohn Baldwin 		CP(olddelta, tv32, tv_usec);
195448052f99SJohn Baldwin 		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
19553ebc1248SPeter Wemm 	}
19563ebc1248SPeter Wemm 	return (error);
19573ebc1248SPeter Wemm }
19583ebc1248SPeter Wemm 
1959c050455eSMarcel Moolenaar #ifdef COMPAT_FREEBSD4
19603ebc1248SPeter Wemm int
freebsd4_freebsd32_statfs(struct thread * td,struct freebsd4_freebsd32_statfs_args * uap)19610c70bcedSPeter Wemm freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
19623ebc1248SPeter Wemm {
19632e89f95dSBrooks Davis 	struct ostatfs32 s32;
19642f304845SKonstantin Belousov 	struct statfs *sp;
19653ebc1248SPeter Wemm 	int error;
19663ebc1248SPeter Wemm 
19672f304845SKonstantin Belousov 	sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
19682f304845SKonstantin Belousov 	error = kern_statfs(td, uap->path, UIO_USERSPACE, sp);
19692f304845SKonstantin Belousov 	if (error == 0) {
19702f304845SKonstantin Belousov 		copy_statfs(sp, &s32);
19712f304845SKonstantin Belousov 		error = copyout(&s32, uap->buf, sizeof(s32));
19722f304845SKonstantin Belousov 	}
19732f304845SKonstantin Belousov 	free(sp, M_STATFS);
19743ebc1248SPeter Wemm 	return (error);
19753ebc1248SPeter Wemm }
1976c050455eSMarcel Moolenaar #endif
19773ebc1248SPeter Wemm 
1978c050455eSMarcel Moolenaar #ifdef COMPAT_FREEBSD4
19793ebc1248SPeter Wemm int
freebsd4_freebsd32_fstatfs(struct thread * td,struct freebsd4_freebsd32_fstatfs_args * uap)19800c70bcedSPeter Wemm freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
19813ebc1248SPeter Wemm {
19822e89f95dSBrooks Davis 	struct ostatfs32 s32;
19832f304845SKonstantin Belousov 	struct statfs *sp;
19843ebc1248SPeter Wemm 	int error;
19853ebc1248SPeter Wemm 
19862f304845SKonstantin Belousov 	sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
19872f304845SKonstantin Belousov 	error = kern_fstatfs(td, uap->fd, sp);
19882f304845SKonstantin Belousov 	if (error == 0) {
19892f304845SKonstantin Belousov 		copy_statfs(sp, &s32);
19902f304845SKonstantin Belousov 		error = copyout(&s32, uap->buf, sizeof(s32));
19912f304845SKonstantin Belousov 	}
19922f304845SKonstantin Belousov 	free(sp, M_STATFS);
19933ebc1248SPeter Wemm 	return (error);
19943ebc1248SPeter Wemm }
1995c050455eSMarcel Moolenaar #endif
19963ebc1248SPeter Wemm 
1997c050455eSMarcel Moolenaar #ifdef COMPAT_FREEBSD4
19983ebc1248SPeter Wemm int
freebsd4_freebsd32_fhstatfs(struct thread * td,struct freebsd4_freebsd32_fhstatfs_args * uap)19990c70bcedSPeter Wemm freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
20000c70bcedSPeter Wemm {
20012e89f95dSBrooks Davis 	struct ostatfs32 s32;
20022f304845SKonstantin Belousov 	struct statfs *sp;
200338765a31SJohn Baldwin 	fhandle_t fh;
20040c70bcedSPeter Wemm 	int error;
20050c70bcedSPeter Wemm 
200638765a31SJohn Baldwin 	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
20070c70bcedSPeter Wemm 		return (error);
20082f304845SKonstantin Belousov 	sp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
20092f304845SKonstantin Belousov 	error = kern_fhstatfs(td, fh, sp);
20102f304845SKonstantin Belousov 	if (error == 0) {
20112f304845SKonstantin Belousov 		copy_statfs(sp, &s32);
20122f304845SKonstantin Belousov 		error = copyout(&s32, uap->buf, sizeof(s32));
20132f304845SKonstantin Belousov 	}
20142f304845SKonstantin Belousov 	free(sp, M_STATFS);
20150c70bcedSPeter Wemm 	return (error);
20160c70bcedSPeter Wemm }
2017c050455eSMarcel Moolenaar #endif
20180c70bcedSPeter Wemm 
20190c70bcedSPeter Wemm int
freebsd32_pread(struct thread * td,struct freebsd32_pread_args * uap)20201c7abef7SPeter Wemm freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
20213ebc1248SPeter Wemm {
20223ebc1248SPeter Wemm 
2023b38b22b0SEdward Tomasz Napierala 	return (kern_pread(td, uap->fd, uap->buf, uap->nbyte,
2024b38b22b0SEdward Tomasz Napierala 	    PAIR32TO64(off_t, uap->offset)));
20253ebc1248SPeter Wemm }
20263ebc1248SPeter Wemm 
20273ebc1248SPeter Wemm int
freebsd32_pwrite(struct thread * td,struct freebsd32_pwrite_args * uap)20281c7abef7SPeter Wemm freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
20293ebc1248SPeter Wemm {
20303ebc1248SPeter Wemm 
2031b38b22b0SEdward Tomasz Napierala 	return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte,
2032b38b22b0SEdward Tomasz Napierala 	    PAIR32TO64(off_t, uap->offset)));
20333ebc1248SPeter Wemm }
20343ebc1248SPeter Wemm 
203571812178SKonstantin Belousov #ifdef COMPAT_43
203671812178SKonstantin Belousov int
ofreebsd32_lseek(struct thread * td,struct ofreebsd32_lseek_args * uap)203771812178SKonstantin Belousov ofreebsd32_lseek(struct thread *td, struct ofreebsd32_lseek_args *uap)
203871812178SKonstantin Belousov {
203971812178SKonstantin Belousov 
2040f67d6b5fSEdward Tomasz Napierala 	return (kern_lseek(td, uap->fd, uap->offset, uap->whence));
204171812178SKonstantin Belousov }
204271812178SKonstantin Belousov #endif
204371812178SKonstantin Belousov 
20443ebc1248SPeter Wemm int
freebsd32_lseek(struct thread * td,struct freebsd32_lseek_args * uap)20451c7abef7SPeter Wemm freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
20463ebc1248SPeter Wemm {
20473ebc1248SPeter Wemm 	int error;
20483ebc1248SPeter Wemm 	off_t pos;
20493ebc1248SPeter Wemm 
2050f67d6b5fSEdward Tomasz Napierala 	error = kern_lseek(td, uap->fd, PAIR32TO64(off_t, uap->offset),
2051f67d6b5fSEdward Tomasz Napierala 	    uap->whence);
20523ebc1248SPeter Wemm 	/* Expand the quad return into two parts for eax and edx */
20536f2b769cSJohn-Mark Gurney 	pos = td->td_uretoff.tdu_off;
2054841c0c7eSNathan Whitehorn 	td->td_retval[RETVAL_LO] = pos & 0xffffffff;	/* %eax */
2055841c0c7eSNathan Whitehorn 	td->td_retval[RETVAL_HI] = pos >> 32;		/* %edx */
20563ebc1248SPeter Wemm 	return error;
20573ebc1248SPeter Wemm }
20583ebc1248SPeter Wemm 
20593ebc1248SPeter Wemm int
freebsd32_truncate(struct thread * td,struct freebsd32_truncate_args * uap)20601c7abef7SPeter Wemm freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
20613ebc1248SPeter Wemm {
20623ebc1248SPeter Wemm 
2063fc8bde8fSEdward Tomasz Napierala 	return (kern_truncate(td, uap->path, UIO_USERSPACE,
2064fc8bde8fSEdward Tomasz Napierala 	    PAIR32TO64(off_t, uap->length)));
20653ebc1248SPeter Wemm }
20663ebc1248SPeter Wemm 
2067f19e3fd2SBrooks Davis #ifdef COMPAT_43
2068f19e3fd2SBrooks Davis int
ofreebsd32_truncate(struct thread * td,struct ofreebsd32_truncate_args * uap)2069f19e3fd2SBrooks Davis ofreebsd32_truncate(struct thread *td, struct ofreebsd32_truncate_args *uap)
2070f19e3fd2SBrooks Davis {
2071f19e3fd2SBrooks Davis 	return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
2072f19e3fd2SBrooks Davis }
2073f19e3fd2SBrooks Davis #endif
2074f19e3fd2SBrooks Davis 
20753ebc1248SPeter Wemm int
freebsd32_ftruncate(struct thread * td,struct freebsd32_ftruncate_args * uap)20761c7abef7SPeter Wemm freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
20773ebc1248SPeter Wemm {
20783ebc1248SPeter Wemm 
2079ae6b6ef6SEdward Tomasz Napierala 	return (kern_ftruncate(td, uap->fd, PAIR32TO64(off_t, uap->length)));
20803ebc1248SPeter Wemm }
20813ebc1248SPeter Wemm 
20827332c129SKonstantin Belousov #ifdef COMPAT_43
20837332c129SKonstantin Belousov int
ofreebsd32_ftruncate(struct thread * td,struct ofreebsd32_ftruncate_args * uap)2084f19e3fd2SBrooks Davis ofreebsd32_ftruncate(struct thread *td, struct ofreebsd32_ftruncate_args *uap)
2085f19e3fd2SBrooks Davis {
2086f19e3fd2SBrooks Davis 	return (kern_ftruncate(td, uap->fd, uap->length));
2087f19e3fd2SBrooks Davis }
2088f19e3fd2SBrooks Davis 
2089f19e3fd2SBrooks Davis int
ofreebsd32_getdirentries(struct thread * td,struct ofreebsd32_getdirentries_args * uap)20907332c129SKonstantin Belousov ofreebsd32_getdirentries(struct thread *td,
20917332c129SKonstantin Belousov     struct ofreebsd32_getdirentries_args *uap)
20927332c129SKonstantin Belousov {
20937332c129SKonstantin Belousov 	struct ogetdirentries_args ap;
20947332c129SKonstantin Belousov 	int error;
20957332c129SKonstantin Belousov 	long loff;
20967332c129SKonstantin Belousov 	int32_t loff_cut;
20977332c129SKonstantin Belousov 
20987332c129SKonstantin Belousov 	ap.fd = uap->fd;
20997332c129SKonstantin Belousov 	ap.buf = uap->buf;
21007332c129SKonstantin Belousov 	ap.count = uap->count;
21017332c129SKonstantin Belousov 	ap.basep = NULL;
21027332c129SKonstantin Belousov 	error = kern_ogetdirentries(td, &ap, &loff);
21037332c129SKonstantin Belousov 	if (error == 0) {
21047332c129SKonstantin Belousov 		loff_cut = loff;
21057332c129SKonstantin Belousov 		error = copyout(&loff_cut, uap->basep, sizeof(int32_t));
21067332c129SKonstantin Belousov 	}
21077332c129SKonstantin Belousov 	return (error);
21087332c129SKonstantin Belousov }
21097332c129SKonstantin Belousov #endif
21107332c129SKonstantin Belousov 
211169921123SKonstantin Belousov #if defined(COMPAT_FREEBSD11)
211269921123SKonstantin Belousov int
freebsd11_freebsd32_getdirentries(struct thread * td,struct freebsd11_freebsd32_getdirentries_args * uap)211369921123SKonstantin Belousov freebsd11_freebsd32_getdirentries(struct thread *td,
211469921123SKonstantin Belousov     struct freebsd11_freebsd32_getdirentries_args *uap)
211569921123SKonstantin Belousov {
211669921123SKonstantin Belousov 	long base;
211769921123SKonstantin Belousov 	int32_t base32;
211869921123SKonstantin Belousov 	int error;
211969921123SKonstantin Belousov 
212069921123SKonstantin Belousov 	error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
212169921123SKonstantin Belousov 	    &base, NULL);
212269921123SKonstantin Belousov 	if (error)
212369921123SKonstantin Belousov 		return (error);
212469921123SKonstantin Belousov 	if (uap->basep != NULL) {
212569921123SKonstantin Belousov 		base32 = base;
212669921123SKonstantin Belousov 		error = copyout(&base32, uap->basep, sizeof(int32_t));
212769921123SKonstantin Belousov 	}
212869921123SKonstantin Belousov 	return (error);
212969921123SKonstantin Belousov }
213069921123SKonstantin Belousov #endif /* COMPAT_FREEBSD11 */
213169921123SKonstantin Belousov 
21325aa69f9cSPeter Wemm #ifdef COMPAT_FREEBSD6
21335aa69f9cSPeter Wemm /* versions with the 'int pad' argument */
21345aa69f9cSPeter Wemm int
freebsd6_freebsd32_pread(struct thread * td,struct freebsd6_freebsd32_pread_args * uap)21355aa69f9cSPeter Wemm freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
21365aa69f9cSPeter Wemm {
21375aa69f9cSPeter Wemm 
2138b38b22b0SEdward Tomasz Napierala 	return (kern_pread(td, uap->fd, uap->buf, uap->nbyte,
2139b38b22b0SEdward Tomasz Napierala 	    PAIR32TO64(off_t, uap->offset)));
21405aa69f9cSPeter Wemm }
21415aa69f9cSPeter Wemm 
21425aa69f9cSPeter Wemm int
freebsd6_freebsd32_pwrite(struct thread * td,struct freebsd6_freebsd32_pwrite_args * uap)21435aa69f9cSPeter Wemm freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
21445aa69f9cSPeter Wemm {
21455aa69f9cSPeter Wemm 
2146b38b22b0SEdward Tomasz Napierala 	return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte,
2147b38b22b0SEdward Tomasz Napierala 	    PAIR32TO64(off_t, uap->offset)));
21485aa69f9cSPeter Wemm }
21495aa69f9cSPeter Wemm 
21505aa69f9cSPeter Wemm int
freebsd6_freebsd32_lseek(struct thread * td,struct freebsd6_freebsd32_lseek_args * uap)21515aa69f9cSPeter Wemm freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
21525aa69f9cSPeter Wemm {
21535aa69f9cSPeter Wemm 	int error;
21545aa69f9cSPeter Wemm 	off_t pos;
21555aa69f9cSPeter Wemm 
2156f67d6b5fSEdward Tomasz Napierala 	error = kern_lseek(td, uap->fd, PAIR32TO64(off_t, uap->offset),
2157f67d6b5fSEdward Tomasz Napierala 	    uap->whence);
21585aa69f9cSPeter Wemm 	/* Expand the quad return into two parts for eax and edx */
21595aa69f9cSPeter Wemm 	pos = *(off_t *)(td->td_retval);
2160841c0c7eSNathan Whitehorn 	td->td_retval[RETVAL_LO] = pos & 0xffffffff;	/* %eax */
2161841c0c7eSNathan Whitehorn 	td->td_retval[RETVAL_HI] = pos >> 32;		/* %edx */
21625aa69f9cSPeter Wemm 	return error;
21635aa69f9cSPeter Wemm }
21645aa69f9cSPeter Wemm 
21655aa69f9cSPeter Wemm int
freebsd6_freebsd32_truncate(struct thread * td,struct freebsd6_freebsd32_truncate_args * uap)21665aa69f9cSPeter Wemm freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
21675aa69f9cSPeter Wemm {
21685aa69f9cSPeter Wemm 
2169fc8bde8fSEdward Tomasz Napierala 	return (kern_truncate(td, uap->path, UIO_USERSPACE,
2170fc8bde8fSEdward Tomasz Napierala 	    PAIR32TO64(off_t, uap->length)));
21715aa69f9cSPeter Wemm }
21725aa69f9cSPeter Wemm 
21735aa69f9cSPeter Wemm int
freebsd6_freebsd32_ftruncate(struct thread * td,struct freebsd6_freebsd32_ftruncate_args * uap)21745aa69f9cSPeter Wemm freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
21755aa69f9cSPeter Wemm {
21765aa69f9cSPeter Wemm 
2177ae6b6ef6SEdward Tomasz Napierala 	return (kern_ftruncate(td, uap->fd, PAIR32TO64(off_t, uap->length)));
21785aa69f9cSPeter Wemm }
21795aa69f9cSPeter Wemm #endif /* COMPAT_FREEBSD6 */
21805aa69f9cSPeter Wemm 
2181fa545f43SPaul Saab struct sf_hdtr32 {
2182fa545f43SPaul Saab 	uint32_t headers;
2183fa545f43SPaul Saab 	int hdr_cnt;
2184fa545f43SPaul Saab 	uint32_t trailers;
2185fa545f43SPaul Saab 	int trl_cnt;
2186fa545f43SPaul Saab };
2187fa545f43SPaul Saab 
2188fa545f43SPaul Saab static int
freebsd32_do_sendfile(struct thread * td,struct freebsd32_sendfile_args * uap,int compat)2189fa545f43SPaul Saab freebsd32_do_sendfile(struct thread *td,
2190fa545f43SPaul Saab     struct freebsd32_sendfile_args *uap, int compat)
2191fa545f43SPaul Saab {
2192fa545f43SPaul Saab 	struct sf_hdtr32 hdtr32;
2193fa545f43SPaul Saab 	struct sf_hdtr hdtr;
2194fa545f43SPaul Saab 	struct uio *hdr_uio, *trl_uio;
2195efe28398SGleb Smirnoff 	struct file *fp;
2196efe28398SGleb Smirnoff 	cap_rights_t rights;
2197fa545f43SPaul Saab 	struct iovec32 *iov32;
21980e87b36eSGleb Smirnoff 	off_t offset, sbytes;
2199fa545f43SPaul Saab 	int error;
2200fa545f43SPaul Saab 
2201ca04d21dSGleb Smirnoff 	offset = PAIR32TO64(off_t, uap->offset);
2202ca04d21dSGleb Smirnoff 	if (offset < 0)
2203ca04d21dSGleb Smirnoff 		return (EINVAL);
2204fa545f43SPaul Saab 
2205ca04d21dSGleb Smirnoff 	hdr_uio = trl_uio = NULL;
2206fa545f43SPaul Saab 
2207fa545f43SPaul Saab 	if (uap->hdtr != NULL) {
2208fa545f43SPaul Saab 		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
2209fa545f43SPaul Saab 		if (error)
2210fa545f43SPaul Saab 			goto out;
2211fa545f43SPaul Saab 		PTRIN_CP(hdtr32, hdtr, headers);
2212fa545f43SPaul Saab 		CP(hdtr32, hdtr, hdr_cnt);
2213fa545f43SPaul Saab 		PTRIN_CP(hdtr32, hdtr, trailers);
2214fa545f43SPaul Saab 		CP(hdtr32, hdtr, trl_cnt);
2215fa545f43SPaul Saab 
2216fa545f43SPaul Saab 		if (hdtr.headers != NULL) {
2217acdd09f9SJohn Baldwin 			iov32 = PTRIN(hdtr32.headers);
2218fa545f43SPaul Saab 			error = freebsd32_copyinuio(iov32,
2219fa545f43SPaul Saab 			    hdtr32.hdr_cnt, &hdr_uio);
2220fa545f43SPaul Saab 			if (error)
2221fa545f43SPaul Saab 				goto out;
22229c64cfe5SGleb Smirnoff #ifdef COMPAT_FREEBSD4
22239c64cfe5SGleb Smirnoff 			/*
22249c64cfe5SGleb Smirnoff 			 * In FreeBSD < 5.0 the nbytes to send also included
22259c64cfe5SGleb Smirnoff 			 * the header.  If compat is specified subtract the
22269c64cfe5SGleb Smirnoff 			 * header size from nbytes.
22279c64cfe5SGleb Smirnoff 			 */
22289c64cfe5SGleb Smirnoff 			if (compat) {
22299c64cfe5SGleb Smirnoff 				if (uap->nbytes > hdr_uio->uio_resid)
22309c64cfe5SGleb Smirnoff 					uap->nbytes -= hdr_uio->uio_resid;
22319c64cfe5SGleb Smirnoff 				else
22329c64cfe5SGleb Smirnoff 					uap->nbytes = 0;
22339c64cfe5SGleb Smirnoff 			}
22349c64cfe5SGleb Smirnoff #endif
2235fa545f43SPaul Saab 		}
2236fa545f43SPaul Saab 		if (hdtr.trailers != NULL) {
2237acdd09f9SJohn Baldwin 			iov32 = PTRIN(hdtr32.trailers);
2238fa545f43SPaul Saab 			error = freebsd32_copyinuio(iov32,
2239fa545f43SPaul Saab 			    hdtr32.trl_cnt, &trl_uio);
2240fa545f43SPaul Saab 			if (error)
2241fa545f43SPaul Saab 				goto out;
2242fa545f43SPaul Saab 		}
22430e87b36eSGleb Smirnoff 	}
22440cfea1c8SAdrian Chadd 
22450e87b36eSGleb Smirnoff 	AUDIT_ARG_FD(uap->fd);
22460e87b36eSGleb Smirnoff 
22470e87b36eSGleb Smirnoff 	if ((error = fget_read(td, uap->fd,
22486b3a9a0fSMateusz Guzik 	    cap_rights_init_one(&rights, CAP_PREAD), &fp)) != 0)
22490cfea1c8SAdrian Chadd 		goto out;
22500cfea1c8SAdrian Chadd 
22510e87b36eSGleb Smirnoff 	error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, offset,
22529c64cfe5SGleb Smirnoff 	    uap->nbytes, &sbytes, uap->flags, td);
22530e87b36eSGleb Smirnoff 	fdrop(fp, td);
2254ca04d21dSGleb Smirnoff 
22557689abaeSAdrian Chadd 	if (uap->sbytes != NULL)
2256d0adc2f2SMark Johnston 		(void)copyout(&sbytes, uap->sbytes, sizeof(off_t));
2257ca04d21dSGleb Smirnoff 
2258fa545f43SPaul Saab out:
2259fa545f43SPaul Saab 	if (hdr_uio)
226061cc4830SAlfredo Mazzinghi 		freeuio(hdr_uio);
2261fa545f43SPaul Saab 	if (trl_uio)
226261cc4830SAlfredo Mazzinghi 		freeuio(trl_uio);
2263fa545f43SPaul Saab 	return (error);
2264fa545f43SPaul Saab }
2265fa545f43SPaul Saab 
2266459e3a7aSPeter Wemm #ifdef COMPAT_FREEBSD4
2267459e3a7aSPeter Wemm int
freebsd4_freebsd32_sendfile(struct thread * td,struct freebsd4_freebsd32_sendfile_args * uap)22681c7abef7SPeter Wemm freebsd4_freebsd32_sendfile(struct thread *td,
22691c7abef7SPeter Wemm     struct freebsd4_freebsd32_sendfile_args *uap)
2270459e3a7aSPeter Wemm {
2271fa545f43SPaul Saab 	return (freebsd32_do_sendfile(td,
2272fa545f43SPaul Saab 	    (struct freebsd32_sendfile_args *)uap, 1));
2273459e3a7aSPeter Wemm }
2274459e3a7aSPeter Wemm #endif
2275459e3a7aSPeter Wemm 
22763ebc1248SPeter Wemm int
freebsd32_sendfile(struct thread * td,struct freebsd32_sendfile_args * uap)22771c7abef7SPeter Wemm freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
22783ebc1248SPeter Wemm {
22793ebc1248SPeter Wemm 
2280fa545f43SPaul Saab 	return (freebsd32_do_sendfile(td, uap, 0));
22813ebc1248SPeter Wemm }
22823ebc1248SPeter Wemm 
22833ebc1248SPeter Wemm static void
copy_stat(struct stat * in,struct stat32 * out)22843ebc1248SPeter Wemm copy_stat(struct stat *in, struct stat32 *out)
22853ebc1248SPeter Wemm {
228645b6fa3bSKonstantin Belousov 
2287f90cd1aeSEd Maste #ifndef __amd64__
2288f90cd1aeSEd Maste 	/*
2289f90cd1aeSEd Maste 	 * 32-bit architectures other than i386 have 64-bit time_t.  This
2290f90cd1aeSEd Maste 	 * results in struct timespec32 with 12 bytes for tv_sec and tv_nsec,
2291f90cd1aeSEd Maste 	 * and 4 bytes of padding.  Zero the padding holes in struct stat32.
2292f90cd1aeSEd Maste 	 */
2293f90cd1aeSEd Maste 	bzero(&out->st_atim, sizeof(out->st_atim));
2294f90cd1aeSEd Maste 	bzero(&out->st_mtim, sizeof(out->st_mtim));
2295f90cd1aeSEd Maste 	bzero(&out->st_ctim, sizeof(out->st_ctim));
2296f90cd1aeSEd Maste 	bzero(&out->st_birthtim, sizeof(out->st_birthtim));
2297f90cd1aeSEd Maste #endif
22983ebc1248SPeter Wemm 	CP(*in, *out, st_dev);
22993ebc1248SPeter Wemm 	CP(*in, *out, st_ino);
23003ebc1248SPeter Wemm 	CP(*in, *out, st_mode);
23013ebc1248SPeter Wemm 	CP(*in, *out, st_nlink);
23023ebc1248SPeter Wemm 	CP(*in, *out, st_uid);
23033ebc1248SPeter Wemm 	CP(*in, *out, st_gid);
23043ebc1248SPeter Wemm 	CP(*in, *out, st_rdev);
2305510ea843SEd Schouten 	TS_CP(*in, *out, st_atim);
2306510ea843SEd Schouten 	TS_CP(*in, *out, st_mtim);
2307510ea843SEd Schouten 	TS_CP(*in, *out, st_ctim);
23083ebc1248SPeter Wemm 	CP(*in, *out, st_size);
23093ebc1248SPeter Wemm 	CP(*in, *out, st_blocks);
23103ebc1248SPeter Wemm 	CP(*in, *out, st_blksize);
23113ebc1248SPeter Wemm 	CP(*in, *out, st_flags);
23123ebc1248SPeter Wemm 	CP(*in, *out, st_gen);
2313b4663a8dSKonstantin Belousov 	CP(*in, *out, st_filerev);
231486db734aSKonstantin Belousov 	CP(*in, *out, st_bsdflags);
231564dc04deSKonstantin Belousov 	TS_CP(*in, *out, st_birthtim);
231669921123SKonstantin Belousov 	out->st_padding1 = 0;
231769921123SKonstantin Belousov #ifdef __STAT32_TIME_T_EXT
231869921123SKonstantin Belousov 	out->st_atim_ext = 0;
231969921123SKonstantin Belousov 	out->st_mtim_ext = 0;
232069921123SKonstantin Belousov 	out->st_ctim_ext = 0;
232169921123SKonstantin Belousov 	out->st_btim_ext = 0;
232269921123SKonstantin Belousov #endif
232369921123SKonstantin Belousov 	bzero(out->st_spare, sizeof(out->st_spare));
23243ebc1248SPeter Wemm }
23253ebc1248SPeter Wemm 
23267332c129SKonstantin Belousov #ifdef COMPAT_43
23277332c129SKonstantin Belousov static void
copy_ostat(struct stat * in,struct ostat32 * out)23287332c129SKonstantin Belousov copy_ostat(struct stat *in, struct ostat32 *out)
23297332c129SKonstantin Belousov {
23307332c129SKonstantin Belousov 
2331372639f9SBruce Evans 	bzero(out, sizeof(*out));
23327332c129SKonstantin Belousov 	CP(*in, *out, st_dev);
23337332c129SKonstantin Belousov 	CP(*in, *out, st_ino);
23347332c129SKonstantin Belousov 	CP(*in, *out, st_mode);
23357332c129SKonstantin Belousov 	CP(*in, *out, st_nlink);
23367332c129SKonstantin Belousov 	CP(*in, *out, st_uid);
23377332c129SKonstantin Belousov 	CP(*in, *out, st_gid);
23387332c129SKonstantin Belousov 	CP(*in, *out, st_rdev);
2339372639f9SBruce Evans 	out->st_size = MIN(in->st_size, INT32_MAX);
23407332c129SKonstantin Belousov 	TS_CP(*in, *out, st_atim);
23417332c129SKonstantin Belousov 	TS_CP(*in, *out, st_mtim);
23427332c129SKonstantin Belousov 	TS_CP(*in, *out, st_ctim);
23437332c129SKonstantin Belousov 	CP(*in, *out, st_blksize);
23447332c129SKonstantin Belousov 	CP(*in, *out, st_blocks);
23457332c129SKonstantin Belousov 	CP(*in, *out, st_flags);
23467332c129SKonstantin Belousov 	CP(*in, *out, st_gen);
23477332c129SKonstantin Belousov }
23487332c129SKonstantin Belousov #endif
23497332c129SKonstantin Belousov 
23507332c129SKonstantin Belousov #ifdef COMPAT_43
23517332c129SKonstantin Belousov int
ofreebsd32_stat(struct thread * td,struct ofreebsd32_stat_args * uap)23527332c129SKonstantin Belousov ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)
23537332c129SKonstantin Belousov {
23547332c129SKonstantin Belousov 	struct stat sb;
23557332c129SKonstantin Belousov 	struct ostat32 sb32;
23567332c129SKonstantin Belousov 	int error;
23577332c129SKonstantin Belousov 
2358cb858340SDmitry Chagin 	error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);
23597332c129SKonstantin Belousov 	if (error)
23607332c129SKonstantin Belousov 		return (error);
23617332c129SKonstantin Belousov 	copy_ostat(&sb, &sb32);
23627332c129SKonstantin Belousov 	error = copyout(&sb32, uap->ub, sizeof (sb32));
23637332c129SKonstantin Belousov 	return (error);
23647332c129SKonstantin Belousov }
23657332c129SKonstantin Belousov #endif
23667332c129SKonstantin Belousov 
23673ebc1248SPeter Wemm int
freebsd32_fstat(struct thread * td,struct freebsd32_fstat_args * uap)23681c7abef7SPeter Wemm freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
23693ebc1248SPeter Wemm {
237034eda634SPeter Wemm 	struct stat ub;
237134eda634SPeter Wemm 	struct stat32 ub32;
23723ebc1248SPeter Wemm 	int error;
23733ebc1248SPeter Wemm 
237438765a31SJohn Baldwin 	error = kern_fstat(td, uap->fd, &ub);
23753ebc1248SPeter Wemm 	if (error)
23763ebc1248SPeter Wemm 		return (error);
237734eda634SPeter Wemm 	copy_stat(&ub, &ub32);
2378f1a14110SBrooks Davis 	error = copyout(&ub32, uap->sb, sizeof(ub32));
23793ebc1248SPeter Wemm 	return (error);
23803ebc1248SPeter Wemm }
23813ebc1248SPeter Wemm 
23827332c129SKonstantin Belousov #ifdef COMPAT_43
23837332c129SKonstantin Belousov int
ofreebsd32_fstat(struct thread * td,struct ofreebsd32_fstat_args * uap)23847332c129SKonstantin Belousov ofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap)
23857332c129SKonstantin Belousov {
23867332c129SKonstantin Belousov 	struct stat ub;
23877332c129SKonstantin Belousov 	struct ostat32 ub32;
23887332c129SKonstantin Belousov 	int error;
23897332c129SKonstantin Belousov 
23907332c129SKonstantin Belousov 	error = kern_fstat(td, uap->fd, &ub);
23917332c129SKonstantin Belousov 	if (error)
23927332c129SKonstantin Belousov 		return (error);
23937332c129SKonstantin Belousov 	copy_ostat(&ub, &ub32);
2394ab3ccb75SBrooks Davis 	error = copyout(&ub32, uap->sb, sizeof(ub32));
23957332c129SKonstantin Belousov 	return (error);
23967332c129SKonstantin Belousov }
23977332c129SKonstantin Belousov #endif
23987332c129SKonstantin Belousov 
23993ebc1248SPeter Wemm int
freebsd32_fstatat(struct thread * td,struct freebsd32_fstatat_args * uap)24004f1e7213SKonstantin Belousov freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
24014f1e7213SKonstantin Belousov {
24024f1e7213SKonstantin Belousov 	struct stat ub;
24034f1e7213SKonstantin Belousov 	struct stat32 ub32;
24044f1e7213SKonstantin Belousov 	int error;
24054f1e7213SKonstantin Belousov 
24066e646651SKonstantin Belousov 	error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE,
2407cb858340SDmitry Chagin 	    &ub);
24084f1e7213SKonstantin Belousov 	if (error)
24094f1e7213SKonstantin Belousov 		return (error);
24104f1e7213SKonstantin Belousov 	copy_stat(&ub, &ub32);
24114f1e7213SKonstantin Belousov 	error = copyout(&ub32, uap->buf, sizeof(ub32));
24124f1e7213SKonstantin Belousov 	return (error);
24134f1e7213SKonstantin Belousov }
24144f1e7213SKonstantin Belousov 
24157332c129SKonstantin Belousov #ifdef COMPAT_43
24167332c129SKonstantin Belousov int
ofreebsd32_lstat(struct thread * td,struct ofreebsd32_lstat_args * uap)24177332c129SKonstantin Belousov ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)
24187332c129SKonstantin Belousov {
24197332c129SKonstantin Belousov 	struct stat sb;
24207332c129SKonstantin Belousov 	struct ostat32 sb32;
24217332c129SKonstantin Belousov 	int error;
24227332c129SKonstantin Belousov 
24236e646651SKonstantin Belousov 	error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
2424cb858340SDmitry Chagin 	    UIO_USERSPACE, &sb);
24257332c129SKonstantin Belousov 	if (error)
24267332c129SKonstantin Belousov 		return (error);
24277332c129SKonstantin Belousov 	copy_ostat(&sb, &sb32);
24287332c129SKonstantin Belousov 	error = copyout(&sb32, uap->ub, sizeof (sb32));
24297332c129SKonstantin Belousov 	return (error);
24307332c129SKonstantin Belousov }
24317332c129SKonstantin Belousov #endif
24327332c129SKonstantin Belousov 
24333ebc1248SPeter Wemm int
freebsd32_fhstat(struct thread * td,struct freebsd32_fhstat_args * uap)243469921123SKonstantin Belousov freebsd32_fhstat(struct thread *td, struct freebsd32_fhstat_args *uap)
243569921123SKonstantin Belousov {
243669921123SKonstantin Belousov 	struct stat sb;
243769921123SKonstantin Belousov 	struct stat32 sb32;
243869921123SKonstantin Belousov 	struct fhandle fh;
243969921123SKonstantin Belousov 	int error;
244069921123SKonstantin Belousov 
244169921123SKonstantin Belousov 	error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
244269921123SKonstantin Belousov         if (error != 0)
244369921123SKonstantin Belousov                 return (error);
244469921123SKonstantin Belousov 	error = kern_fhstat(td, fh, &sb);
244569921123SKonstantin Belousov 	if (error != 0)
244669921123SKonstantin Belousov 		return (error);
244769921123SKonstantin Belousov 	copy_stat(&sb, &sb32);
244869921123SKonstantin Belousov 	error = copyout(&sb32, uap->sb, sizeof (sb32));
244969921123SKonstantin Belousov 	return (error);
245069921123SKonstantin Belousov }
245169921123SKonstantin Belousov 
245269921123SKonstantin Belousov #if defined(COMPAT_FREEBSD11)
24533df7ebc4SKonstantin Belousov extern int ino64_trunc_error;
24543df7ebc4SKonstantin Belousov 
24553df7ebc4SKonstantin Belousov static int
freebsd11_cvtstat32(struct stat * in,struct freebsd11_stat32 * out)245669921123SKonstantin Belousov freebsd11_cvtstat32(struct stat *in, struct freebsd11_stat32 *out)
245769921123SKonstantin Belousov {
245869921123SKonstantin Belousov 
2459f90cd1aeSEd Maste #ifndef __amd64__
2460f90cd1aeSEd Maste 	/*
2461f90cd1aeSEd Maste 	 * 32-bit architectures other than i386 have 64-bit time_t.  This
2462f90cd1aeSEd Maste 	 * results in struct timespec32 with 12 bytes for tv_sec and tv_nsec,
2463f90cd1aeSEd Maste 	 * and 4 bytes of padding.  Zero the padding holes in freebsd11_stat32.
2464f90cd1aeSEd Maste 	 */
2465f90cd1aeSEd Maste 	bzero(&out->st_atim, sizeof(out->st_atim));
2466f90cd1aeSEd Maste 	bzero(&out->st_mtim, sizeof(out->st_mtim));
2467f90cd1aeSEd Maste 	bzero(&out->st_ctim, sizeof(out->st_ctim));
2468f90cd1aeSEd Maste 	bzero(&out->st_birthtim, sizeof(out->st_birthtim));
2469f90cd1aeSEd Maste #endif
2470f90cd1aeSEd Maste 
247169921123SKonstantin Belousov 	CP(*in, *out, st_ino);
24727abe0df2SKonstantin Belousov 	if (in->st_ino != out->st_ino) {
24737abe0df2SKonstantin Belousov 		switch (ino64_trunc_error) {
24747abe0df2SKonstantin Belousov 		default:
24757abe0df2SKonstantin Belousov 		case 0:
24767abe0df2SKonstantin Belousov 			break;
24777abe0df2SKonstantin Belousov 		case 1:
24783df7ebc4SKonstantin Belousov 			return (EOVERFLOW);
24797abe0df2SKonstantin Belousov 		case 2:
24807abe0df2SKonstantin Belousov 			out->st_ino = UINT32_MAX;
24817abe0df2SKonstantin Belousov 			break;
24827abe0df2SKonstantin Belousov 		}
24837abe0df2SKonstantin Belousov 	}
248469921123SKonstantin Belousov 	CP(*in, *out, st_nlink);
24857abe0df2SKonstantin Belousov 	if (in->st_nlink != out->st_nlink) {
24867abe0df2SKonstantin Belousov 		switch (ino64_trunc_error) {
24877abe0df2SKonstantin Belousov 		default:
24887abe0df2SKonstantin Belousov 		case 0:
24897abe0df2SKonstantin Belousov 			break;
24907abe0df2SKonstantin Belousov 		case 1:
24913df7ebc4SKonstantin Belousov 			return (EOVERFLOW);
24927abe0df2SKonstantin Belousov 		case 2:
24937abe0df2SKonstantin Belousov 			out->st_nlink = UINT16_MAX;
24947abe0df2SKonstantin Belousov 			break;
24957abe0df2SKonstantin Belousov 		}
24967abe0df2SKonstantin Belousov 	}
2497ab35e1c7SBruce Evans 	out->st_dev = in->st_dev;
2498ab35e1c7SBruce Evans 	if (out->st_dev != in->st_dev) {
2499ab35e1c7SBruce Evans 		switch (ino64_trunc_error) {
2500ab35e1c7SBruce Evans 		default:
2501ab35e1c7SBruce Evans 			break;
2502ab35e1c7SBruce Evans 		case 1:
2503ab35e1c7SBruce Evans 			return (EOVERFLOW);
2504ab35e1c7SBruce Evans 		}
2505ab35e1c7SBruce Evans 	}
250669921123SKonstantin Belousov 	CP(*in, *out, st_mode);
250769921123SKonstantin Belousov 	CP(*in, *out, st_uid);
250869921123SKonstantin Belousov 	CP(*in, *out, st_gid);
2509ab35e1c7SBruce Evans 	out->st_rdev = in->st_rdev;
2510ab35e1c7SBruce Evans 	if (out->st_rdev != in->st_rdev) {
2511ab35e1c7SBruce Evans 		switch (ino64_trunc_error) {
2512ab35e1c7SBruce Evans 		default:
2513ab35e1c7SBruce Evans 			break;
2514ab35e1c7SBruce Evans 		case 1:
2515ab35e1c7SBruce Evans 			return (EOVERFLOW);
2516ab35e1c7SBruce Evans 		}
2517ab35e1c7SBruce Evans 	}
251869921123SKonstantin Belousov 	TS_CP(*in, *out, st_atim);
251969921123SKonstantin Belousov 	TS_CP(*in, *out, st_mtim);
252069921123SKonstantin Belousov 	TS_CP(*in, *out, st_ctim);
252169921123SKonstantin Belousov 	CP(*in, *out, st_size);
252269921123SKonstantin Belousov 	CP(*in, *out, st_blocks);
252369921123SKonstantin Belousov 	CP(*in, *out, st_blksize);
252469921123SKonstantin Belousov 	CP(*in, *out, st_flags);
252569921123SKonstantin Belousov 	CP(*in, *out, st_gen);
252669921123SKonstantin Belousov 	TS_CP(*in, *out, st_birthtim);
252769921123SKonstantin Belousov 	out->st_lspare = 0;
252869921123SKonstantin Belousov 	bzero((char *)&out->st_birthtim + sizeof(out->st_birthtim),
252969921123SKonstantin Belousov 	    sizeof(*out) - offsetof(struct freebsd11_stat32,
253069921123SKonstantin Belousov 	    st_birthtim) - sizeof(out->st_birthtim));
25313df7ebc4SKonstantin Belousov 	return (0);
253269921123SKonstantin Belousov }
253369921123SKonstantin Belousov 
253469921123SKonstantin Belousov int
freebsd11_freebsd32_stat(struct thread * td,struct freebsd11_freebsd32_stat_args * uap)253569921123SKonstantin Belousov freebsd11_freebsd32_stat(struct thread *td,
253669921123SKonstantin Belousov     struct freebsd11_freebsd32_stat_args *uap)
253769921123SKonstantin Belousov {
253869921123SKonstantin Belousov 	struct stat sb;
253969921123SKonstantin Belousov 	struct freebsd11_stat32 sb32;
254069921123SKonstantin Belousov 	int error;
254169921123SKonstantin Belousov 
2542cb858340SDmitry Chagin 	error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);
254369921123SKonstantin Belousov 	if (error != 0)
254469921123SKonstantin Belousov 		return (error);
25453df7ebc4SKonstantin Belousov 	error = freebsd11_cvtstat32(&sb, &sb32);
25463df7ebc4SKonstantin Belousov 	if (error == 0)
254769921123SKonstantin Belousov 		error = copyout(&sb32, uap->ub, sizeof (sb32));
254869921123SKonstantin Belousov 	return (error);
254969921123SKonstantin Belousov }
255069921123SKonstantin Belousov 
255169921123SKonstantin Belousov int
freebsd11_freebsd32_fstat(struct thread * td,struct freebsd11_freebsd32_fstat_args * uap)255269921123SKonstantin Belousov freebsd11_freebsd32_fstat(struct thread *td,
255369921123SKonstantin Belousov     struct freebsd11_freebsd32_fstat_args *uap)
255469921123SKonstantin Belousov {
255569921123SKonstantin Belousov 	struct stat sb;
255669921123SKonstantin Belousov 	struct freebsd11_stat32 sb32;
255769921123SKonstantin Belousov 	int error;
255869921123SKonstantin Belousov 
255969921123SKonstantin Belousov 	error = kern_fstat(td, uap->fd, &sb);
256069921123SKonstantin Belousov 	if (error != 0)
256169921123SKonstantin Belousov 		return (error);
25623df7ebc4SKonstantin Belousov 	error = freebsd11_cvtstat32(&sb, &sb32);
25633df7ebc4SKonstantin Belousov 	if (error == 0)
2564ab3ccb75SBrooks Davis 		error = copyout(&sb32, uap->sb, sizeof (sb32));
256569921123SKonstantin Belousov 	return (error);
256669921123SKonstantin Belousov }
256769921123SKonstantin Belousov 
256869921123SKonstantin Belousov int
freebsd11_freebsd32_fstatat(struct thread * td,struct freebsd11_freebsd32_fstatat_args * uap)256969921123SKonstantin Belousov freebsd11_freebsd32_fstatat(struct thread *td,
257069921123SKonstantin Belousov     struct freebsd11_freebsd32_fstatat_args *uap)
257169921123SKonstantin Belousov {
257269921123SKonstantin Belousov 	struct stat sb;
257369921123SKonstantin Belousov 	struct freebsd11_stat32 sb32;
257469921123SKonstantin Belousov 	int error;
257569921123SKonstantin Belousov 
257669921123SKonstantin Belousov 	error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE,
2577cb858340SDmitry Chagin 	    &sb);
257869921123SKonstantin Belousov 	if (error != 0)
257969921123SKonstantin Belousov 		return (error);
25803df7ebc4SKonstantin Belousov 	error = freebsd11_cvtstat32(&sb, &sb32);
25813df7ebc4SKonstantin Belousov 	if (error == 0)
258269921123SKonstantin Belousov 		error = copyout(&sb32, uap->buf, sizeof (sb32));
258369921123SKonstantin Belousov 	return (error);
258469921123SKonstantin Belousov }
258569921123SKonstantin Belousov 
258669921123SKonstantin Belousov int
freebsd11_freebsd32_lstat(struct thread * td,struct freebsd11_freebsd32_lstat_args * uap)258769921123SKonstantin Belousov freebsd11_freebsd32_lstat(struct thread *td,
258869921123SKonstantin Belousov     struct freebsd11_freebsd32_lstat_args *uap)
258969921123SKonstantin Belousov {
259069921123SKonstantin Belousov 	struct stat sb;
259169921123SKonstantin Belousov 	struct freebsd11_stat32 sb32;
259269921123SKonstantin Belousov 	int error;
259369921123SKonstantin Belousov 
259469921123SKonstantin Belousov 	error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
2595cb858340SDmitry Chagin 	    UIO_USERSPACE, &sb);
25963df7ebc4SKonstantin Belousov 	if (error != 0)
259769921123SKonstantin Belousov 		return (error);
25983df7ebc4SKonstantin Belousov 	error = freebsd11_cvtstat32(&sb, &sb32);
25993df7ebc4SKonstantin Belousov 	if (error == 0)
260069921123SKonstantin Belousov 		error = copyout(&sb32, uap->ub, sizeof (sb32));
260169921123SKonstantin Belousov 	return (error);
260269921123SKonstantin Belousov }
260369921123SKonstantin Belousov 
260469921123SKonstantin Belousov int
freebsd11_freebsd32_fhstat(struct thread * td,struct freebsd11_freebsd32_fhstat_args * uap)260569921123SKonstantin Belousov freebsd11_freebsd32_fhstat(struct thread *td,
260669921123SKonstantin Belousov     struct freebsd11_freebsd32_fhstat_args *uap)
260769921123SKonstantin Belousov {
260869921123SKonstantin Belousov 	struct stat sb;
260969921123SKonstantin Belousov 	struct freebsd11_stat32 sb32;
261069921123SKonstantin Belousov 	struct fhandle fh;
261169921123SKonstantin Belousov 	int error;
261269921123SKonstantin Belousov 
261369921123SKonstantin Belousov 	error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
261469921123SKonstantin Belousov         if (error != 0)
261569921123SKonstantin Belousov                 return (error);
261669921123SKonstantin Belousov 	error = kern_fhstat(td, fh, &sb);
261769921123SKonstantin Belousov 	if (error != 0)
261869921123SKonstantin Belousov 		return (error);
26193df7ebc4SKonstantin Belousov 	error = freebsd11_cvtstat32(&sb, &sb32);
26203df7ebc4SKonstantin Belousov 	if (error == 0)
262169921123SKonstantin Belousov 		error = copyout(&sb32, uap->sb, sizeof (sb32));
262269921123SKonstantin Belousov 	return (error);
262369921123SKonstantin Belousov }
26246eefabd4SBrooks Davis 
26256eefabd4SBrooks Davis static int
freebsd11_cvtnstat32(struct stat * sb,struct nstat32 * nsb32)26266eefabd4SBrooks Davis freebsd11_cvtnstat32(struct stat *sb, struct nstat32 *nsb32)
26276eefabd4SBrooks Davis {
26286eefabd4SBrooks Davis 	struct nstat nsb;
26296eefabd4SBrooks Davis 	int error;
26306eefabd4SBrooks Davis 
26316eefabd4SBrooks Davis 	error = freebsd11_cvtnstat(sb, &nsb);
26326eefabd4SBrooks Davis 	if (error != 0)
26336eefabd4SBrooks Davis 		return (error);
26346eefabd4SBrooks Davis 
26356eefabd4SBrooks Davis 	bzero(nsb32, sizeof(*nsb32));
26366eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_dev);
26376eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_ino);
26386eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_mode);
26396eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_nlink);
26406eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_uid);
26416eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_gid);
26426eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_rdev);
26436eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_atim.tv_sec);
26446eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_atim.tv_nsec);
26456eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_mtim.tv_sec);
26466eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_mtim.tv_nsec);
26476eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_ctim.tv_sec);
26486eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_ctim.tv_nsec);
26496eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_size);
26506eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_blocks);
26516eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_blksize);
26526eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_flags);
26536eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_gen);
26546eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_birthtim.tv_sec);
26556eefabd4SBrooks Davis 	CP(nsb, *nsb32, st_birthtim.tv_nsec);
26566eefabd4SBrooks Davis 	return (0);
26576eefabd4SBrooks Davis }
26586eefabd4SBrooks Davis 
26596eefabd4SBrooks Davis int
freebsd11_freebsd32_nstat(struct thread * td,struct freebsd11_freebsd32_nstat_args * uap)26606eefabd4SBrooks Davis freebsd11_freebsd32_nstat(struct thread *td,
26616eefabd4SBrooks Davis     struct freebsd11_freebsd32_nstat_args *uap)
26626eefabd4SBrooks Davis {
26636eefabd4SBrooks Davis 	struct stat sb;
26646eefabd4SBrooks Davis 	struct nstat32 nsb;
26656eefabd4SBrooks Davis 	int error;
26666eefabd4SBrooks Davis 
2667cb858340SDmitry Chagin 	error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE, &sb);
26686eefabd4SBrooks Davis 	if (error != 0)
26696eefabd4SBrooks Davis 		return (error);
26706eefabd4SBrooks Davis 	error = freebsd11_cvtnstat32(&sb, &nsb);
26716eefabd4SBrooks Davis 	if (error != 0)
26726eefabd4SBrooks Davis 		error = copyout(&nsb, uap->ub, sizeof (nsb));
26736eefabd4SBrooks Davis 	return (error);
26746eefabd4SBrooks Davis }
26756eefabd4SBrooks Davis 
26766eefabd4SBrooks Davis int
freebsd11_freebsd32_nlstat(struct thread * td,struct freebsd11_freebsd32_nlstat_args * uap)26776eefabd4SBrooks Davis freebsd11_freebsd32_nlstat(struct thread *td,
26786eefabd4SBrooks Davis     struct freebsd11_freebsd32_nlstat_args *uap)
26796eefabd4SBrooks Davis {
26806eefabd4SBrooks Davis 	struct stat sb;
26816eefabd4SBrooks Davis 	struct nstat32 nsb;
26826eefabd4SBrooks Davis 	int error;
26836eefabd4SBrooks Davis 
26846eefabd4SBrooks Davis 	error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
2685cb858340SDmitry Chagin 	    UIO_USERSPACE, &sb);
26866eefabd4SBrooks Davis 	if (error != 0)
26876eefabd4SBrooks Davis 		return (error);
26886eefabd4SBrooks Davis 	error = freebsd11_cvtnstat32(&sb, &nsb);
26896eefabd4SBrooks Davis 	if (error == 0)
26906eefabd4SBrooks Davis 		error = copyout(&nsb, uap->ub, sizeof (nsb));
26916eefabd4SBrooks Davis 	return (error);
26926eefabd4SBrooks Davis }
26936eefabd4SBrooks Davis 
26946eefabd4SBrooks Davis int
freebsd11_freebsd32_nfstat(struct thread * td,struct freebsd11_freebsd32_nfstat_args * uap)26956eefabd4SBrooks Davis freebsd11_freebsd32_nfstat(struct thread *td,
26966eefabd4SBrooks Davis     struct freebsd11_freebsd32_nfstat_args *uap)
26976eefabd4SBrooks Davis {
26986eefabd4SBrooks Davis 	struct nstat32 nub;
26996eefabd4SBrooks Davis 	struct stat ub;
27006eefabd4SBrooks Davis 	int error;
27016eefabd4SBrooks Davis 
27026eefabd4SBrooks Davis 	error = kern_fstat(td, uap->fd, &ub);
27036eefabd4SBrooks Davis 	if (error != 0)
27046eefabd4SBrooks Davis 		return (error);
27056eefabd4SBrooks Davis 	error = freebsd11_cvtnstat32(&ub, &nub);
27066eefabd4SBrooks Davis 	if (error == 0)
27076eefabd4SBrooks Davis 		error = copyout(&nub, uap->sb, sizeof(nub));
27086eefabd4SBrooks Davis 	return (error);
27096eefabd4SBrooks Davis }
271069921123SKonstantin Belousov #endif
271169921123SKonstantin Belousov 
271269921123SKonstantin Belousov int
freebsd32___sysctl(struct thread * td,struct freebsd32___sysctl_args * uap)271340747517SBrooks Davis freebsd32___sysctl(struct thread *td, struct freebsd32___sysctl_args *uap)
27143ebc1248SPeter Wemm {
27153ebc1248SPeter Wemm 	int error, name[CTL_MAXNAME];
27163ebc1248SPeter Wemm 	size_t j, oldlen;
27170a2c94b8SKonstantin Belousov 	uint32_t tmp;
27183ebc1248SPeter Wemm 
27193ebc1248SPeter Wemm 	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
27203ebc1248SPeter Wemm 		return (EINVAL);
2721a7bc3102SPeter Wemm  	error = copyin(uap->name, name, uap->namelen * sizeof(int));
27223ebc1248SPeter Wemm  	if (error)
27233ebc1248SPeter Wemm 		return (error);
27240a2c94b8SKonstantin Belousov 	if (uap->oldlenp) {
27250a2c94b8SKonstantin Belousov 		error = fueword32(uap->oldlenp, &tmp);
27260a2c94b8SKonstantin Belousov 		oldlen = tmp;
27270a2c94b8SKonstantin Belousov 	} else {
27283ebc1248SPeter Wemm 		oldlen = 0;
27290a2c94b8SKonstantin Belousov 	}
27300a2c94b8SKonstantin Belousov 	if (error != 0)
27310a2c94b8SKonstantin Belousov 		return (EFAULT);
27323ebc1248SPeter Wemm 	error = userland_sysctl(td, name, uap->namelen,
27333ebc1248SPeter Wemm 		uap->old, &oldlen, 1,
2734a7bc3102SPeter Wemm 		uap->new, uap->newlen, &j, SCTL_MASK32);
2735e15f0023SBrooks Davis 	if (error)
2736ddf9d243SEd Schouten 		return (error);
273781eb7baaSMark Johnston 	if (uap->oldlenp != NULL && suword32(uap->oldlenp, j) != 0)
273881eb7baaSMark Johnston 		error = EFAULT;
273981eb7baaSMark Johnston 	return (error);
27403ebc1248SPeter Wemm }
27413ebc1248SPeter Wemm 
27423ebc1248SPeter Wemm int
freebsd32___sysctlbyname(struct thread * td,struct freebsd32___sysctlbyname_args * uap)2743d05b53e0SMateusz Guzik freebsd32___sysctlbyname(struct thread *td,
2744d05b53e0SMateusz Guzik     struct freebsd32___sysctlbyname_args *uap)
2745d05b53e0SMateusz Guzik {
2746d05b53e0SMateusz Guzik 	size_t oldlen, rv;
2747d05b53e0SMateusz Guzik 	int error;
2748d05b53e0SMateusz Guzik 	uint32_t tmp;
2749d05b53e0SMateusz Guzik 
2750d05b53e0SMateusz Guzik 	if (uap->oldlenp != NULL) {
2751d05b53e0SMateusz Guzik 		error = fueword32(uap->oldlenp, &tmp);
2752d05b53e0SMateusz Guzik 		oldlen = tmp;
2753d05b53e0SMateusz Guzik 	} else {
2754d05b53e0SMateusz Guzik 		error = oldlen = 0;
2755d05b53e0SMateusz Guzik 	}
2756d05b53e0SMateusz Guzik 	if (error != 0)
2757d05b53e0SMateusz Guzik 		return (EFAULT);
2758d05b53e0SMateusz Guzik 	error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,
2759d05b53e0SMateusz Guzik 	    &oldlen, uap->new, uap->newlen, &rv, SCTL_MASK32, 1);
2760d05b53e0SMateusz Guzik 	if (error != 0)
2761d05b53e0SMateusz Guzik 		return (error);
2762bd1654ceSMark Johnston 	if (uap->oldlenp != NULL && suword32(uap->oldlenp, rv) != 0)
2763bd1654ceSMark Johnston 		error = EFAULT;
2764d05b53e0SMateusz Guzik 	return (error);
2765d05b53e0SMateusz Guzik }
2766d05b53e0SMateusz Guzik 
2767d05b53e0SMateusz Guzik int
freebsd32_jail(struct thread * td,struct freebsd32_jail_args * uap)2768c542c43eSJamie Gritton freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
2769413628a7SBjoern A. Zeeb {
2770413628a7SBjoern A. Zeeb 	uint32_t version;
2771413628a7SBjoern A. Zeeb 	int error;
27720304c731SJamie Gritton 	struct jail j;
2773413628a7SBjoern A. Zeeb 
2774413628a7SBjoern A. Zeeb 	error = copyin(uap->jail, &version, sizeof(uint32_t));
2775413628a7SBjoern A. Zeeb 	if (error)
2776413628a7SBjoern A. Zeeb 		return (error);
27778571af59SJamie Gritton 
2778413628a7SBjoern A. Zeeb 	switch (version) {
2779413628a7SBjoern A. Zeeb 	case 0:
2780413628a7SBjoern A. Zeeb 	{
2781413628a7SBjoern A. Zeeb 		/* FreeBSD single IPv4 jails. */
2782413628a7SBjoern A. Zeeb 		struct jail32_v0 j32_v0;
2783413628a7SBjoern A. Zeeb 
27840304c731SJamie Gritton 		bzero(&j, sizeof(struct jail));
2785413628a7SBjoern A. Zeeb 		error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
2786413628a7SBjoern A. Zeeb 		if (error)
2787413628a7SBjoern A. Zeeb 			return (error);
27880304c731SJamie Gritton 		CP(j32_v0, j, version);
27890304c731SJamie Gritton 		PTRIN_CP(j32_v0, j, path);
27900304c731SJamie Gritton 		PTRIN_CP(j32_v0, j, hostname);
2791b5019bc4SPeter Wemm 		j.ip4s = htonl(j32_v0.ip_number);	/* jail_v0 is host order */
2792413628a7SBjoern A. Zeeb 		break;
2793413628a7SBjoern A. Zeeb 	}
2794413628a7SBjoern A. Zeeb 
2795413628a7SBjoern A. Zeeb 	case 1:
2796413628a7SBjoern A. Zeeb 		/*
2797413628a7SBjoern A. Zeeb 		 * Version 1 was used by multi-IPv4 jail implementations
2798413628a7SBjoern A. Zeeb 		 * that never made it into the official kernel.
2799413628a7SBjoern A. Zeeb 		 */
2800413628a7SBjoern A. Zeeb 		return (EINVAL);
2801413628a7SBjoern A. Zeeb 
2802413628a7SBjoern A. Zeeb 	case 2:	/* JAIL_API_VERSION */
2803413628a7SBjoern A. Zeeb 	{
2804413628a7SBjoern A. Zeeb 		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
2805413628a7SBjoern A. Zeeb 		struct jail32 j32;
2806413628a7SBjoern A. Zeeb 
2807413628a7SBjoern A. Zeeb 		error = copyin(uap->jail, &j32, sizeof(struct jail32));
2808413628a7SBjoern A. Zeeb 		if (error)
2809413628a7SBjoern A. Zeeb 			return (error);
28100304c731SJamie Gritton 		CP(j32, j, version);
28110304c731SJamie Gritton 		PTRIN_CP(j32, j, path);
28120304c731SJamie Gritton 		PTRIN_CP(j32, j, hostname);
28130304c731SJamie Gritton 		PTRIN_CP(j32, j, jailname);
28140304c731SJamie Gritton 		CP(j32, j, ip4s);
28150304c731SJamie Gritton 		CP(j32, j, ip6s);
28160304c731SJamie Gritton 		PTRIN_CP(j32, j, ip4);
28170304c731SJamie Gritton 		PTRIN_CP(j32, j, ip6);
2818413628a7SBjoern A. Zeeb 		break;
2819413628a7SBjoern A. Zeeb 	}
2820413628a7SBjoern A. Zeeb 
2821413628a7SBjoern A. Zeeb 	default:
2822413628a7SBjoern A. Zeeb 		/* Sci-Fi jails are not supported, sorry. */
2823413628a7SBjoern A. Zeeb 		return (EINVAL);
2824413628a7SBjoern A. Zeeb 	}
2825c542c43eSJamie Gritton 	return (kern_jail(td, &j));
2826b38ff370SJamie Gritton }
2827b38ff370SJamie Gritton 
2828b38ff370SJamie Gritton int
freebsd32_jail_set(struct thread * td,struct freebsd32_jail_set_args * uap)2829b38ff370SJamie Gritton freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
2830b38ff370SJamie Gritton {
2831b38ff370SJamie Gritton 	struct uio *auio;
2832b38ff370SJamie Gritton 	int error;
2833b38ff370SJamie Gritton 
2834b38ff370SJamie Gritton 	/* Check that we have an even number of iovecs. */
2835b38ff370SJamie Gritton 	if (uap->iovcnt & 1)
2836b38ff370SJamie Gritton 		return (EINVAL);
2837b38ff370SJamie Gritton 
2838b38ff370SJamie Gritton 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2839b38ff370SJamie Gritton 	if (error)
2840b38ff370SJamie Gritton 		return (error);
2841b38ff370SJamie Gritton 	error = kern_jail_set(td, auio, uap->flags);
284261cc4830SAlfredo Mazzinghi 	freeuio(auio);
2843b38ff370SJamie Gritton 	return (error);
2844b38ff370SJamie Gritton }
2845b38ff370SJamie Gritton 
2846b38ff370SJamie Gritton int
freebsd32_jail_get(struct thread * td,struct freebsd32_jail_get_args * uap)2847b38ff370SJamie Gritton freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
2848b38ff370SJamie Gritton {
2849b38ff370SJamie Gritton 	struct iovec32 iov32;
2850b38ff370SJamie Gritton 	struct uio *auio;
2851b38ff370SJamie Gritton 	int error, i;
2852b38ff370SJamie Gritton 
2853b38ff370SJamie Gritton 	/* Check that we have an even number of iovecs. */
2854b38ff370SJamie Gritton 	if (uap->iovcnt & 1)
2855b38ff370SJamie Gritton 		return (EINVAL);
2856b38ff370SJamie Gritton 
2857b38ff370SJamie Gritton 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2858b38ff370SJamie Gritton 	if (error)
2859b38ff370SJamie Gritton 		return (error);
2860b38ff370SJamie Gritton 	error = kern_jail_get(td, auio, uap->flags);
2861b38ff370SJamie Gritton 	if (error == 0)
2862b38ff370SJamie Gritton 		for (i = 0; i < uap->iovcnt; i++) {
2863b38ff370SJamie Gritton 			PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
2864b38ff370SJamie Gritton 			CP(auio->uio_iov[i], iov32, iov_len);
2865b38ff370SJamie Gritton 			error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
2866b38ff370SJamie Gritton 			if (error != 0)
2867b38ff370SJamie Gritton 				break;
2868b38ff370SJamie Gritton 		}
286961cc4830SAlfredo Mazzinghi 	freeuio(auio);
2870b38ff370SJamie Gritton 	return (error);
2871413628a7SBjoern A. Zeeb }
2872413628a7SBjoern A. Zeeb 
2873413628a7SBjoern A. Zeeb int
freebsd32_sigaction(struct thread * td,struct freebsd32_sigaction_args * uap)28741c7abef7SPeter Wemm freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
28753ebc1248SPeter Wemm {
2876fe8cdcaeSJohn Baldwin 	struct sigaction32 s32;
2877fe8cdcaeSJohn Baldwin 	struct sigaction sa, osa, *sap;
28783ebc1248SPeter Wemm 	int error;
28793ebc1248SPeter Wemm 
2880fe8cdcaeSJohn Baldwin 	if (uap->act) {
2881fe8cdcaeSJohn Baldwin 		error = copyin(uap->act, &s32, sizeof(s32));
28823ebc1248SPeter Wemm 		if (error)
28833ebc1248SPeter Wemm 			return (error);
2884fe8cdcaeSJohn Baldwin 		sa.sa_handler = PTRIN(s32.sa_u);
2885fe8cdcaeSJohn Baldwin 		CP(s32, sa, sa_flags);
2886fe8cdcaeSJohn Baldwin 		CP(s32, sa, sa_mask);
2887fe8cdcaeSJohn Baldwin 		sap = &sa;
2888fe8cdcaeSJohn Baldwin 	} else
2889fe8cdcaeSJohn Baldwin 		sap = NULL;
2890fe8cdcaeSJohn Baldwin 	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
2891473dd55fSPaul Saab 	if (error == 0 && uap->oact != NULL) {
2892fe8cdcaeSJohn Baldwin 		s32.sa_u = PTROUT(osa.sa_handler);
2893fe8cdcaeSJohn Baldwin 		CP(osa, s32, sa_flags);
2894fe8cdcaeSJohn Baldwin 		CP(osa, s32, sa_mask);
2895fe8cdcaeSJohn Baldwin 		error = copyout(&s32, uap->oact, sizeof(s32));
28963ebc1248SPeter Wemm 	}
28973ebc1248SPeter Wemm 	return (error);
28983ebc1248SPeter Wemm }
28993ebc1248SPeter Wemm 
2900d85631c4SPeter Wemm #ifdef COMPAT_FREEBSD4
2901d85631c4SPeter Wemm int
freebsd4_freebsd32_sigaction(struct thread * td,struct freebsd4_freebsd32_sigaction_args * uap)29021c7abef7SPeter Wemm freebsd4_freebsd32_sigaction(struct thread *td,
29031c7abef7SPeter Wemm 			     struct freebsd4_freebsd32_sigaction_args *uap)
2904d85631c4SPeter Wemm {
2905d85631c4SPeter Wemm 	struct sigaction32 s32;
2906d85631c4SPeter Wemm 	struct sigaction sa, osa, *sap;
2907d85631c4SPeter Wemm 	int error;
2908d85631c4SPeter Wemm 
2909d85631c4SPeter Wemm 	if (uap->act) {
2910d85631c4SPeter Wemm 		error = copyin(uap->act, &s32, sizeof(s32));
2911d85631c4SPeter Wemm 		if (error)
2912d85631c4SPeter Wemm 			return (error);
2913d85631c4SPeter Wemm 		sa.sa_handler = PTRIN(s32.sa_u);
2914d85631c4SPeter Wemm 		CP(s32, sa, sa_flags);
2915d85631c4SPeter Wemm 		CP(s32, sa, sa_mask);
2916d85631c4SPeter Wemm 		sap = &sa;
2917d85631c4SPeter Wemm 	} else
2918d85631c4SPeter Wemm 		sap = NULL;
2919d85631c4SPeter Wemm 	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
2920473dd55fSPaul Saab 	if (error == 0 && uap->oact != NULL) {
2921d85631c4SPeter Wemm 		s32.sa_u = PTROUT(osa.sa_handler);
2922d85631c4SPeter Wemm 		CP(osa, s32, sa_flags);
2923d85631c4SPeter Wemm 		CP(osa, s32, sa_mask);
2924d85631c4SPeter Wemm 		error = copyout(&s32, uap->oact, sizeof(s32));
2925d85631c4SPeter Wemm 	}
2926d85631c4SPeter Wemm 	return (error);
2927d85631c4SPeter Wemm }
2928d85631c4SPeter Wemm #endif
2929d85631c4SPeter Wemm 
2930e7abd4a0SPaul Saab #ifdef COMPAT_43
2931767dfc44SPeter Wemm struct osigaction32 {
2932cc5aa0a4SJohn Baldwin 	uint32_t	sa_u;
2933e7abd4a0SPaul Saab 	osigset_t	sa_mask;
2934e7abd4a0SPaul Saab 	int		sa_flags;
2935e7abd4a0SPaul Saab };
2936e7abd4a0SPaul Saab 
2937e7abd4a0SPaul Saab #define	ONSIG	32
2938e7abd4a0SPaul Saab 
2939e7abd4a0SPaul Saab int
ofreebsd32_sigaction(struct thread * td,struct ofreebsd32_sigaction_args * uap)2940767dfc44SPeter Wemm ofreebsd32_sigaction(struct thread *td,
2941767dfc44SPeter Wemm 			     struct ofreebsd32_sigaction_args *uap)
2942e7abd4a0SPaul Saab {
2943767dfc44SPeter Wemm 	struct osigaction32 s32;
2944e7abd4a0SPaul Saab 	struct sigaction sa, osa, *sap;
2945e7abd4a0SPaul Saab 	int error;
2946e7abd4a0SPaul Saab 
2947e7abd4a0SPaul Saab 	if (uap->signum <= 0 || uap->signum >= ONSIG)
2948e7abd4a0SPaul Saab 		return (EINVAL);
2949e7abd4a0SPaul Saab 
2950e7abd4a0SPaul Saab 	if (uap->nsa) {
2951e7abd4a0SPaul Saab 		error = copyin(uap->nsa, &s32, sizeof(s32));
2952e7abd4a0SPaul Saab 		if (error)
2953e7abd4a0SPaul Saab 			return (error);
2954e7abd4a0SPaul Saab 		sa.sa_handler = PTRIN(s32.sa_u);
2955e7abd4a0SPaul Saab 		CP(s32, sa, sa_flags);
2956e7abd4a0SPaul Saab 		OSIG2SIG(s32.sa_mask, sa.sa_mask);
2957e7abd4a0SPaul Saab 		sap = &sa;
2958e7abd4a0SPaul Saab 	} else
2959e7abd4a0SPaul Saab 		sap = NULL;
2960e7abd4a0SPaul Saab 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2961e7abd4a0SPaul Saab 	if (error == 0 && uap->osa != NULL) {
2962e7abd4a0SPaul Saab 		s32.sa_u = PTROUT(osa.sa_handler);
2963e7abd4a0SPaul Saab 		CP(osa, s32, sa_flags);
2964e7abd4a0SPaul Saab 		SIG2OSIG(osa.sa_mask, s32.sa_mask);
2965e7abd4a0SPaul Saab 		error = copyout(&s32, uap->osa, sizeof(s32));
2966e7abd4a0SPaul Saab 	}
2967e7abd4a0SPaul Saab 	return (error);
2968e7abd4a0SPaul Saab }
2969e7abd4a0SPaul Saab 
2970e7abd4a0SPaul Saab struct sigvec32 {
2971cc5aa0a4SJohn Baldwin 	uint32_t	sv_handler;
2972e7abd4a0SPaul Saab 	int		sv_mask;
2973e7abd4a0SPaul Saab 	int		sv_flags;
2974e7abd4a0SPaul Saab };
2975e7abd4a0SPaul Saab 
2976e7abd4a0SPaul Saab int
ofreebsd32_sigvec(struct thread * td,struct ofreebsd32_sigvec_args * uap)2977767dfc44SPeter Wemm ofreebsd32_sigvec(struct thread *td,
2978767dfc44SPeter Wemm 			  struct ofreebsd32_sigvec_args *uap)
2979e7abd4a0SPaul Saab {
2980e7abd4a0SPaul Saab 	struct sigvec32 vec;
2981e7abd4a0SPaul Saab 	struct sigaction sa, osa, *sap;
2982e7abd4a0SPaul Saab 	int error;
2983e7abd4a0SPaul Saab 
2984e7abd4a0SPaul Saab 	if (uap->signum <= 0 || uap->signum >= ONSIG)
2985e7abd4a0SPaul Saab 		return (EINVAL);
2986e7abd4a0SPaul Saab 
2987e7abd4a0SPaul Saab 	if (uap->nsv) {
2988e7abd4a0SPaul Saab 		error = copyin(uap->nsv, &vec, sizeof(vec));
2989e7abd4a0SPaul Saab 		if (error)
2990e7abd4a0SPaul Saab 			return (error);
2991e7abd4a0SPaul Saab 		sa.sa_handler = PTRIN(vec.sv_handler);
2992e7abd4a0SPaul Saab 		OSIG2SIG(vec.sv_mask, sa.sa_mask);
2993e7abd4a0SPaul Saab 		sa.sa_flags = vec.sv_flags;
2994e7abd4a0SPaul Saab 		sa.sa_flags ^= SA_RESTART;
2995e7abd4a0SPaul Saab 		sap = &sa;
2996e7abd4a0SPaul Saab 	} else
2997e7abd4a0SPaul Saab 		sap = NULL;
2998e7abd4a0SPaul Saab 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2999e7abd4a0SPaul Saab 	if (error == 0 && uap->osv != NULL) {
3000e7abd4a0SPaul Saab 		vec.sv_handler = PTROUT(osa.sa_handler);
3001e7abd4a0SPaul Saab 		SIG2OSIG(osa.sa_mask, vec.sv_mask);
3002e7abd4a0SPaul Saab 		vec.sv_flags = osa.sa_flags;
3003e7abd4a0SPaul Saab 		vec.sv_flags &= ~SA_NOCLDWAIT;
3004e7abd4a0SPaul Saab 		vec.sv_flags ^= SA_RESTART;
3005e7abd4a0SPaul Saab 		error = copyout(&vec, uap->osv, sizeof(vec));
3006e7abd4a0SPaul Saab 	}
3007e7abd4a0SPaul Saab 	return (error);
3008e7abd4a0SPaul Saab }
3009e7abd4a0SPaul Saab 
3010e7abd4a0SPaul Saab struct sigstack32 {
3011cc5aa0a4SJohn Baldwin 	uint32_t	ss_sp;
3012e7abd4a0SPaul Saab 	int		ss_onstack;
3013e7abd4a0SPaul Saab };
3014e7abd4a0SPaul Saab 
3015e7abd4a0SPaul Saab int
ofreebsd32_sigstack(struct thread * td,struct ofreebsd32_sigstack_args * uap)3016767dfc44SPeter Wemm ofreebsd32_sigstack(struct thread *td,
3017767dfc44SPeter Wemm 			    struct ofreebsd32_sigstack_args *uap)
3018e7abd4a0SPaul Saab {
3019e7abd4a0SPaul Saab 	struct sigstack32 s32;
3020e7abd4a0SPaul Saab 	struct sigstack nss, oss;
3021739c673cSMatt Jacob 	int error = 0, unss;
3022e7abd4a0SPaul Saab 
3023e7abd4a0SPaul Saab 	if (uap->nss != NULL) {
3024e7abd4a0SPaul Saab 		error = copyin(uap->nss, &s32, sizeof(s32));
3025e7abd4a0SPaul Saab 		if (error)
3026e7abd4a0SPaul Saab 			return (error);
3027e7abd4a0SPaul Saab 		nss.ss_sp = PTRIN(s32.ss_sp);
3028e7abd4a0SPaul Saab 		CP(s32, nss, ss_onstack);
3029739c673cSMatt Jacob 		unss = 1;
3030739c673cSMatt Jacob 	} else {
3031739c673cSMatt Jacob 		unss = 0;
3032e7abd4a0SPaul Saab 	}
3033e7abd4a0SPaul Saab 	oss.ss_sp = td->td_sigstk.ss_sp;
3034e7abd4a0SPaul Saab 	oss.ss_onstack = sigonstack(cpu_getstack(td));
3035739c673cSMatt Jacob 	if (unss) {
3036e7abd4a0SPaul Saab 		td->td_sigstk.ss_sp = nss.ss_sp;
3037e7abd4a0SPaul Saab 		td->td_sigstk.ss_size = 0;
3038739c673cSMatt Jacob 		td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
3039e7abd4a0SPaul Saab 		td->td_pflags |= TDP_ALTSTACK;
3040e7abd4a0SPaul Saab 	}
3041e7abd4a0SPaul Saab 	if (uap->oss != NULL) {
3042e7abd4a0SPaul Saab 		s32.ss_sp = PTROUT(oss.ss_sp);
3043e7abd4a0SPaul Saab 		CP(oss, s32, ss_onstack);
3044e7abd4a0SPaul Saab 		error = copyout(&s32, uap->oss, sizeof(s32));
3045e7abd4a0SPaul Saab 	}
3046e7abd4a0SPaul Saab 	return (error);
3047e7abd4a0SPaul Saab }
3048e7abd4a0SPaul Saab #endif
3049e7abd4a0SPaul Saab 
30507fdf2c85SPaul Saab int
freebsd32_nanosleep(struct thread * td,struct freebsd32_nanosleep_args * uap)30517fdf2c85SPaul Saab freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
30527fdf2c85SPaul Saab {
30533f8455b0SEric van Gyzen 
30543f8455b0SEric van Gyzen 	return (freebsd32_user_clock_nanosleep(td, CLOCK_REALTIME,
30553f8455b0SEric van Gyzen 	    TIMER_RELTIME, uap->rqtp, uap->rmtp));
30563f8455b0SEric van Gyzen }
30573f8455b0SEric van Gyzen 
30583f8455b0SEric van Gyzen int
freebsd32_clock_nanosleep(struct thread * td,struct freebsd32_clock_nanosleep_args * uap)30593f8455b0SEric van Gyzen freebsd32_clock_nanosleep(struct thread *td,
30603f8455b0SEric van Gyzen     struct freebsd32_clock_nanosleep_args *uap)
30613f8455b0SEric van Gyzen {
30623f8455b0SEric van Gyzen 	int error;
30633f8455b0SEric van Gyzen 
30643f8455b0SEric van Gyzen 	error = freebsd32_user_clock_nanosleep(td, uap->clock_id, uap->flags,
30653f8455b0SEric van Gyzen 	    uap->rqtp, uap->rmtp);
30663f8455b0SEric van Gyzen 	return (kern_posix_error(td, error));
30673f8455b0SEric van Gyzen }
30683f8455b0SEric van Gyzen 
30693f8455b0SEric van Gyzen static int
freebsd32_user_clock_nanosleep(struct thread * td,clockid_t clock_id,int flags,const struct timespec32 * ua_rqtp,struct timespec32 * ua_rmtp)30703f8455b0SEric van Gyzen freebsd32_user_clock_nanosleep(struct thread *td, clockid_t clock_id,
30713f8455b0SEric van Gyzen     int flags, const struct timespec32 *ua_rqtp, struct timespec32 *ua_rmtp)
30723f8455b0SEric van Gyzen {
30737fdf2c85SPaul Saab 	struct timespec32 rmt32, rqt32;
30747fdf2c85SPaul Saab 	struct timespec rmt, rqt;
3075618a20d4SBrooks Davis 	int error, error2;
30767fdf2c85SPaul Saab 
30773f8455b0SEric van Gyzen 	error = copyin(ua_rqtp, &rqt32, sizeof(rqt32));
30787fdf2c85SPaul Saab 	if (error)
30797fdf2c85SPaul Saab 		return (error);
30807fdf2c85SPaul Saab 
30817fdf2c85SPaul Saab 	CP(rqt32, rqt, tv_sec);
30827fdf2c85SPaul Saab 	CP(rqt32, rqt, tv_nsec);
30837fdf2c85SPaul Saab 
30843f8455b0SEric van Gyzen 	error = kern_clock_nanosleep(td, clock_id, flags, &rqt, &rmt);
30853f8455b0SEric van Gyzen 	if (error == EINTR && ua_rmtp != NULL && (flags & TIMER_ABSTIME) == 0) {
30867fdf2c85SPaul Saab 		CP(rmt, rmt32, tv_sec);
30877fdf2c85SPaul Saab 		CP(rmt, rmt32, tv_nsec);
30887fdf2c85SPaul Saab 
30893f8455b0SEric van Gyzen 		error2 = copyout(&rmt32, ua_rmtp, sizeof(rmt32));
3090618a20d4SBrooks Davis 		if (error2 != 0)
30917fdf2c85SPaul Saab 			error = error2;
30927fdf2c85SPaul Saab 	}
30937fdf2c85SPaul Saab 	return (error);
30947fdf2c85SPaul Saab }
30957fdf2c85SPaul Saab 
3096f0b479cdSPaul Saab int
freebsd32_clock_gettime(struct thread * td,struct freebsd32_clock_gettime_args * uap)3097f0b479cdSPaul Saab freebsd32_clock_gettime(struct thread *td,
3098f0b479cdSPaul Saab 			struct freebsd32_clock_gettime_args *uap)
3099f0b479cdSPaul Saab {
3100f0b479cdSPaul Saab 	struct timespec	ats;
3101f0b479cdSPaul Saab 	struct timespec32 ats32;
3102f0b479cdSPaul Saab 	int error;
3103f0b479cdSPaul Saab 
3104f0b479cdSPaul Saab 	error = kern_clock_gettime(td, uap->clock_id, &ats);
3105f0b479cdSPaul Saab 	if (error == 0) {
3106f0b479cdSPaul Saab 		CP(ats, ats32, tv_sec);
3107f0b479cdSPaul Saab 		CP(ats, ats32, tv_nsec);
3108f0b479cdSPaul Saab 		error = copyout(&ats32, uap->tp, sizeof(ats32));
3109f0b479cdSPaul Saab 	}
3110f0b479cdSPaul Saab 	return (error);
3111f0b479cdSPaul Saab }
3112f0b479cdSPaul Saab 
3113f0b479cdSPaul Saab int
freebsd32_clock_settime(struct thread * td,struct freebsd32_clock_settime_args * uap)3114f0b479cdSPaul Saab freebsd32_clock_settime(struct thread *td,
3115f0b479cdSPaul Saab 			struct freebsd32_clock_settime_args *uap)
3116f0b479cdSPaul Saab {
3117f0b479cdSPaul Saab 	struct timespec	ats;
3118f0b479cdSPaul Saab 	struct timespec32 ats32;
3119f0b479cdSPaul Saab 	int error;
3120f0b479cdSPaul Saab 
3121f0b479cdSPaul Saab 	error = copyin(uap->tp, &ats32, sizeof(ats32));
3122f0b479cdSPaul Saab 	if (error)
3123f0b479cdSPaul Saab 		return (error);
3124f0b479cdSPaul Saab 	CP(ats32, ats, tv_sec);
3125f0b479cdSPaul Saab 	CP(ats32, ats, tv_nsec);
3126f0b479cdSPaul Saab 
3127f0b479cdSPaul Saab 	return (kern_clock_settime(td, uap->clock_id, &ats));
3128f0b479cdSPaul Saab }
3129f0b479cdSPaul Saab 
3130f0b479cdSPaul Saab int
freebsd32_clock_getres(struct thread * td,struct freebsd32_clock_getres_args * uap)3131f0b479cdSPaul Saab freebsd32_clock_getres(struct thread *td,
3132f0b479cdSPaul Saab 		       struct freebsd32_clock_getres_args *uap)
3133f0b479cdSPaul Saab {
3134f0b479cdSPaul Saab 	struct timespec	ts;
3135f0b479cdSPaul Saab 	struct timespec32 ts32;
3136f0b479cdSPaul Saab 	int error;
3137f0b479cdSPaul Saab 
3138f0b479cdSPaul Saab 	if (uap->tp == NULL)
3139f0b479cdSPaul Saab 		return (0);
3140f0b479cdSPaul Saab 	error = kern_clock_getres(td, uap->clock_id, &ts);
3141f0b479cdSPaul Saab 	if (error == 0) {
3142f0b479cdSPaul Saab 		CP(ts, ts32, tv_sec);
3143f0b479cdSPaul Saab 		CP(ts, ts32, tv_nsec);
3144f0b479cdSPaul Saab 		error = copyout(&ts32, uap->tp, sizeof(ts32));
3145f0b479cdSPaul Saab 	}
3146f0b479cdSPaul Saab 	return (error);
3147f0b479cdSPaul Saab }
3148f0b479cdSPaul Saab 
freebsd32_ktimer_create(struct thread * td,struct freebsd32_ktimer_create_args * uap)3149643ee871SKonstantin Belousov int freebsd32_ktimer_create(struct thread *td,
3150643ee871SKonstantin Belousov     struct freebsd32_ktimer_create_args *uap)
3151643ee871SKonstantin Belousov {
3152643ee871SKonstantin Belousov 	struct sigevent32 ev32;
3153643ee871SKonstantin Belousov 	struct sigevent ev, *evp;
3154643ee871SKonstantin Belousov 	int error, id;
3155643ee871SKonstantin Belousov 
3156643ee871SKonstantin Belousov 	if (uap->evp == NULL) {
3157643ee871SKonstantin Belousov 		evp = NULL;
3158643ee871SKonstantin Belousov 	} else {
3159643ee871SKonstantin Belousov 		evp = &ev;
3160643ee871SKonstantin Belousov 		error = copyin(uap->evp, &ev32, sizeof(ev32));
3161643ee871SKonstantin Belousov 		if (error != 0)
3162643ee871SKonstantin Belousov 			return (error);
3163643ee871SKonstantin Belousov 		error = convert_sigevent32(&ev32, &ev);
3164643ee871SKonstantin Belousov 		if (error != 0)
3165643ee871SKonstantin Belousov 			return (error);
3166643ee871SKonstantin Belousov 	}
3167643ee871SKonstantin Belousov 	error = kern_ktimer_create(td, uap->clock_id, evp, &id, -1);
3168643ee871SKonstantin Belousov 	if (error == 0) {
3169643ee871SKonstantin Belousov 		error = copyout(&id, uap->timerid, sizeof(int));
3170643ee871SKonstantin Belousov 		if (error != 0)
3171643ee871SKonstantin Belousov 			kern_ktimer_delete(td, id);
3172643ee871SKonstantin Belousov 	}
3173643ee871SKonstantin Belousov 	return (error);
3174643ee871SKonstantin Belousov }
3175643ee871SKonstantin Belousov 
3176643ee871SKonstantin Belousov int
freebsd32_ktimer_settime(struct thread * td,struct freebsd32_ktimer_settime_args * uap)3177643ee871SKonstantin Belousov freebsd32_ktimer_settime(struct thread *td,
3178643ee871SKonstantin Belousov     struct freebsd32_ktimer_settime_args *uap)
3179643ee871SKonstantin Belousov {
3180643ee871SKonstantin Belousov 	struct itimerspec32 val32, oval32;
3181643ee871SKonstantin Belousov 	struct itimerspec val, oval, *ovalp;
3182643ee871SKonstantin Belousov 	int error;
3183643ee871SKonstantin Belousov 
3184643ee871SKonstantin Belousov 	error = copyin(uap->value, &val32, sizeof(val32));
3185643ee871SKonstantin Belousov 	if (error != 0)
3186643ee871SKonstantin Belousov 		return (error);
3187643ee871SKonstantin Belousov 	ITS_CP(val32, val);
3188643ee871SKonstantin Belousov 	ovalp = uap->ovalue != NULL ? &oval : NULL;
3189643ee871SKonstantin Belousov 	error = kern_ktimer_settime(td, uap->timerid, uap->flags, &val, ovalp);
3190643ee871SKonstantin Belousov 	if (error == 0 && uap->ovalue != NULL) {
3191643ee871SKonstantin Belousov 		ITS_CP(oval, oval32);
3192643ee871SKonstantin Belousov 		error = copyout(&oval32, uap->ovalue, sizeof(oval32));
3193643ee871SKonstantin Belousov 	}
3194643ee871SKonstantin Belousov 	return (error);
3195643ee871SKonstantin Belousov }
3196643ee871SKonstantin Belousov 
3197643ee871SKonstantin Belousov int
freebsd32_ktimer_gettime(struct thread * td,struct freebsd32_ktimer_gettime_args * uap)3198643ee871SKonstantin Belousov freebsd32_ktimer_gettime(struct thread *td,
3199643ee871SKonstantin Belousov     struct freebsd32_ktimer_gettime_args *uap)
3200643ee871SKonstantin Belousov {
3201643ee871SKonstantin Belousov 	struct itimerspec32 val32;
3202643ee871SKonstantin Belousov 	struct itimerspec val;
3203643ee871SKonstantin Belousov 	int error;
3204643ee871SKonstantin Belousov 
3205643ee871SKonstantin Belousov 	error = kern_ktimer_gettime(td, uap->timerid, &val);
3206643ee871SKonstantin Belousov 	if (error == 0) {
3207643ee871SKonstantin Belousov 		ITS_CP(val, val32);
3208643ee871SKonstantin Belousov 		error = copyout(&val32, uap->value, sizeof(val32));
3209643ee871SKonstantin Belousov 	}
3210643ee871SKonstantin Belousov 	return (error);
3211643ee871SKonstantin Belousov }
3212643ee871SKonstantin Belousov 
3213cda9a0d1SDavid Xu int
freebsd32_timerfd_gettime(struct thread * td,struct freebsd32_timerfd_gettime_args * uap)3214918966a2SJake Freeland freebsd32_timerfd_gettime(struct thread *td,
3215918966a2SJake Freeland     struct freebsd32_timerfd_gettime_args *uap)
3216918966a2SJake Freeland {
3217918966a2SJake Freeland 	struct itimerspec curr_value;
3218918966a2SJake Freeland 	struct itimerspec32 curr_value32;
3219918966a2SJake Freeland 	int error;
3220918966a2SJake Freeland 
3221918966a2SJake Freeland 	error = kern_timerfd_gettime(td, uap->fd, &curr_value);
3222918966a2SJake Freeland 	if (error == 0) {
3223918966a2SJake Freeland 		CP(curr_value, curr_value32, it_value.tv_sec);
3224918966a2SJake Freeland 		CP(curr_value, curr_value32, it_value.tv_nsec);
3225918966a2SJake Freeland 		CP(curr_value, curr_value32, it_interval.tv_sec);
3226918966a2SJake Freeland 		CP(curr_value, curr_value32, it_interval.tv_nsec);
3227918966a2SJake Freeland 		error = copyout(&curr_value32, uap->curr_value,
3228918966a2SJake Freeland 		    sizeof(curr_value32));
3229918966a2SJake Freeland 	}
3230918966a2SJake Freeland 
3231918966a2SJake Freeland 	return (error);
3232918966a2SJake Freeland }
3233918966a2SJake Freeland 
3234918966a2SJake Freeland int
freebsd32_timerfd_settime(struct thread * td,struct freebsd32_timerfd_settime_args * uap)3235918966a2SJake Freeland freebsd32_timerfd_settime(struct thread *td,
3236918966a2SJake Freeland     struct freebsd32_timerfd_settime_args *uap)
3237918966a2SJake Freeland {
3238918966a2SJake Freeland 	struct itimerspec new_value, old_value;
3239918966a2SJake Freeland 	struct itimerspec32 new_value32, old_value32;
3240918966a2SJake Freeland 	int error;
3241918966a2SJake Freeland 
3242918966a2SJake Freeland 	error = copyin(uap->new_value, &new_value32, sizeof(new_value32));
3243918966a2SJake Freeland 	if (error != 0)
3244918966a2SJake Freeland 		return (error);
3245918966a2SJake Freeland 	CP(new_value32, new_value, it_value.tv_sec);
3246918966a2SJake Freeland 	CP(new_value32, new_value, it_value.tv_nsec);
3247918966a2SJake Freeland 	CP(new_value32, new_value, it_interval.tv_sec);
3248918966a2SJake Freeland 	CP(new_value32, new_value, it_interval.tv_nsec);
3249918966a2SJake Freeland 	if (uap->old_value == NULL) {
3250918966a2SJake Freeland 		error = kern_timerfd_settime(td, uap->fd, uap->flags,
3251918966a2SJake Freeland 		    &new_value, NULL);
3252918966a2SJake Freeland 	} else {
3253918966a2SJake Freeland 		error = kern_timerfd_settime(td, uap->fd, uap->flags,
3254918966a2SJake Freeland 		    &new_value, &old_value);
3255918966a2SJake Freeland 		if (error == 0) {
3256918966a2SJake Freeland 			CP(old_value, old_value32, it_value.tv_sec);
3257918966a2SJake Freeland 			CP(old_value, old_value32, it_value.tv_nsec);
3258918966a2SJake Freeland 			CP(old_value, old_value32, it_interval.tv_sec);
3259918966a2SJake Freeland 			CP(old_value, old_value32, it_interval.tv_nsec);
3260918966a2SJake Freeland 			error = copyout(&old_value32, uap->old_value,
3261918966a2SJake Freeland 			    sizeof(old_value32));
3262918966a2SJake Freeland 		}
3263918966a2SJake Freeland 	}
3264918966a2SJake Freeland 	return (error);
3265918966a2SJake Freeland }
3266918966a2SJake Freeland 
3267918966a2SJake Freeland int
freebsd32_clock_getcpuclockid2(struct thread * td,struct freebsd32_clock_getcpuclockid2_args * uap)3268d31e4b3aSKonstantin Belousov freebsd32_clock_getcpuclockid2(struct thread *td,
3269d31e4b3aSKonstantin Belousov     struct freebsd32_clock_getcpuclockid2_args *uap)
3270d31e4b3aSKonstantin Belousov {
3271d31e4b3aSKonstantin Belousov 	clockid_t clk_id;
3272d31e4b3aSKonstantin Belousov 	int error;
3273d31e4b3aSKonstantin Belousov 
3274d31e4b3aSKonstantin Belousov 	error = kern_clock_getcpuclockid2(td, PAIR32TO64(id_t, uap->id),
3275d31e4b3aSKonstantin Belousov 	    uap->which, &clk_id);
3276d31e4b3aSKonstantin Belousov 	if (error == 0)
3277d31e4b3aSKonstantin Belousov 		error = copyout(&clk_id, uap->clock_id, sizeof(clockid_t));
3278d31e4b3aSKonstantin Belousov 	return (error);
3279d31e4b3aSKonstantin Belousov }
3280d31e4b3aSKonstantin Belousov 
3281d31e4b3aSKonstantin Belousov int
freebsd32_thr_new(struct thread * td,struct freebsd32_thr_new_args * uap)3282cda9a0d1SDavid Xu freebsd32_thr_new(struct thread *td,
3283cda9a0d1SDavid Xu 		  struct freebsd32_thr_new_args *uap)
3284cda9a0d1SDavid Xu {
3285cda9a0d1SDavid Xu 	struct thr_param32 param32;
3286cda9a0d1SDavid Xu 	struct thr_param param;
3287cda9a0d1SDavid Xu 	int error;
3288cda9a0d1SDavid Xu 
3289cda9a0d1SDavid Xu 	if (uap->param_size < 0 ||
3290cda9a0d1SDavid Xu 	    uap->param_size > sizeof(struct thr_param32))
3291cda9a0d1SDavid Xu 		return (EINVAL);
3292cda9a0d1SDavid Xu 	bzero(&param, sizeof(struct thr_param));
3293cda9a0d1SDavid Xu 	bzero(&param32, sizeof(struct thr_param32));
3294cda9a0d1SDavid Xu 	error = copyin(uap->param, &param32, uap->param_size);
3295cda9a0d1SDavid Xu 	if (error != 0)
3296cda9a0d1SDavid Xu 		return (error);
3297cda9a0d1SDavid Xu 	param.start_func = PTRIN(param32.start_func);
3298cda9a0d1SDavid Xu 	param.arg = PTRIN(param32.arg);
3299cda9a0d1SDavid Xu 	param.stack_base = PTRIN(param32.stack_base);
3300cda9a0d1SDavid Xu 	param.stack_size = param32.stack_size;
3301cda9a0d1SDavid Xu 	param.tls_base = PTRIN(param32.tls_base);
3302cda9a0d1SDavid Xu 	param.tls_size = param32.tls_size;
3303cda9a0d1SDavid Xu 	param.child_tid = PTRIN(param32.child_tid);
3304cda9a0d1SDavid Xu 	param.parent_tid = PTRIN(param32.parent_tid);
3305cda9a0d1SDavid Xu 	param.flags = param32.flags;
3306cda9a0d1SDavid Xu 	param.rtp = PTRIN(param32.rtp);
3307cda9a0d1SDavid Xu 	param.spare[0] = PTRIN(param32.spare[0]);
3308cda9a0d1SDavid Xu 	param.spare[1] = PTRIN(param32.spare[1]);
3309cda9a0d1SDavid Xu 	param.spare[2] = PTRIN(param32.spare[2]);
3310cda9a0d1SDavid Xu 
3311cda9a0d1SDavid Xu 	return (kern_thr_new(td, &param));
3312cda9a0d1SDavid Xu }
3313cda9a0d1SDavid Xu 
3314cda9a0d1SDavid Xu int
freebsd32_thr_suspend(struct thread * td,struct freebsd32_thr_suspend_args * uap)3315cda9a0d1SDavid Xu freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
3316cda9a0d1SDavid Xu {
3317cda9a0d1SDavid Xu 	struct timespec32 ts32;
3318cda9a0d1SDavid Xu 	struct timespec ts, *tsp;
3319cda9a0d1SDavid Xu 	int error;
3320cda9a0d1SDavid Xu 
3321cda9a0d1SDavid Xu 	error = 0;
3322cda9a0d1SDavid Xu 	tsp = NULL;
3323cda9a0d1SDavid Xu 	if (uap->timeout != NULL) {
3324cda9a0d1SDavid Xu 		error = copyin((const void *)uap->timeout, (void *)&ts32,
3325cda9a0d1SDavid Xu 		    sizeof(struct timespec32));
3326cda9a0d1SDavid Xu 		if (error != 0)
3327cda9a0d1SDavid Xu 			return (error);
3328cda9a0d1SDavid Xu 		ts.tv_sec = ts32.tv_sec;
3329cda9a0d1SDavid Xu 		ts.tv_nsec = ts32.tv_nsec;
3330cda9a0d1SDavid Xu 		tsp = &ts;
3331cda9a0d1SDavid Xu 	}
3332cda9a0d1SDavid Xu 	return (kern_thr_suspend(td, tsp));
3333cda9a0d1SDavid Xu }
3334cda9a0d1SDavid Xu 
3335c6511aeaSDavid Xu void
siginfo_to_siginfo32(const siginfo_t * src,struct __siginfo32 * dst)3336d060b420SBrooks Davis siginfo_to_siginfo32(const siginfo_t *src, struct __siginfo32 *dst)
3337c6511aeaSDavid Xu {
3338c6511aeaSDavid Xu 	bzero(dst, sizeof(*dst));
3339c6511aeaSDavid Xu 	dst->si_signo = src->si_signo;
3340c6511aeaSDavid Xu 	dst->si_errno = src->si_errno;
3341c6511aeaSDavid Xu 	dst->si_code = src->si_code;
3342c6511aeaSDavid Xu 	dst->si_pid = src->si_pid;
3343c6511aeaSDavid Xu 	dst->si_uid = src->si_uid;
3344c6511aeaSDavid Xu 	dst->si_status = src->si_status;
3345dc5aaa84SPeter Wemm 	dst->si_addr = (uintptr_t)src->si_addr;
3346df4d0ed1SKonstantin Belousov 	dst->si_value.sival_int = src->si_value.sival_int;
3347c6511aeaSDavid Xu 	dst->si_timerid = src->si_timerid;
3348c6511aeaSDavid Xu 	dst->si_overrun = src->si_overrun;
3349c6511aeaSDavid Xu }
3350c6511aeaSDavid Xu 
3351f19351aaSBrooks Davis #ifndef _FREEBSD32_SYSPROTO_H_
3352f19351aaSBrooks Davis struct freebsd32_sigqueue_args {
3353f19351aaSBrooks Davis         pid_t pid;
3354f19351aaSBrooks Davis         int signum;
3355f19351aaSBrooks Davis         /* union sigval32 */ int value;
3356f19351aaSBrooks Davis };
3357f19351aaSBrooks Davis #endif
3358f19351aaSBrooks Davis int
freebsd32_sigqueue(struct thread * td,struct freebsd32_sigqueue_args * uap)3359f19351aaSBrooks Davis freebsd32_sigqueue(struct thread *td, struct freebsd32_sigqueue_args *uap)
3360f19351aaSBrooks Davis {
3361f19351aaSBrooks Davis 	union sigval sv;
3362f19351aaSBrooks Davis 
3363f19351aaSBrooks Davis 	/*
3364f19351aaSBrooks Davis 	 * On 32-bit ABIs, sival_int and sival_ptr are the same.
3365f19351aaSBrooks Davis 	 * On 64-bit little-endian ABIs, the low bits are the same.
3366f19351aaSBrooks Davis 	 * In 64-bit big-endian ABIs, sival_int overlaps with
3367f19351aaSBrooks Davis 	 * sival_ptr's HIGH bits.  We choose to support sival_int
3368f19351aaSBrooks Davis 	 * rather than sival_ptr in this case as it seems to be
3369f19351aaSBrooks Davis 	 * more common.
3370f19351aaSBrooks Davis 	 */
3371f19351aaSBrooks Davis 	bzero(&sv, sizeof(sv));
3372158dcd73SBrooks Davis 	sv.sival_int = (uint32_t)(uint64_t)uap->value;
3373f19351aaSBrooks Davis 
3374f19351aaSBrooks Davis 	return (kern_sigqueue(td, uap->pid, uap->signum, &sv));
3375f19351aaSBrooks Davis }
3376f19351aaSBrooks Davis 
3377c6511aeaSDavid Xu int
freebsd32_sigtimedwait(struct thread * td,struct freebsd32_sigtimedwait_args * uap)3378c6511aeaSDavid Xu freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
3379c6511aeaSDavid Xu {
3380c6511aeaSDavid Xu 	struct timespec32 ts32;
3381c6511aeaSDavid Xu 	struct timespec ts;
3382c6511aeaSDavid Xu 	struct timespec *timeout;
3383c6511aeaSDavid Xu 	sigset_t set;
3384c6511aeaSDavid Xu 	ksiginfo_t ksi;
3385d060b420SBrooks Davis 	struct __siginfo32 si32;
3386c6511aeaSDavid Xu 	int error;
3387c6511aeaSDavid Xu 
3388c6511aeaSDavid Xu 	if (uap->timeout) {
3389c6511aeaSDavid Xu 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
3390c6511aeaSDavid Xu 		if (error)
3391c6511aeaSDavid Xu 			return (error);
3392c6511aeaSDavid Xu 		ts.tv_sec = ts32.tv_sec;
3393c6511aeaSDavid Xu 		ts.tv_nsec = ts32.tv_nsec;
3394c6511aeaSDavid Xu 		timeout = &ts;
3395c6511aeaSDavid Xu 	} else
3396c6511aeaSDavid Xu 		timeout = NULL;
3397c6511aeaSDavid Xu 
3398c6511aeaSDavid Xu 	error = copyin(uap->set, &set, sizeof(set));
3399c6511aeaSDavid Xu 	if (error)
3400c6511aeaSDavid Xu 		return (error);
3401c6511aeaSDavid Xu 
3402c6511aeaSDavid Xu 	error = kern_sigtimedwait(td, set, &ksi, timeout);
3403c6511aeaSDavid Xu 	if (error)
3404c6511aeaSDavid Xu 		return (error);
3405c6511aeaSDavid Xu 
3406c6511aeaSDavid Xu 	if (uap->info) {
3407c6511aeaSDavid Xu 		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
3408d060b420SBrooks Davis 		error = copyout(&si32, uap->info, sizeof(struct __siginfo32));
3409c6511aeaSDavid Xu 	}
3410c6511aeaSDavid Xu 
3411c6511aeaSDavid Xu 	if (error == 0)
3412c6511aeaSDavid Xu 		td->td_retval[0] = ksi.ksi_signo;
3413c6511aeaSDavid Xu 	return (error);
3414c6511aeaSDavid Xu }
3415c6511aeaSDavid Xu 
3416c6511aeaSDavid Xu /*
3417c6511aeaSDavid Xu  * MPSAFE
3418c6511aeaSDavid Xu  */
3419c6511aeaSDavid Xu int
freebsd32_sigwaitinfo(struct thread * td,struct freebsd32_sigwaitinfo_args * uap)3420c6511aeaSDavid Xu freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
3421c6511aeaSDavid Xu {
3422c6511aeaSDavid Xu 	ksiginfo_t ksi;
3423d060b420SBrooks Davis 	struct __siginfo32 si32;
3424c6511aeaSDavid Xu 	sigset_t set;
3425c6511aeaSDavid Xu 	int error;
3426c6511aeaSDavid Xu 
3427c6511aeaSDavid Xu 	error = copyin(uap->set, &set, sizeof(set));
3428c6511aeaSDavid Xu 	if (error)
3429c6511aeaSDavid Xu 		return (error);
3430c6511aeaSDavid Xu 
3431c6511aeaSDavid Xu 	error = kern_sigtimedwait(td, set, &ksi, NULL);
3432c6511aeaSDavid Xu 	if (error)
3433c6511aeaSDavid Xu 		return (error);
3434c6511aeaSDavid Xu 
3435c6511aeaSDavid Xu 	if (uap->info) {
3436c6511aeaSDavid Xu 		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
3437d060b420SBrooks Davis 		error = copyout(&si32, uap->info, sizeof(struct __siginfo32));
3438c6511aeaSDavid Xu 	}
3439c6511aeaSDavid Xu 	if (error == 0)
3440c6511aeaSDavid Xu 		td->td_retval[0] = ksi.ksi_signo;
3441c6511aeaSDavid Xu 	return (error);
3442c6511aeaSDavid Xu }
3443c6511aeaSDavid Xu 
3444a8c6d6d0SBrooks Davis int
freebsd32_cpuset_setid(struct thread * td,struct freebsd32_cpuset_setid_args * uap)3445a8c6d6d0SBrooks Davis freebsd32_cpuset_setid(struct thread *td,
3446a8c6d6d0SBrooks Davis     struct freebsd32_cpuset_setid_args *uap)
3447a8c6d6d0SBrooks Davis {
3448a8c6d6d0SBrooks Davis 
3449ea2ebdc1SEdward Tomasz Napierala 	return (kern_cpuset_setid(td, uap->which,
3450ea2ebdc1SEdward Tomasz Napierala 	    PAIR32TO64(id_t, uap->id), uap->setid));
3451a8c6d6d0SBrooks Davis }
3452a8c6d6d0SBrooks Davis 
3453a8c6d6d0SBrooks Davis int
freebsd32_cpuset_getid(struct thread * td,struct freebsd32_cpuset_getid_args * uap)3454a8c6d6d0SBrooks Davis freebsd32_cpuset_getid(struct thread *td,
3455a8c6d6d0SBrooks Davis     struct freebsd32_cpuset_getid_args *uap)
3456a8c6d6d0SBrooks Davis {
3457a8c6d6d0SBrooks Davis 
3458ea2ebdc1SEdward Tomasz Napierala 	return (kern_cpuset_getid(td, uap->level, uap->which,
3459ea2ebdc1SEdward Tomasz Napierala 	    PAIR32TO64(id_t, uap->id), uap->setid));
3460a8c6d6d0SBrooks Davis }
3461a8c6d6d0SBrooks Davis 
346247a57144SJustin Hibbits static int
copyin32_set(const void * u,void * k,size_t size)346347a57144SJustin Hibbits copyin32_set(const void *u, void *k, size_t size)
346447a57144SJustin Hibbits {
346547a57144SJustin Hibbits #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
346647a57144SJustin Hibbits 	int rv;
346747a57144SJustin Hibbits 	struct bitset *kb = k;
346847a57144SJustin Hibbits 	int *p;
346947a57144SJustin Hibbits 
347047a57144SJustin Hibbits 	rv = copyin(u, k, size);
347147a57144SJustin Hibbits 	if (rv != 0)
347247a57144SJustin Hibbits 		return (rv);
347347a57144SJustin Hibbits 
347447a57144SJustin Hibbits 	p = (int *)kb->__bits;
347547a57144SJustin Hibbits 	/* Loop through swapping words.
347647a57144SJustin Hibbits 	 * `size' is in bytes, we need bits. */
347747a57144SJustin Hibbits 	for (int i = 0; i < __bitset_words(size * 8); i++) {
347847a57144SJustin Hibbits 		int tmp = p[0];
347947a57144SJustin Hibbits 		p[0] = p[1];
348047a57144SJustin Hibbits 		p[1] = tmp;
348147a57144SJustin Hibbits 		p += 2;
348247a57144SJustin Hibbits 	}
348347a57144SJustin Hibbits 	return (0);
348447a57144SJustin Hibbits #else
348547a57144SJustin Hibbits 	return (copyin(u, k, size));
348647a57144SJustin Hibbits #endif
348747a57144SJustin Hibbits }
348847a57144SJustin Hibbits 
348947a57144SJustin Hibbits static int
copyout32_set(const void * k,void * u,size_t size)349047a57144SJustin Hibbits copyout32_set(const void *k, void *u, size_t size)
349147a57144SJustin Hibbits {
349247a57144SJustin Hibbits #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
349347a57144SJustin Hibbits 	const struct bitset *kb = k;
349447a57144SJustin Hibbits 	struct bitset *ub = u;
349547a57144SJustin Hibbits 	const int *kp = (const int *)kb->__bits;
349647a57144SJustin Hibbits 	int *up = (int *)ub->__bits;
349747a57144SJustin Hibbits 	int rv;
349847a57144SJustin Hibbits 
349947a57144SJustin Hibbits 	for (int i = 0; i < __bitset_words(CPU_SETSIZE); i++) {
350047a57144SJustin Hibbits 		/* `size' is in bytes, we need bits. */
350147a57144SJustin Hibbits 		for (int i = 0; i < __bitset_words(size * 8); i++) {
350247a57144SJustin Hibbits 			rv = suword32(up, kp[1]);
350347a57144SJustin Hibbits 			if (rv == 0)
350447a57144SJustin Hibbits 				rv = suword32(up + 1, kp[0]);
350547a57144SJustin Hibbits 			if (rv != 0)
350647a57144SJustin Hibbits 				return (EFAULT);
350747a57144SJustin Hibbits 		}
350847a57144SJustin Hibbits 	}
350947a57144SJustin Hibbits 	return (0);
351047a57144SJustin Hibbits #else
351147a57144SJustin Hibbits 	return (copyout(k, u, size));
351247a57144SJustin Hibbits #endif
351347a57144SJustin Hibbits }
351447a57144SJustin Hibbits 
351547a57144SJustin Hibbits static const struct cpuset_copy_cb cpuset_copy32_cb = {
35164a3e5133SMark Johnston 	.cpuset_copyin = copyin32_set,
35174a3e5133SMark Johnston 	.cpuset_copyout = copyout32_set
351847a57144SJustin Hibbits };
351947a57144SJustin Hibbits 
3520a8c6d6d0SBrooks Davis int
freebsd32_cpuset_getaffinity(struct thread * td,struct freebsd32_cpuset_getaffinity_args * uap)3521a8c6d6d0SBrooks Davis freebsd32_cpuset_getaffinity(struct thread *td,
3522a8c6d6d0SBrooks Davis     struct freebsd32_cpuset_getaffinity_args *uap)
3523a8c6d6d0SBrooks Davis {
3524a8c6d6d0SBrooks Davis 
3525d46174cdSDmitry Chagin 	return (user_cpuset_getaffinity(td, uap->level, uap->which,
352647a57144SJustin Hibbits 	    PAIR32TO64(id_t,uap->id), uap->cpusetsize, uap->mask,
352747a57144SJustin Hibbits 	    &cpuset_copy32_cb));
3528a8c6d6d0SBrooks Davis }
3529a8c6d6d0SBrooks Davis 
3530a8c6d6d0SBrooks Davis int
freebsd32_cpuset_setaffinity(struct thread * td,struct freebsd32_cpuset_setaffinity_args * uap)3531a8c6d6d0SBrooks Davis freebsd32_cpuset_setaffinity(struct thread *td,
3532a8c6d6d0SBrooks Davis     struct freebsd32_cpuset_setaffinity_args *uap)
3533a8c6d6d0SBrooks Davis {
3534a8c6d6d0SBrooks Davis 
3535f35093f8SDmitry Chagin 	return (user_cpuset_setaffinity(td, uap->level, uap->which,
353647a57144SJustin Hibbits 	    PAIR32TO64(id_t,uap->id), uap->cpusetsize, uap->mask,
353747a57144SJustin Hibbits 	    &cpuset_copy32_cb));
3538a8c6d6d0SBrooks Davis }
3539a8c6d6d0SBrooks Davis 
35406e6049e9SDavid E. O'Brien int
freebsd32_cpuset_getdomain(struct thread * td,struct freebsd32_cpuset_getdomain_args * uap)35413f289c3fSJeff Roberson freebsd32_cpuset_getdomain(struct thread *td,
35423f289c3fSJeff Roberson     struct freebsd32_cpuset_getdomain_args *uap)
35433f289c3fSJeff Roberson {
35443f289c3fSJeff Roberson 
35453f289c3fSJeff Roberson 	return (kern_cpuset_getdomain(td, uap->level, uap->which,
354647a57144SJustin Hibbits 	    PAIR32TO64(id_t,uap->id), uap->domainsetsize, uap->mask, uap->policy,
354747a57144SJustin Hibbits 	    &cpuset_copy32_cb));
35483f289c3fSJeff Roberson }
35493f289c3fSJeff Roberson 
35503f289c3fSJeff Roberson int
freebsd32_cpuset_setdomain(struct thread * td,struct freebsd32_cpuset_setdomain_args * uap)35513f289c3fSJeff Roberson freebsd32_cpuset_setdomain(struct thread *td,
35523f289c3fSJeff Roberson     struct freebsd32_cpuset_setdomain_args *uap)
35533f289c3fSJeff Roberson {
35543f289c3fSJeff Roberson 
35553f289c3fSJeff Roberson 	return (kern_cpuset_setdomain(td, uap->level, uap->which,
355647a57144SJustin Hibbits 	    PAIR32TO64(id_t,uap->id), uap->domainsetsize, uap->mask, uap->policy,
355747a57144SJustin Hibbits 	    &cpuset_copy32_cb));
35583f289c3fSJeff Roberson }
35593f289c3fSJeff Roberson 
35603f289c3fSJeff Roberson int
freebsd32_nmount(struct thread * td,struct freebsd32_nmount_args * uap)35616e6049e9SDavid E. O'Brien freebsd32_nmount(struct thread *td,
35626e6049e9SDavid E. O'Brien     struct freebsd32_nmount_args /* {
35636e6049e9SDavid E. O'Brien     	struct iovec *iovp;
35646e6049e9SDavid E. O'Brien     	unsigned int iovcnt;
35656e6049e9SDavid E. O'Brien     	int flags;
35666e6049e9SDavid E. O'Brien     } */ *uap)
35676e6049e9SDavid E. O'Brien {
35686e6049e9SDavid E. O'Brien 	struct uio *auio;
3569cc672d35SKirk McKusick 	uint64_t flags;
3570f86bce5eSJamie Gritton 	int error;
35713ebc1248SPeter Wemm 
3572cc672d35SKirk McKusick 	/*
3573cc672d35SKirk McKusick 	 * Mount flags are now 64-bits. On 32-bit archtectures only
3574cc672d35SKirk McKusick 	 * 32-bits are passed in, but from here on everything handles
3575cc672d35SKirk McKusick 	 * 64-bit flags correctly.
3576cc672d35SKirk McKusick 	 */
3577cc672d35SKirk McKusick 	flags = uap->flags;
3578cc672d35SKirk McKusick 
3579cc672d35SKirk McKusick 	AUDIT_ARG_FFLAGS(flags);
35806e6049e9SDavid E. O'Brien 
35816e6049e9SDavid E. O'Brien 	/*
35826e6049e9SDavid E. O'Brien 	 * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
35836e6049e9SDavid E. O'Brien 	 * userspace to set this flag, but we must filter it out if we want
35846e6049e9SDavid E. O'Brien 	 * MNT_UPDATE on the root file system to work.
3585f03749caSSergey Kandaurov 	 * MNT_ROOTFS should only be set by the kernel when mounting its
3586f03749caSSergey Kandaurov 	 * root file system.
35876e6049e9SDavid E. O'Brien 	 */
3588cc672d35SKirk McKusick 	flags &= ~MNT_ROOTFS;
35896e6049e9SDavid E. O'Brien 
35906e6049e9SDavid E. O'Brien 	/*
35916e6049e9SDavid E. O'Brien 	 * check that we have an even number of iovec's
35926e6049e9SDavid E. O'Brien 	 * and that we have at least two options.
35936e6049e9SDavid E. O'Brien 	 */
35946e6049e9SDavid E. O'Brien 	if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
35956e6049e9SDavid E. O'Brien 		return (EINVAL);
35966e6049e9SDavid E. O'Brien 
35976e6049e9SDavid E. O'Brien 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
35986e6049e9SDavid E. O'Brien 	if (error)
35996e6049e9SDavid E. O'Brien 		return (error);
3600cc672d35SKirk McKusick 	error = vfs_donmount(td, flags, auio);
3601f86bce5eSJamie Gritton 
360261cc4830SAlfredo Mazzinghi 	freeuio(auio);
36036e6049e9SDavid E. O'Brien 	return error;
36046e6049e9SDavid E. O'Brien }
36056e6049e9SDavid E. O'Brien 
36066e6049e9SDavid E. O'Brien #if 0
36073ebc1248SPeter Wemm int
36081c7abef7SPeter Wemm freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
36093ebc1248SPeter Wemm {
36103ebc1248SPeter Wemm 	struct yyy32 *p32, s32;
36113ebc1248SPeter Wemm 	struct yyy *p = NULL, s;
3612109ea24cSDavid E. O'Brien 	struct xxx_arg ap;
3613109ea24cSDavid E. O'Brien 	int error;
36143ebc1248SPeter Wemm 
361519042f9cSJohn Baldwin 	if (uap->zzz) {
361619042f9cSJohn Baldwin 		error = copyin(uap->zzz, &s32, sizeof(s32));
36173ebc1248SPeter Wemm 		if (error)
36183ebc1248SPeter Wemm 			return (error);
36193ebc1248SPeter Wemm 		/* translate in */
362019042f9cSJohn Baldwin 		p = &s;
36213ebc1248SPeter Wemm 	}
362219042f9cSJohn Baldwin 	error = kern_xxx(td, p);
36233ebc1248SPeter Wemm 	if (error)
36243ebc1248SPeter Wemm 		return (error);
362519042f9cSJohn Baldwin 	if (uap->zzz) {
36263ebc1248SPeter Wemm 		/* translate out */
36273ebc1248SPeter Wemm 		error = copyout(&s32, p32, sizeof(s32));
36283ebc1248SPeter Wemm 	}
36293ebc1248SPeter Wemm 	return (error);
36303ebc1248SPeter Wemm }
36313ebc1248SPeter Wemm #endif
363288ac915aSJohn Baldwin 
363388ac915aSJohn Baldwin int
syscall32_module_handler(struct module * mod,int what,void * arg)363488ac915aSJohn Baldwin syscall32_module_handler(struct module *mod, int what, void *arg)
363588ac915aSJohn Baldwin {
363688ac915aSJohn Baldwin 
3637b81e88d2SBrooks Davis 	return (kern_syscall_module_handler(freebsd32_sysent, mod, what, arg));
363888ac915aSJohn Baldwin }
3639841c0c7eSNathan Whitehorn 
36400687ba3eSKonstantin Belousov int
syscall32_helper_register(struct syscall_helper_data * sd,int flags)3641e015b1abSMateusz Guzik syscall32_helper_register(struct syscall_helper_data *sd, int flags)
36420687ba3eSKonstantin Belousov {
36430687ba3eSKonstantin Belousov 
3644b81e88d2SBrooks Davis 	return (kern_syscall_helper_register(freebsd32_sysent, sd, flags));
36450687ba3eSKonstantin Belousov }
36460687ba3eSKonstantin Belousov 
36470687ba3eSKonstantin Belousov int
syscall32_helper_unregister(struct syscall_helper_data * sd)36480687ba3eSKonstantin Belousov syscall32_helper_unregister(struct syscall_helper_data *sd)
36490687ba3eSKonstantin Belousov {
36500687ba3eSKonstantin Belousov 
3651b81e88d2SBrooks Davis 	return (kern_syscall_helper_unregister(freebsd32_sysent, sd));
36520687ba3eSKonstantin Belousov }
36530687ba3eSKonstantin Belousov 
365403b0d68cSJohn Baldwin int
freebsd32_copyout_strings(struct image_params * imgp,uintptr_t * stack_base)365531174518SJohn Baldwin freebsd32_copyout_strings(struct image_params *imgp, uintptr_t *stack_base)
3656841c0c7eSNathan Whitehorn {
3657f04a0960SMark Johnston 	struct sysentvec *sysent;
3658ee235befSKonstantin Belousov 	int argc, envc, i;
3659cc5aa0a4SJohn Baldwin 	uint32_t *vectp;
366088b124ceSKonstantin Belousov 	char *stringp;
366131174518SJohn Baldwin 	uintptr_t destp, ustringp;
3662841c0c7eSNathan Whitehorn 	struct freebsd32_ps_strings *arginfo;
3663ee235befSKonstantin Belousov 	char canary[sizeof(long) * 8];
3664ee235befSKonstantin Belousov 	int32_t pagesizes32[MAXPAGESIZES];
3665841c0c7eSNathan Whitehorn 	size_t execpath_len;
366603b0d68cSJohn Baldwin 	int error, szsigcode;
3667841c0c7eSNathan Whitehorn 
3668f04a0960SMark Johnston 	sysent = imgp->sysent;
3669f04a0960SMark Johnston 
3670706f4a81SMark Johnston 	arginfo = (struct freebsd32_ps_strings *)PROC_PS_STRINGS(imgp->proc);
3671397df744SBrooks Davis 	imgp->ps_strings = arginfo;
367288b124ceSKonstantin Belousov 	destp =	(uintptr_t)arginfo;
3673841c0c7eSNathan Whitehorn 
3674841c0c7eSNathan Whitehorn 	/*
3675f04a0960SMark Johnston 	 * Install sigcode.
3676841c0c7eSNathan Whitehorn 	 */
3677361971fbSKornel Dulęba 	if (!PROC_HAS_SHP(imgp->proc)) {
3678f04a0960SMark Johnston 		szsigcode = *sysent->sv_szsigcode;
367988b124ceSKonstantin Belousov 		destp -= szsigcode;
368088b124ceSKonstantin Belousov 		destp = rounddown2(destp, sizeof(uint32_t));
3681f04a0960SMark Johnston 		error = copyout(sysent->sv_sigcode, (void *)destp,
368288b124ceSKonstantin Belousov 		    szsigcode);
368303b0d68cSJohn Baldwin 		if (error != 0)
368403b0d68cSJohn Baldwin 			return (error);
368588b124ceSKonstantin Belousov 	}
3686841c0c7eSNathan Whitehorn 
3687841c0c7eSNathan Whitehorn 	/*
3688841c0c7eSNathan Whitehorn 	 * Copy the image path for the rtld.
3689841c0c7eSNathan Whitehorn 	 */
3690f04a0960SMark Johnston 	if (imgp->execpath != NULL && imgp->auxargs != NULL) {
3691f04a0960SMark Johnston 		execpath_len = strlen(imgp->execpath) + 1;
369288b124ceSKonstantin Belousov 		destp -= execpath_len;
3693b24e6ac8SBrooks Davis 		imgp->execpathp = (void *)destp;
3694b24e6ac8SBrooks Davis 		error = copyout(imgp->execpath, imgp->execpathp, execpath_len);
369503b0d68cSJohn Baldwin 		if (error != 0)
369603b0d68cSJohn Baldwin 			return (error);
3697841c0c7eSNathan Whitehorn 	}
3698841c0c7eSNathan Whitehorn 
3699841c0c7eSNathan Whitehorn 	/*
3700ee235befSKonstantin Belousov 	 * Prepare the canary for SSP.
3701ee235befSKonstantin Belousov 	 */
3702ee235befSKonstantin Belousov 	arc4rand(canary, sizeof(canary), 0);
370388b124ceSKonstantin Belousov 	destp -= sizeof(canary);
3704b24e6ac8SBrooks Davis 	imgp->canary = (void *)destp;
3705b24e6ac8SBrooks Davis 	error = copyout(canary, imgp->canary, sizeof(canary));
370603b0d68cSJohn Baldwin 	if (error != 0)
370703b0d68cSJohn Baldwin 		return (error);
3708ee235befSKonstantin Belousov 	imgp->canarylen = sizeof(canary);
3709ee235befSKonstantin Belousov 
3710ee235befSKonstantin Belousov 	/*
3711ee235befSKonstantin Belousov 	 * Prepare the pagesizes array.
3712ee235befSKonstantin Belousov 	 */
3713ee235befSKonstantin Belousov 	for (i = 0; i < MAXPAGESIZES; i++)
3714ee235befSKonstantin Belousov 		pagesizes32[i] = (uint32_t)pagesizes[i];
371588b124ceSKonstantin Belousov 	destp -= sizeof(pagesizes32);
371688b124ceSKonstantin Belousov 	destp = rounddown2(destp, sizeof(uint32_t));
3717b24e6ac8SBrooks Davis 	imgp->pagesizes = (void *)destp;
3718b24e6ac8SBrooks Davis 	error = copyout(pagesizes32, imgp->pagesizes, sizeof(pagesizes32));
371903b0d68cSJohn Baldwin 	if (error != 0)
372003b0d68cSJohn Baldwin 		return (error);
3721ee235befSKonstantin Belousov 	imgp->pagesizeslen = sizeof(pagesizes32);
3722ee235befSKonstantin Belousov 
372331174518SJohn Baldwin 	/*
372431174518SJohn Baldwin 	 * Allocate room for the argument and environment strings.
372531174518SJohn Baldwin 	 */
372688b124ceSKonstantin Belousov 	destp -= ARG_MAX - imgp->args->stringspace;
372788b124ceSKonstantin Belousov 	destp = rounddown2(destp, sizeof(uint32_t));
372831174518SJohn Baldwin 	ustringp = destp;
372988b124ceSKonstantin Belousov 
373003b0d68cSJohn Baldwin 	if (imgp->auxargs) {
3731d8010b11SJohn Baldwin 		/*
3732d8010b11SJohn Baldwin 		 * Allocate room on the stack for the ELF auxargs
3733d8010b11SJohn Baldwin 		 * array.  It has up to AT_COUNT entries.
3734d8010b11SJohn Baldwin 		 */
3735d8010b11SJohn Baldwin 		destp -= AT_COUNT * sizeof(Elf32_Auxinfo);
3736d8010b11SJohn Baldwin 		destp = rounddown2(destp, sizeof(uint32_t));
373703b0d68cSJohn Baldwin 	}
3738841c0c7eSNathan Whitehorn 
373931174518SJohn Baldwin 	vectp = (uint32_t *)destp;
374031174518SJohn Baldwin 
3741841c0c7eSNathan Whitehorn 	/*
374273c8686eSJohn Baldwin 	 * Allocate room for the argv[] and env vectors including the
374373c8686eSJohn Baldwin 	 * terminating NULL pointers.
374473c8686eSJohn Baldwin 	 */
374573c8686eSJohn Baldwin 	vectp -= imgp->args->argc + 1 + imgp->args->envc + 1;
374673c8686eSJohn Baldwin 
374773c8686eSJohn Baldwin 	/*
3748841c0c7eSNathan Whitehorn 	 * vectp also becomes our initial stack base
3749841c0c7eSNathan Whitehorn 	 */
375031174518SJohn Baldwin 	*stack_base = (uintptr_t)vectp;
3751841c0c7eSNathan Whitehorn 
3752841c0c7eSNathan Whitehorn 	stringp = imgp->args->begin_argv;
3753841c0c7eSNathan Whitehorn 	argc = imgp->args->argc;
3754841c0c7eSNathan Whitehorn 	envc = imgp->args->envc;
3755841c0c7eSNathan Whitehorn 	/*
3756841c0c7eSNathan Whitehorn 	 * Copy out strings - arguments and environment.
3757841c0c7eSNathan Whitehorn 	 */
375831174518SJohn Baldwin 	error = copyout(stringp, (void *)ustringp,
375903b0d68cSJohn Baldwin 	    ARG_MAX - imgp->args->stringspace);
376003b0d68cSJohn Baldwin 	if (error != 0)
376103b0d68cSJohn Baldwin 		return (error);
3762841c0c7eSNathan Whitehorn 
3763841c0c7eSNathan Whitehorn 	/*
3764841c0c7eSNathan Whitehorn 	 * Fill in "ps_strings" struct for ps, w, etc.
3765841c0c7eSNathan Whitehorn 	 */
37669df1c38bSBrooks Davis 	imgp->argv = vectp;
3767cc5aa0a4SJohn Baldwin 	if (suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp) != 0 ||
376803b0d68cSJohn Baldwin 	    suword32(&arginfo->ps_nargvstr, argc) != 0)
376903b0d68cSJohn Baldwin 		return (EFAULT);
3770841c0c7eSNathan Whitehorn 
3771841c0c7eSNathan Whitehorn 	/*
3772841c0c7eSNathan Whitehorn 	 * Fill in argument portion of vector table.
3773841c0c7eSNathan Whitehorn 	 */
3774841c0c7eSNathan Whitehorn 	for (; argc > 0; --argc) {
377531174518SJohn Baldwin 		if (suword32(vectp++, ustringp) != 0)
377603b0d68cSJohn Baldwin 			return (EFAULT);
3777841c0c7eSNathan Whitehorn 		while (*stringp++ != 0)
377831174518SJohn Baldwin 			ustringp++;
377931174518SJohn Baldwin 		ustringp++;
3780841c0c7eSNathan Whitehorn 	}
3781841c0c7eSNathan Whitehorn 
3782841c0c7eSNathan Whitehorn 	/* a null vector table pointer separates the argp's from the envp's */
378303b0d68cSJohn Baldwin 	if (suword32(vectp++, 0) != 0)
378403b0d68cSJohn Baldwin 		return (EFAULT);
3785841c0c7eSNathan Whitehorn 
37869df1c38bSBrooks Davis 	imgp->envv = vectp;
3787cc5aa0a4SJohn Baldwin 	if (suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp) != 0 ||
378803b0d68cSJohn Baldwin 	    suword32(&arginfo->ps_nenvstr, envc) != 0)
378903b0d68cSJohn Baldwin 		return (EFAULT);
3790841c0c7eSNathan Whitehorn 
3791841c0c7eSNathan Whitehorn 	/*
3792841c0c7eSNathan Whitehorn 	 * Fill in environment portion of vector table.
3793841c0c7eSNathan Whitehorn 	 */
3794841c0c7eSNathan Whitehorn 	for (; envc > 0; --envc) {
379531174518SJohn Baldwin 		if (suword32(vectp++, ustringp) != 0)
379603b0d68cSJohn Baldwin 			return (EFAULT);
3797841c0c7eSNathan Whitehorn 		while (*stringp++ != 0)
379831174518SJohn Baldwin 			ustringp++;
379931174518SJohn Baldwin 		ustringp++;
3800841c0c7eSNathan Whitehorn 	}
3801841c0c7eSNathan Whitehorn 
3802841c0c7eSNathan Whitehorn 	/* end of vector table is a null pointer */
380303b0d68cSJohn Baldwin 	if (suword32(vectp, 0) != 0)
380403b0d68cSJohn Baldwin 		return (EFAULT);
3805841c0c7eSNathan Whitehorn 
3806d8010b11SJohn Baldwin 	if (imgp->auxargs) {
3807d8010b11SJohn Baldwin 		vectp++;
3808d8010b11SJohn Baldwin 		error = imgp->sysent->sv_copyout_auxargs(imgp,
3809d8010b11SJohn Baldwin 		    (uintptr_t)vectp);
3810d8010b11SJohn Baldwin 		if (error != 0)
3811d8010b11SJohn Baldwin 			return (error);
3812d8010b11SJohn Baldwin 	}
3813d8010b11SJohn Baldwin 
381403b0d68cSJohn Baldwin 	return (0);
3815841c0c7eSNathan Whitehorn }
3816841c0c7eSNathan Whitehorn 
381786665509SKonstantin Belousov int
freebsd32_kldstat(struct thread * td,struct freebsd32_kldstat_args * uap)381886665509SKonstantin Belousov freebsd32_kldstat(struct thread *td, struct freebsd32_kldstat_args *uap)
381986665509SKonstantin Belousov {
3820edb01d11SGordon Tetlow 	struct kld_file_stat *stat;
38215d0d6869SBrooks Davis 	struct kld_file_stat32 *stat32;
382286665509SKonstantin Belousov 	int error, version;
382386665509SKonstantin Belousov 
382486665509SKonstantin Belousov 	if ((error = copyin(&uap->stat->version, &version, sizeof(version)))
382586665509SKonstantin Belousov 	    != 0)
382686665509SKonstantin Belousov 		return (error);
38275d0d6869SBrooks Davis 	if (version != sizeof(struct kld_file_stat_1_32) &&
38285d0d6869SBrooks Davis 	    version != sizeof(struct kld_file_stat32))
382986665509SKonstantin Belousov 		return (EINVAL);
383086665509SKonstantin Belousov 
3831edb01d11SGordon Tetlow 	stat = malloc(sizeof(*stat), M_TEMP, M_WAITOK | M_ZERO);
3832edb01d11SGordon Tetlow 	stat32 = malloc(sizeof(*stat32), M_TEMP, M_WAITOK | M_ZERO);
3833edb01d11SGordon Tetlow 	error = kern_kldstat(td, uap->fileid, stat);
3834edb01d11SGordon Tetlow 	if (error == 0) {
3835edb01d11SGordon Tetlow 		bcopy(&stat->name[0], &stat32->name[0], sizeof(stat->name));
3836edb01d11SGordon Tetlow 		CP(*stat, *stat32, refs);
3837edb01d11SGordon Tetlow 		CP(*stat, *stat32, id);
3838edb01d11SGordon Tetlow 		PTROUT_CP(*stat, *stat32, address);
3839edb01d11SGordon Tetlow 		CP(*stat, *stat32, size);
3840edb01d11SGordon Tetlow 		bcopy(&stat->pathname[0], &stat32->pathname[0],
3841edb01d11SGordon Tetlow 		    sizeof(stat->pathname));
3842fb441a88SKonstantin Belousov 		stat32->version  = version;
3843edb01d11SGordon Tetlow 		error = copyout(stat32, uap->stat, version);
3844edb01d11SGordon Tetlow 	}
3845edb01d11SGordon Tetlow 	free(stat, M_TEMP);
3846edb01d11SGordon Tetlow 	free(stat32, M_TEMP);
384786665509SKonstantin Belousov 	return (error);
384886665509SKonstantin Belousov }
3849d91f88f7SMatthew D Fleming 
3850d91f88f7SMatthew D Fleming int
freebsd32_posix_fallocate(struct thread * td,struct freebsd32_posix_fallocate_args * uap)3851d91f88f7SMatthew D Fleming freebsd32_posix_fallocate(struct thread *td,
3852d91f88f7SMatthew D Fleming     struct freebsd32_posix_fallocate_args *uap)
3853d91f88f7SMatthew D Fleming {
38540acf5d0bSMark Johnston 	int error;
3855d91f88f7SMatthew D Fleming 
38560acf5d0bSMark Johnston 	error = kern_posix_fallocate(td, uap->fd,
38572852de04SKonstantin Belousov 	    PAIR32TO64(off_t, uap->offset), PAIR32TO64(off_t, uap->len));
38580acf5d0bSMark Johnston 	return (kern_posix_error(td, error));
3859d91f88f7SMatthew D Fleming }
3860936c09acSJohn Baldwin 
3861936c09acSJohn Baldwin int
freebsd32_posix_fadvise(struct thread * td,struct freebsd32_posix_fadvise_args * uap)3862936c09acSJohn Baldwin freebsd32_posix_fadvise(struct thread *td,
3863936c09acSJohn Baldwin     struct freebsd32_posix_fadvise_args *uap)
3864936c09acSJohn Baldwin {
38650acf5d0bSMark Johnston 	int error;
3866936c09acSJohn Baldwin 
38670acf5d0bSMark Johnston 	error = kern_posix_fadvise(td, uap->fd, PAIR32TO64(off_t, uap->offset),
38680acf5d0bSMark Johnston 	    PAIR32TO64(off_t, uap->len), uap->advice);
38690acf5d0bSMark Johnston 	return (kern_posix_error(td, error));
3870936c09acSJohn Baldwin }
387197319989SKonstantin Belousov 
387297319989SKonstantin Belousov int
convert_sigevent32(struct sigevent32 * sig32,struct sigevent * sig)387397319989SKonstantin Belousov convert_sigevent32(struct sigevent32 *sig32, struct sigevent *sig)
387497319989SKonstantin Belousov {
387597319989SKonstantin Belousov 
387697319989SKonstantin Belousov 	CP(*sig32, *sig, sigev_notify);
387797319989SKonstantin Belousov 	switch (sig->sigev_notify) {
387897319989SKonstantin Belousov 	case SIGEV_NONE:
387997319989SKonstantin Belousov 		break;
388097319989SKonstantin Belousov 	case SIGEV_THREAD_ID:
388197319989SKonstantin Belousov 		CP(*sig32, *sig, sigev_notify_thread_id);
388297319989SKonstantin Belousov 		/* FALLTHROUGH */
388397319989SKonstantin Belousov 	case SIGEV_SIGNAL:
388497319989SKonstantin Belousov 		CP(*sig32, *sig, sigev_signo);
388597319989SKonstantin Belousov 		PTRIN_CP(*sig32, *sig, sigev_value.sival_ptr);
388697319989SKonstantin Belousov 		break;
388797319989SKonstantin Belousov 	case SIGEV_KEVENT:
388897319989SKonstantin Belousov 		CP(*sig32, *sig, sigev_notify_kqueue);
388997319989SKonstantin Belousov 		CP(*sig32, *sig, sigev_notify_kevent_flags);
389097319989SKonstantin Belousov 		PTRIN_CP(*sig32, *sig, sigev_value.sival_ptr);
389197319989SKonstantin Belousov 		break;
389297319989SKonstantin Belousov 	default:
389397319989SKonstantin Belousov 		return (EINVAL);
389497319989SKonstantin Belousov 	}
389597319989SKonstantin Belousov 	return (0);
389697319989SKonstantin Belousov }
389755648840SJohn Baldwin 
389855648840SJohn Baldwin int
freebsd32_procctl(struct thread * td,struct freebsd32_procctl_args * uap)389955648840SJohn Baldwin freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
390055648840SJohn Baldwin {
390155648840SJohn Baldwin 	void *data;
3902237623b0SKonstantin Belousov 	union {
3903237623b0SKonstantin Belousov 		struct procctl_reaper_status rs;
3904237623b0SKonstantin Belousov 		struct procctl_reaper_pids rp;
3905237623b0SKonstantin Belousov 		struct procctl_reaper_kill rk;
3906237623b0SKonstantin Belousov 	} x;
3907237623b0SKonstantin Belousov 	union {
3908237623b0SKonstantin Belousov 		struct procctl_reaper_pids32 rp;
3909237623b0SKonstantin Belousov 	} x32;
3910b9408863SKonstantin Belousov 	int error, error1, flags, signum;
391155648840SJohn Baldwin 
3912fd8d844fSKonstantin Belousov 	if (uap->com >= PROC_PROCCTL_MD_MIN)
3913fd8d844fSKonstantin Belousov 		return (cpu_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id),
3914fd8d844fSKonstantin Belousov 		    uap->com, PTRIN(uap->data)));
3915fd8d844fSKonstantin Belousov 
391655648840SJohn Baldwin 	switch (uap->com) {
3917fa50a355SKonstantin Belousov 	case PROC_ASLR_CTL:
39185dc7e31aSKonstantin Belousov 	case PROC_PROTMAX_CTL:
391955648840SJohn Baldwin 	case PROC_SPROTECT:
3920fe69291fSKonstantin Belousov 	case PROC_STACKGAP_CTL:
3921677258f7SKonstantin Belousov 	case PROC_TRACE_CTL:
3922643f6f47SKonstantin Belousov 	case PROC_TRAPCAP_CTL:
3923db8d680eSEdward Tomasz Napierala 	case PROC_NO_NEW_PRIVS_CTL:
3924796a8e1aSKonstantin Belousov 	case PROC_WXMAP_CTL:
3925dabf006aSKyle Evans 	case PROC_LOGSIGEXIT_CTL:
392655648840SJohn Baldwin 		error = copyin(PTRIN(uap->data), &flags, sizeof(flags));
3927237623b0SKonstantin Belousov 		if (error != 0)
392855648840SJohn Baldwin 			return (error);
392955648840SJohn Baldwin 		data = &flags;
393055648840SJohn Baldwin 		break;
3931237623b0SKonstantin Belousov 	case PROC_REAP_ACQUIRE:
3932237623b0SKonstantin Belousov 	case PROC_REAP_RELEASE:
3933237623b0SKonstantin Belousov 		if (uap->data != NULL)
3934237623b0SKonstantin Belousov 			return (EINVAL);
3935237623b0SKonstantin Belousov 		data = NULL;
3936237623b0SKonstantin Belousov 		break;
3937237623b0SKonstantin Belousov 	case PROC_REAP_STATUS:
3938237623b0SKonstantin Belousov 		data = &x.rs;
3939237623b0SKonstantin Belousov 		break;
3940237623b0SKonstantin Belousov 	case PROC_REAP_GETPIDS:
3941237623b0SKonstantin Belousov 		error = copyin(uap->data, &x32.rp, sizeof(x32.rp));
3942237623b0SKonstantin Belousov 		if (error != 0)
3943237623b0SKonstantin Belousov 			return (error);
3944237623b0SKonstantin Belousov 		CP(x32.rp, x.rp, rp_count);
3945237623b0SKonstantin Belousov 		PTRIN_CP(x32.rp, x.rp, rp_pids);
3946237623b0SKonstantin Belousov 		data = &x.rp;
3947237623b0SKonstantin Belousov 		break;
3948237623b0SKonstantin Belousov 	case PROC_REAP_KILL:
3949237623b0SKonstantin Belousov 		error = copyin(uap->data, &x.rk, sizeof(x.rk));
3950237623b0SKonstantin Belousov 		if (error != 0)
3951237623b0SKonstantin Belousov 			return (error);
3952237623b0SKonstantin Belousov 		data = &x.rk;
3953237623b0SKonstantin Belousov 		break;
3954fa50a355SKonstantin Belousov 	case PROC_ASLR_STATUS:
39555dc7e31aSKonstantin Belousov 	case PROC_PROTMAX_STATUS:
3956fe69291fSKonstantin Belousov 	case PROC_STACKGAP_STATUS:
3957677258f7SKonstantin Belousov 	case PROC_TRACE_STATUS:
3958643f6f47SKonstantin Belousov 	case PROC_TRAPCAP_STATUS:
3959db8d680eSEdward Tomasz Napierala 	case PROC_NO_NEW_PRIVS_STATUS:
3960796a8e1aSKonstantin Belousov 	case PROC_WXMAP_STATUS:
3961dabf006aSKyle Evans 	case PROC_LOGSIGEXIT_STATUS:
3962677258f7SKonstantin Belousov 		data = &flags;
3963677258f7SKonstantin Belousov 		break;
39641302eea7SKonstantin Belousov 	case PROC_PDEATHSIG_CTL:
3965b9408863SKonstantin Belousov 		error = copyin(uap->data, &signum, sizeof(signum));
3966b9408863SKonstantin Belousov 		if (error != 0)
3967b9408863SKonstantin Belousov 			return (error);
3968b9408863SKonstantin Belousov 		data = &signum;
3969b9408863SKonstantin Belousov 		break;
39701302eea7SKonstantin Belousov 	case PROC_PDEATHSIG_STATUS:
3971b9408863SKonstantin Belousov 		data = &signum;
3972b9408863SKonstantin Belousov 		break;
397355648840SJohn Baldwin 	default:
397455648840SJohn Baldwin 		return (EINVAL);
397555648840SJohn Baldwin 	}
3976237623b0SKonstantin Belousov 	error = kern_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id),
3977237623b0SKonstantin Belousov 	    uap->com, data);
3978237623b0SKonstantin Belousov 	switch (uap->com) {
3979237623b0SKonstantin Belousov 	case PROC_REAP_STATUS:
3980237623b0SKonstantin Belousov 		if (error == 0)
3981237623b0SKonstantin Belousov 			error = copyout(&x.rs, uap->data, sizeof(x.rs));
3982237623b0SKonstantin Belousov 		break;
3983237623b0SKonstantin Belousov 	case PROC_REAP_KILL:
3984237623b0SKonstantin Belousov 		error1 = copyout(&x.rk, uap->data, sizeof(x.rk));
3985237623b0SKonstantin Belousov 		if (error == 0)
3986237623b0SKonstantin Belousov 			error = error1;
3987237623b0SKonstantin Belousov 		break;
3988fa50a355SKonstantin Belousov 	case PROC_ASLR_STATUS:
39895dc7e31aSKonstantin Belousov 	case PROC_PROTMAX_STATUS:
3990fe69291fSKonstantin Belousov 	case PROC_STACKGAP_STATUS:
3991677258f7SKonstantin Belousov 	case PROC_TRACE_STATUS:
3992643f6f47SKonstantin Belousov 	case PROC_TRAPCAP_STATUS:
3993db8d680eSEdward Tomasz Napierala 	case PROC_NO_NEW_PRIVS_STATUS:
3994796a8e1aSKonstantin Belousov 	case PROC_WXMAP_STATUS:
3995dabf006aSKyle Evans 	case PROC_LOGSIGEXIT_STATUS:
3996677258f7SKonstantin Belousov 		if (error == 0)
3997677258f7SKonstantin Belousov 			error = copyout(&flags, uap->data, sizeof(flags));
3998677258f7SKonstantin Belousov 		break;
39991302eea7SKonstantin Belousov 	case PROC_PDEATHSIG_STATUS:
4000b9408863SKonstantin Belousov 		if (error == 0)
4001b9408863SKonstantin Belousov 			error = copyout(&signum, uap->data, sizeof(signum));
4002b9408863SKonstantin Belousov 		break;
4003237623b0SKonstantin Belousov 	}
4004237623b0SKonstantin Belousov 	return (error);
400555648840SJohn Baldwin }
40068fbeebf5SKonstantin Belousov 
40078fbeebf5SKonstantin Belousov int
freebsd32_fcntl(struct thread * td,struct freebsd32_fcntl_args * uap)40088fbeebf5SKonstantin Belousov freebsd32_fcntl(struct thread *td, struct freebsd32_fcntl_args *uap)
40098fbeebf5SKonstantin Belousov {
4010d0efabdfSBrooks Davis 	intptr_t tmp;
40118fbeebf5SKonstantin Belousov 
40128fbeebf5SKonstantin Belousov 	switch (uap->cmd) {
40138fbeebf5SKonstantin Belousov 	/*
40148fbeebf5SKonstantin Belousov 	 * Do unsigned conversion for arg when operation
40158fbeebf5SKonstantin Belousov 	 * interprets it as flags or pointer.
40168fbeebf5SKonstantin Belousov 	 */
40178fbeebf5SKonstantin Belousov 	case F_SETLK_REMOTE:
40188fbeebf5SKonstantin Belousov 	case F_SETLKW:
40198fbeebf5SKonstantin Belousov 	case F_SETLK:
40208fbeebf5SKonstantin Belousov 	case F_GETLK:
40218fbeebf5SKonstantin Belousov 	case F_SETFD:
40228fbeebf5SKonstantin Belousov 	case F_SETFL:
4023b53fc49cSKonstantin Belousov 	case F_OGETLK:
4024b53fc49cSKonstantin Belousov 	case F_OSETLK:
4025b53fc49cSKonstantin Belousov 	case F_OSETLKW:
4026794d3e8eSKonstantin Belousov 	case F_KINFO:
40278fbeebf5SKonstantin Belousov 		tmp = (unsigned int)(uap->arg);
40288fbeebf5SKonstantin Belousov 		break;
40298fbeebf5SKonstantin Belousov 	default:
40308fbeebf5SKonstantin Belousov 		tmp = uap->arg;
40318fbeebf5SKonstantin Belousov 		break;
40328fbeebf5SKonstantin Belousov 	}
4033f69261f2SKonstantin Belousov 	return (kern_fcntl_freebsd(td, uap->fd, uap->cmd, tmp));
40348fbeebf5SKonstantin Belousov }
4035186d9c34SDmitry Chagin 
4036186d9c34SDmitry Chagin int
freebsd32_ppoll(struct thread * td,struct freebsd32_ppoll_args * uap)4037186d9c34SDmitry Chagin freebsd32_ppoll(struct thread *td, struct freebsd32_ppoll_args *uap)
4038186d9c34SDmitry Chagin {
4039186d9c34SDmitry Chagin 	struct timespec32 ts32;
4040186d9c34SDmitry Chagin 	struct timespec ts, *tsp;
4041186d9c34SDmitry Chagin 	sigset_t set, *ssp;
4042186d9c34SDmitry Chagin 	int error;
4043186d9c34SDmitry Chagin 
4044186d9c34SDmitry Chagin 	if (uap->ts != NULL) {
4045186d9c34SDmitry Chagin 		error = copyin(uap->ts, &ts32, sizeof(ts32));
4046186d9c34SDmitry Chagin 		if (error != 0)
4047186d9c34SDmitry Chagin 			return (error);
4048186d9c34SDmitry Chagin 		CP(ts32, ts, tv_sec);
4049186d9c34SDmitry Chagin 		CP(ts32, ts, tv_nsec);
4050186d9c34SDmitry Chagin 		tsp = &ts;
4051186d9c34SDmitry Chagin 	} else
4052186d9c34SDmitry Chagin 		tsp = NULL;
4053186d9c34SDmitry Chagin 	if (uap->set != NULL) {
4054186d9c34SDmitry Chagin 		error = copyin(uap->set, &set, sizeof(set));
4055186d9c34SDmitry Chagin 		if (error != 0)
4056186d9c34SDmitry Chagin 			return (error);
4057186d9c34SDmitry Chagin 		ssp = &set;
4058186d9c34SDmitry Chagin 	} else
4059186d9c34SDmitry Chagin 		ssp = NULL;
4060186d9c34SDmitry Chagin 
4061186d9c34SDmitry Chagin 	return (kern_poll(td, uap->fds, uap->nfds, tsp, ssp));
4062186d9c34SDmitry Chagin }
40633de1e9aaSKonstantin Belousov 
40643de1e9aaSKonstantin Belousov int
freebsd32_sched_rr_get_interval(struct thread * td,struct freebsd32_sched_rr_get_interval_args * uap)40653de1e9aaSKonstantin Belousov freebsd32_sched_rr_get_interval(struct thread *td,
40663de1e9aaSKonstantin Belousov     struct freebsd32_sched_rr_get_interval_args *uap)
40673de1e9aaSKonstantin Belousov {
40683de1e9aaSKonstantin Belousov 	struct timespec ts;
40693de1e9aaSKonstantin Belousov 	struct timespec32 ts32;
40703de1e9aaSKonstantin Belousov 	int error;
40713de1e9aaSKonstantin Belousov 
40723de1e9aaSKonstantin Belousov 	error = kern_sched_rr_get_interval(td, uap->pid, &ts);
40733de1e9aaSKonstantin Belousov 	if (error == 0) {
40743de1e9aaSKonstantin Belousov 		CP(ts, ts32, tv_sec);
40753de1e9aaSKonstantin Belousov 		CP(ts, ts32, tv_nsec);
40763de1e9aaSKonstantin Belousov 		error = copyout(&ts32, uap->interval, sizeof(ts32));
40773de1e9aaSKonstantin Belousov 	}
40783de1e9aaSKonstantin Belousov 	return (error);
40793de1e9aaSKonstantin Belousov }
408031df9c26SKonstantin Belousov 
408131df9c26SKonstantin Belousov static void
timex_to_32(struct timex32 * dst,struct timex * src)408231df9c26SKonstantin Belousov timex_to_32(struct timex32 *dst, struct timex *src)
408331df9c26SKonstantin Belousov {
408431df9c26SKonstantin Belousov 	CP(*src, *dst, modes);
408531df9c26SKonstantin Belousov 	CP(*src, *dst, offset);
408631df9c26SKonstantin Belousov 	CP(*src, *dst, freq);
408731df9c26SKonstantin Belousov 	CP(*src, *dst, maxerror);
408831df9c26SKonstantin Belousov 	CP(*src, *dst, esterror);
408931df9c26SKonstantin Belousov 	CP(*src, *dst, status);
409031df9c26SKonstantin Belousov 	CP(*src, *dst, constant);
409131df9c26SKonstantin Belousov 	CP(*src, *dst, precision);
409231df9c26SKonstantin Belousov 	CP(*src, *dst, tolerance);
409331df9c26SKonstantin Belousov 	CP(*src, *dst, ppsfreq);
409431df9c26SKonstantin Belousov 	CP(*src, *dst, jitter);
409531df9c26SKonstantin Belousov 	CP(*src, *dst, shift);
409631df9c26SKonstantin Belousov 	CP(*src, *dst, stabil);
409731df9c26SKonstantin Belousov 	CP(*src, *dst, jitcnt);
409831df9c26SKonstantin Belousov 	CP(*src, *dst, calcnt);
409931df9c26SKonstantin Belousov 	CP(*src, *dst, errcnt);
410031df9c26SKonstantin Belousov 	CP(*src, *dst, stbcnt);
410131df9c26SKonstantin Belousov }
410231df9c26SKonstantin Belousov 
410331df9c26SKonstantin Belousov static void
timex_from_32(struct timex * dst,struct timex32 * src)410431df9c26SKonstantin Belousov timex_from_32(struct timex *dst, struct timex32 *src)
410531df9c26SKonstantin Belousov {
410631df9c26SKonstantin Belousov 	CP(*src, *dst, modes);
410731df9c26SKonstantin Belousov 	CP(*src, *dst, offset);
410831df9c26SKonstantin Belousov 	CP(*src, *dst, freq);
410931df9c26SKonstantin Belousov 	CP(*src, *dst, maxerror);
411031df9c26SKonstantin Belousov 	CP(*src, *dst, esterror);
411131df9c26SKonstantin Belousov 	CP(*src, *dst, status);
411231df9c26SKonstantin Belousov 	CP(*src, *dst, constant);
411331df9c26SKonstantin Belousov 	CP(*src, *dst, precision);
411431df9c26SKonstantin Belousov 	CP(*src, *dst, tolerance);
411531df9c26SKonstantin Belousov 	CP(*src, *dst, ppsfreq);
411631df9c26SKonstantin Belousov 	CP(*src, *dst, jitter);
411731df9c26SKonstantin Belousov 	CP(*src, *dst, shift);
411831df9c26SKonstantin Belousov 	CP(*src, *dst, stabil);
411931df9c26SKonstantin Belousov 	CP(*src, *dst, jitcnt);
412031df9c26SKonstantin Belousov 	CP(*src, *dst, calcnt);
412131df9c26SKonstantin Belousov 	CP(*src, *dst, errcnt);
412231df9c26SKonstantin Belousov 	CP(*src, *dst, stbcnt);
412331df9c26SKonstantin Belousov }
412431df9c26SKonstantin Belousov 
412531df9c26SKonstantin Belousov int
freebsd32_ntp_adjtime(struct thread * td,struct freebsd32_ntp_adjtime_args * uap)412631df9c26SKonstantin Belousov freebsd32_ntp_adjtime(struct thread *td, struct freebsd32_ntp_adjtime_args *uap)
412731df9c26SKonstantin Belousov {
412831df9c26SKonstantin Belousov 	struct timex tx;
412931df9c26SKonstantin Belousov 	struct timex32 tx32;
413031df9c26SKonstantin Belousov 	int error, retval;
413131df9c26SKonstantin Belousov 
413231df9c26SKonstantin Belousov 	error = copyin(uap->tp, &tx32, sizeof(tx32));
413331df9c26SKonstantin Belousov 	if (error == 0) {
413431df9c26SKonstantin Belousov 		timex_from_32(&tx, &tx32);
413531df9c26SKonstantin Belousov 		error = kern_ntp_adjtime(td, &tx, &retval);
413631df9c26SKonstantin Belousov 		if (error == 0) {
413731df9c26SKonstantin Belousov 			timex_to_32(&tx32, &tx);
413831df9c26SKonstantin Belousov 			error = copyout(&tx32, uap->tp, sizeof(tx32));
413931df9c26SKonstantin Belousov 			if (error == 0)
414031df9c26SKonstantin Belousov 				td->td_retval[0] = retval;
414131df9c26SKonstantin Belousov 		}
414231df9c26SKonstantin Belousov 	}
414331df9c26SKonstantin Belousov 	return (error);
414431df9c26SKonstantin Belousov }
41450dc332bfSKa Ho Ng 
4146e3e811a3SBrooks Davis #ifdef FFCLOCK
4147e3e811a3SBrooks Davis extern struct mtx ffclock_mtx;
4148e3e811a3SBrooks Davis extern struct ffclock_estimate ffclock_estimate;
4149e3e811a3SBrooks Davis extern int8_t ffclock_updated;
4150e3e811a3SBrooks Davis 
4151e3e811a3SBrooks Davis int
freebsd32_ffclock_setestimate(struct thread * td,struct freebsd32_ffclock_setestimate_args * uap)4152e3e811a3SBrooks Davis freebsd32_ffclock_setestimate(struct thread *td,
4153e3e811a3SBrooks Davis     struct freebsd32_ffclock_setestimate_args *uap)
4154e3e811a3SBrooks Davis {
4155e3e811a3SBrooks Davis 	struct ffclock_estimate cest;
4156e3e811a3SBrooks Davis 	struct ffclock_estimate32 cest32;
4157e3e811a3SBrooks Davis 	int error;
4158e3e811a3SBrooks Davis 
4159e3e811a3SBrooks Davis 	/* Reuse of PRIV_CLOCK_SETTIME. */
4160e3e811a3SBrooks Davis 	if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0)
4161e3e811a3SBrooks Davis 		return (error);
4162e3e811a3SBrooks Davis 
4163e3e811a3SBrooks Davis 	if ((error = copyin(uap->cest, &cest32,
4164e3e811a3SBrooks Davis 	    sizeof(struct ffclock_estimate32))) != 0)
4165e3e811a3SBrooks Davis 		return (error);
4166e3e811a3SBrooks Davis 
4167e3e811a3SBrooks Davis 	CP(cest.update_time, cest32.update_time, sec);
4168e3e811a3SBrooks Davis 	memcpy(&cest.update_time.frac, &cest32.update_time.frac, sizeof(uint64_t));
4169e3e811a3SBrooks Davis 	CP(cest, cest32, update_ffcount);
4170e3e811a3SBrooks Davis 	CP(cest, cest32, leapsec_next);
4171e3e811a3SBrooks Davis 	CP(cest, cest32, period);
4172e3e811a3SBrooks Davis 	CP(cest, cest32, errb_abs);
4173e3e811a3SBrooks Davis 	CP(cest, cest32, errb_rate);
4174e3e811a3SBrooks Davis 	CP(cest, cest32, status);
4175e3e811a3SBrooks Davis 	CP(cest, cest32, leapsec_total);
4176e3e811a3SBrooks Davis 	CP(cest, cest32, leapsec);
4177e3e811a3SBrooks Davis 
4178e3e811a3SBrooks Davis 	mtx_lock(&ffclock_mtx);
4179e3e811a3SBrooks Davis 	memcpy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate));
4180e3e811a3SBrooks Davis 	ffclock_updated++;
4181e3e811a3SBrooks Davis 	mtx_unlock(&ffclock_mtx);
4182e3e811a3SBrooks Davis 	return (error);
4183e3e811a3SBrooks Davis }
4184e3e811a3SBrooks Davis 
4185e3e811a3SBrooks Davis int
freebsd32_ffclock_getestimate(struct thread * td,struct freebsd32_ffclock_getestimate_args * uap)4186e3e811a3SBrooks Davis freebsd32_ffclock_getestimate(struct thread *td,
4187e3e811a3SBrooks Davis     struct freebsd32_ffclock_getestimate_args *uap)
4188e3e811a3SBrooks Davis {
4189e3e811a3SBrooks Davis 	struct ffclock_estimate cest;
4190e3e811a3SBrooks Davis 	struct ffclock_estimate32 cest32;
4191e3e811a3SBrooks Davis 	int error;
4192e3e811a3SBrooks Davis 
4193e3e811a3SBrooks Davis 	mtx_lock(&ffclock_mtx);
4194e3e811a3SBrooks Davis 	memcpy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate));
4195e3e811a3SBrooks Davis 	mtx_unlock(&ffclock_mtx);
4196e3e811a3SBrooks Davis 
4197e3e811a3SBrooks Davis 	CP(cest32.update_time, cest.update_time, sec);
4198e3e811a3SBrooks Davis 	memcpy(&cest32.update_time.frac, &cest.update_time.frac, sizeof(uint64_t));
4199e3e811a3SBrooks Davis 	CP(cest32, cest, update_ffcount);
4200e3e811a3SBrooks Davis 	CP(cest32, cest, leapsec_next);
4201e3e811a3SBrooks Davis 	CP(cest32, cest, period);
4202e3e811a3SBrooks Davis 	CP(cest32, cest, errb_abs);
4203e3e811a3SBrooks Davis 	CP(cest32, cest, errb_rate);
4204e3e811a3SBrooks Davis 	CP(cest32, cest, status);
4205e3e811a3SBrooks Davis 	CP(cest32, cest, leapsec_total);
4206e3e811a3SBrooks Davis 	CP(cest32, cest, leapsec);
4207e3e811a3SBrooks Davis 
4208e3e811a3SBrooks Davis 	error = copyout(&cest32, uap->cest, sizeof(struct ffclock_estimate32));
4209e3e811a3SBrooks Davis 	return (error);
4210e3e811a3SBrooks Davis }
4211e3e811a3SBrooks Davis #else /* !FFCLOCK */
4212e3e811a3SBrooks Davis int
freebsd32_ffclock_setestimate(struct thread * td,struct freebsd32_ffclock_setestimate_args * uap)4213e3e811a3SBrooks Davis freebsd32_ffclock_setestimate(struct thread *td,
4214e3e811a3SBrooks Davis     struct freebsd32_ffclock_setestimate_args *uap)
4215e3e811a3SBrooks Davis {
4216e3e811a3SBrooks Davis 	return (ENOSYS);
4217e3e811a3SBrooks Davis }
4218e3e811a3SBrooks Davis 
4219e3e811a3SBrooks Davis int
freebsd32_ffclock_getestimate(struct thread * td,struct freebsd32_ffclock_getestimate_args * uap)4220e3e811a3SBrooks Davis freebsd32_ffclock_getestimate(struct thread *td,
4221e3e811a3SBrooks Davis     struct freebsd32_ffclock_getestimate_args *uap)
4222e3e811a3SBrooks Davis {
4223e3e811a3SBrooks Davis 	return (ENOSYS);
4224e3e811a3SBrooks Davis }
4225e3e811a3SBrooks Davis #endif /* FFCLOCK */
4226e3e811a3SBrooks Davis 
4227f19e3fd2SBrooks Davis #ifdef COMPAT_43
4228f19e3fd2SBrooks Davis int
ofreebsd32_sethostid(struct thread * td,struct ofreebsd32_sethostid_args * uap)4229f19e3fd2SBrooks Davis ofreebsd32_sethostid(struct thread *td, struct ofreebsd32_sethostid_args *uap)
4230f19e3fd2SBrooks Davis {
4231f19e3fd2SBrooks Davis 	int name[] = { CTL_KERN, KERN_HOSTID };
4232f19e3fd2SBrooks Davis 	long hostid;
4233f19e3fd2SBrooks Davis 
4234f19e3fd2SBrooks Davis 	hostid = uap->hostid;
4235f19e3fd2SBrooks Davis 	return (kernel_sysctl(td, name, nitems(name), NULL, NULL, &hostid,
4236f19e3fd2SBrooks Davis 	    sizeof(hostid), NULL, 0));
4237f19e3fd2SBrooks Davis }
4238f19e3fd2SBrooks Davis #endif
4239ddb3eb4eSOlivier Certner 
4240ddb3eb4eSOlivier Certner int
freebsd32_setcred(struct thread * td,struct freebsd32_setcred_args * uap)4241ddb3eb4eSOlivier Certner freebsd32_setcred(struct thread *td, struct freebsd32_setcred_args *uap)
4242ddb3eb4eSOlivier Certner {
4243ddb3eb4eSOlivier Certner 	/* Last argument is 'is_32bit'. */
4244ddb3eb4eSOlivier Certner 	return (user_setcred(td, uap->flags, uap->wcred, uap->size, true));
4245ddb3eb4eSOlivier Certner }
4246