freebsd32_misc.c revision 122253
1/*-
2 * Copyright (c) 2002 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 122253 2003-11-07 21:27:13Z peter $");
29
30#include "opt_compat.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/exec.h>
36#include <sys/fcntl.h>
37#include <sys/filedesc.h>
38#include <sys/imgact.h>
39#include <sys/kernel.h>
40#include <sys/lock.h>
41#include <sys/malloc.h>
42#include <sys/file.h>		/* Must come after sys/malloc.h */
43#include <sys/mman.h>
44#include <sys/module.h>
45#include <sys/mount.h>
46#include <sys/mutex.h>
47#include <sys/namei.h>
48#include <sys/param.h>
49#include <sys/proc.h>
50#include <sys/reboot.h>
51#include <sys/resource.h>
52#include <sys/resourcevar.h>
53#include <sys/selinfo.h>
54#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
55#include <sys/signal.h>
56#include <sys/signalvar.h>
57#include <sys/socket.h>
58#include <sys/socketvar.h>
59#include <sys/stat.h>
60#include <sys/syscallsubr.h>
61#include <sys/sysctl.h>
62#include <sys/sysent.h>
63#include <sys/sysproto.h>
64#include <sys/systm.h>
65#include <sys/unistd.h>
66#include <sys/user.h>
67#include <sys/utsname.h>
68#include <sys/vnode.h>
69
70#include <vm/vm.h>
71#include <vm/vm_kern.h>
72#include <vm/vm_param.h>
73#include <vm/pmap.h>
74#include <vm/vm_map.h>
75#include <vm/vm_object.h>
76#include <vm/vm_extern.h>
77
78#include <compat/freebsd32/freebsd32_util.h>
79#include <compat/freebsd32/freebsd32.h>
80#include <compat/freebsd32/freebsd32_proto.h>
81
82CTASSERT(sizeof(struct timeval32) == 8);
83CTASSERT(sizeof(struct timespec32) == 8);
84CTASSERT(sizeof(struct statfs32) == 256);
85CTASSERT(sizeof(struct rusage32) == 72);
86
87/*
88 * [ taken from the linux emulator ]
89 * Search an alternate path before passing pathname arguments on
90 * to system calls. Useful for keeping a separate 'emulation tree'.
91 *
92 * If cflag is set, we check if an attempt can be made to create
93 * the named file, i.e. we check if the directory it should
94 * be in exists.
95 */
96int
97freebsd32_emul_find(td, sgp, prefix, path, pbuf, cflag)
98	struct thread	*td;
99	caddr_t		*sgp;		/* Pointer to stackgap memory */
100	const char	*prefix;
101	char		*path;
102	char		**pbuf;
103	int		cflag;
104{
105	int			error;
106	size_t			len, sz;
107	char			*buf, *cp, *ptr;
108	struct ucred		*ucred;
109	struct nameidata	nd;
110	struct nameidata	ndroot;
111	struct vattr		vat;
112	struct vattr		vatroot;
113
114	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
115	*pbuf = path;
116
117	for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
118		continue;
119
120	sz = MAXPATHLEN - (ptr - buf);
121
122	/*
123	 * If sgp is not given then the path is already in kernel space
124	 */
125	if (sgp == NULL)
126		error = copystr(path, ptr, sz, &len);
127	else
128		error = copyinstr(path, ptr, sz, &len);
129
130	if (error) {
131		free(buf, M_TEMP);
132		return error;
133	}
134
135	if (*ptr != '/') {
136		free(buf, M_TEMP);
137		return EINVAL;
138	}
139
140	/*
141	 *  We know that there is a / somewhere in this pathname.
142	 *  Search backwards for it, to find the file's parent dir
143	 *  to see if it exists in the alternate tree. If it does,
144	 *  and we want to create a file (cflag is set). We don't
145	 *  need to worry about the root comparison in this case.
146	 */
147
148	if (cflag) {
149		for (cp = &ptr[len] - 1; *cp != '/'; cp--)
150			;
151		*cp = '\0';
152
153		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
154
155		if ((error = namei(&nd)) != 0) {
156			free(buf, M_TEMP);
157			return error;
158		}
159
160		*cp = '/';
161	} else {
162		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
163
164		if ((error = namei(&nd)) != 0) {
165			free(buf, M_TEMP);
166			return error;
167		}
168
169		/*
170		 * We now compare the vnode of the freebsd32_root to the one
171		 * vnode asked. If they resolve to be the same, then we
172		 * ignore the match so that the real root gets used.
173		 * This avoids the problem of traversing "../.." to find the
174		 * root directory and never finding it, because "/" resolves
175		 * to the emulation root directory. This is expensive :-(
176		 */
177		NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE,
178		    freebsd32_emul_path, td);
179
180		if ((error = namei(&ndroot)) != 0) {
181			/* Cannot happen! */
182			free(buf, M_TEMP);
183			vrele(nd.ni_vp);
184			return error;
185		}
186
187		ucred = td->td_ucred;
188		if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
189			goto bad;
190		}
191
192		if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
193		    td)) != 0) {
194			goto bad;
195		}
196
197		if (vat.va_fsid == vatroot.va_fsid &&
198		    vat.va_fileid == vatroot.va_fileid) {
199			error = ENOENT;
200			goto bad;
201		}
202
203	}
204	if (sgp == NULL)
205		*pbuf = buf;
206	else {
207		sz = &ptr[len] - buf;
208		*pbuf = stackgap_alloc(sgp, sz + 1);
209		error = copyout(buf, *pbuf, sz);
210		free(buf, M_TEMP);
211	}
212
213	vrele(nd.ni_vp);
214	if (!cflag)
215		vrele(ndroot.ni_vp);
216
217	return error;
218
219bad:
220	vrele(ndroot.ni_vp);
221	vrele(nd.ni_vp);
222	free(buf, M_TEMP);
223	return error;
224}
225
226int
227freebsd32_open(struct thread *td, struct freebsd32_open_args *uap)
228{
229	caddr_t sg;
230
231	sg = stackgap_init();
232	CHECKALTEXIST(td, &sg, uap->path);
233
234	return open(td, (struct open_args *) uap);
235}
236
237int
238freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
239{
240	int error;
241	caddr_t sg;
242	struct rusage32 *rusage32, ru32;
243	struct rusage *rusage = NULL, ru;
244
245	rusage32 = uap->rusage;
246	if (rusage32) {
247		sg = stackgap_init();
248		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
249		uap->rusage = (struct rusage32 *)rusage;
250	}
251	error = wait4(td, (struct wait_args *)uap);
252	if (error)
253		return (error);
254	if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
255		TV_CP(ru, ru32, ru_utime);
256		TV_CP(ru, ru32, ru_stime);
257		CP(ru, ru32, ru_maxrss);
258		CP(ru, ru32, ru_ixrss);
259		CP(ru, ru32, ru_idrss);
260		CP(ru, ru32, ru_isrss);
261		CP(ru, ru32, ru_minflt);
262		CP(ru, ru32, ru_majflt);
263		CP(ru, ru32, ru_nswap);
264		CP(ru, ru32, ru_inblock);
265		CP(ru, ru32, ru_oublock);
266		CP(ru, ru32, ru_msgsnd);
267		CP(ru, ru32, ru_msgrcv);
268		CP(ru, ru32, ru_nsignals);
269		CP(ru, ru32, ru_nvcsw);
270		CP(ru, ru32, ru_nivcsw);
271		error = copyout(&ru32, rusage32, sizeof(ru32));
272	}
273	return (error);
274}
275
276static void
277copy_statfs(struct statfs *in, struct statfs32 *out)
278{
279	CP(*in, *out, f_bsize);
280	CP(*in, *out, f_iosize);
281	CP(*in, *out, f_blocks);
282	CP(*in, *out, f_bfree);
283	CP(*in, *out, f_bavail);
284	CP(*in, *out, f_files);
285	CP(*in, *out, f_ffree);
286	CP(*in, *out, f_fsid);
287	CP(*in, *out, f_owner);
288	CP(*in, *out, f_type);
289	CP(*in, *out, f_flags);
290	CP(*in, *out, f_flags);
291	CP(*in, *out, f_syncwrites);
292	CP(*in, *out, f_asyncwrites);
293	bcopy(in->f_fstypename,
294	      out->f_fstypename, MFSNAMELEN);
295	bcopy(in->f_mntonname,
296	      out->f_mntonname, MNAMELEN);
297	CP(*in, *out, f_syncreads);
298	CP(*in, *out, f_asyncreads);
299	bcopy(in->f_mntfromname,
300	      out->f_mntfromname, MNAMELEN);
301}
302
303int
304freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)
305{
306	int error;
307	caddr_t sg;
308	struct statfs32 *sp32, stat32;
309	struct statfs *sp = NULL, stat;
310	int maxcount, count, i;
311
312	sp32 = uap->buf;
313	maxcount = uap->bufsize / sizeof(struct statfs32);
314
315	if (sp32) {
316		sg = stackgap_init();
317		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
318		uap->buf = (struct statfs32 *)sp;
319	}
320	error = getfsstat(td, (struct getfsstat_args *) uap);
321	if (sp32 && !error) {
322		count = td->td_retval[0];
323		for (i = 0; i < count; i++) {
324			error = copyin(&sp[i], &stat, sizeof(stat));
325			if (error)
326				return (error);
327			copy_statfs(&stat, &stat32);
328			error = copyout(&stat32, &sp32[i], sizeof(stat32));
329			if (error)
330				return (error);
331		}
332	}
333	return (error);
334}
335
336int
337freebsd32_access(struct thread *td, struct freebsd32_access_args *uap)
338{
339	caddr_t sg;
340
341	sg = stackgap_init();
342	CHECKALTEXIST(td, &sg, uap->path);
343
344	return access(td, (struct access_args *)uap);
345}
346
347int
348freebsd32_chflags(struct thread *td, struct freebsd32_chflags_args *uap)
349{
350	caddr_t sg;
351
352	sg = stackgap_init();
353	CHECKALTEXIST(td, &sg, uap->path);
354
355	return chflags(td, (struct chflags_args *)uap);
356}
357
358struct sigaltstack32 {
359	u_int32_t	ss_sp;
360	u_int32_t	ss_size;
361	int		ss_flags;
362};
363
364CTASSERT(sizeof(struct sigaltstack32) == 12);
365
366int
367freebsd32_sigaltstack(struct thread *td,
368		      struct freebsd32_sigaltstack_args *uap)
369{
370	struct sigaltstack32 s32;
371	struct sigaltstack ss, oss, *ssp;
372	int error;
373
374	if (uap->ss != NULL) {
375		error = copyin(uap->ss, &s32, sizeof(s32));
376		if (error)
377			return (error);
378		PTRIN_CP(s32, ss, ss_sp);
379		CP(s32, ss, ss_size);
380		CP(s32, ss, ss_flags);
381		ssp = &ss;
382	} else
383		ssp = NULL;
384	error = kern_sigaltstack(td, ssp, &oss);
385	if (error == 0 && uap->oss != NULL) {
386		PTROUT_CP(oss, s32, ss_sp);
387		CP(oss, s32, ss_size);
388		CP(oss, s32, ss_flags);
389		error = copyout(&s32, uap->oss, sizeof(s32));
390	}
391	return (error);
392}
393
394int
395freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
396{
397	int error;
398	caddr_t sg;
399	struct execve_args ap;
400	u_int32_t *p32, arg;
401	char **p, *p64;
402	int count;
403
404	sg = stackgap_init();
405	CHECKALTEXIST(td, &sg, uap->fname);
406	ap.fname = uap->fname;
407
408	if (uap->argv) {
409		count = 0;
410		p32 = uap->argv;
411		do {
412			error = copyin(p32++, &arg, sizeof(arg));
413			if (error)
414				return error;
415			count++;
416		} while (arg != 0);
417		p = stackgap_alloc(&sg, count * sizeof(char *));
418		ap.argv = p;
419		p32 = uap->argv;
420		do {
421			error = copyin(p32++, &arg, sizeof(arg));
422			if (error)
423				return error;
424			p64 = PTRIN(arg);
425			error = copyout(&p64, p++, sizeof(p64));
426			if (error)
427				return error;
428		} while (arg != 0);
429	}
430	if (uap->envv) {
431		count = 0;
432		p32 = uap->envv;
433		do {
434			error = copyin(p32++, &arg, sizeof(arg));
435			if (error)
436				return error;
437			count++;
438		} while (arg != 0);
439		p = stackgap_alloc(&sg, count * sizeof(char *));
440		ap.envv = p;
441		p32 = uap->envv;
442		do {
443			error = copyin(p32++, &arg, sizeof(arg));
444			if (error)
445				return error;
446			p64 = PTRIN(arg);
447			error = copyout(&p64, p++, sizeof(p64));
448			if (error)
449				return error;
450		} while (arg != 0);
451	}
452
453	return execve(td, &ap);
454}
455
456#ifdef __ia64__
457static int
458freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
459		       int prot, int fd, off_t pos)
460{
461	vm_map_t map;
462	vm_map_entry_t entry;
463	int rv;
464
465	map = &td->td_proc->p_vmspace->vm_map;
466	if (fd != -1)
467		prot |= VM_PROT_WRITE;
468
469	if (vm_map_lookup_entry(map, start, &entry)) {
470		if ((entry->protection & prot) != prot) {
471			rv = vm_map_protect(map,
472					    trunc_page(start),
473					    round_page(end),
474					    entry->protection | prot,
475					    FALSE);
476			if (rv != KERN_SUCCESS)
477				return (EINVAL);
478		}
479	} else {
480		vm_offset_t addr = trunc_page(start);
481		rv = vm_map_find(map, 0, 0,
482				 &addr, PAGE_SIZE, FALSE, prot,
483				 VM_PROT_ALL, 0);
484		if (rv != KERN_SUCCESS)
485			return (EINVAL);
486	}
487
488	if (fd != -1) {
489		struct pread_args r;
490		r.fd = fd;
491		r.buf = (void *) start;
492		r.nbyte = end - start;
493		r.offset = pos;
494		return (pread(td, &r));
495	} else {
496		while (start < end) {
497			subyte((void *) start, 0);
498			start++;
499		}
500		return (0);
501	}
502}
503#endif
504
505int
506freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
507{
508	struct mmap_args ap;
509	vm_offset_t addr = (vm_offset_t) uap->addr;
510	vm_size_t len	 = uap->len;
511	int prot	 = uap->prot;
512	int flags	 = uap->flags;
513	int fd		 = uap->fd;
514	off_t pos	 = (uap->poslo
515			    | ((off_t)uap->poshi << 32));
516#ifdef __ia64__
517	vm_size_t pageoff;
518	int error;
519
520	/*
521	 * Attempt to handle page size hassles.
522	 */
523	pageoff = (pos & PAGE_MASK);
524	if (flags & MAP_FIXED) {
525		vm_offset_t start, end;
526		start = addr;
527		end = addr + len;
528
529		if (start != trunc_page(start)) {
530			error = freebsd32_mmap_partial(td, start,
531						       round_page(start), prot,
532						       fd, pos);
533			if (fd != -1)
534				pos += round_page(start) - start;
535			start = round_page(start);
536		}
537		if (end != round_page(end)) {
538			vm_offset_t t = trunc_page(end);
539			error = freebsd32_mmap_partial(td, t, end,
540						  prot, fd,
541						  pos + t - start);
542			end = trunc_page(end);
543		}
544		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
545			/*
546			 * We can't map this region at all. The specified
547			 * address doesn't have the same alignment as the file
548			 * position. Fake the mapping by simply reading the
549			 * entire region into memory. First we need to make
550			 * sure the region exists.
551			 */
552			vm_map_t map;
553			struct pread_args r;
554			int rv;
555
556			prot |= VM_PROT_WRITE;
557			map = &td->td_proc->p_vmspace->vm_map;
558			rv = vm_map_remove(map, start, end);
559			if (rv != KERN_SUCCESS)
560				return (EINVAL);
561			rv = vm_map_find(map, 0, 0,
562					 &start, end - start, FALSE,
563					 prot, VM_PROT_ALL, 0);
564			if (rv != KERN_SUCCESS)
565				return (EINVAL);
566			r.fd = fd;
567			r.buf = (void *) start;
568			r.nbyte = end - start;
569			r.offset = pos;
570			error = pread(td, &r);
571			if (error)
572				return (error);
573
574			td->td_retval[0] = addr;
575			return (0);
576		}
577		if (end == start) {
578			/*
579			 * After dealing with the ragged ends, there
580			 * might be none left.
581			 */
582			td->td_retval[0] = addr;
583			return (0);
584		}
585		addr = start;
586		len = end - start;
587	}
588#endif
589
590	ap.addr = (void *) addr;
591	ap.len = len;
592	ap.prot = prot;
593	ap.flags = flags;
594	ap.fd = fd;
595	ap.pos = pos;
596
597	return (mmap(td, &ap));
598}
599
600struct itimerval32 {
601	struct timeval32 it_interval;
602	struct timeval32 it_value;
603};
604
605CTASSERT(sizeof(struct itimerval32) == 16);
606
607int
608freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
609{
610	int error;
611	caddr_t sg;
612	struct itimerval32 *p32, *op32, s32;
613	struct itimerval *p = NULL, *op = NULL, s;
614
615	p32 = uap->itv;
616	if (p32) {
617		sg = stackgap_init();
618		p = stackgap_alloc(&sg, sizeof(struct itimerval));
619		uap->itv = (struct itimerval32 *)p;
620		error = copyin(p32, &s32, sizeof(s32));
621		if (error)
622			return (error);
623		TV_CP(s32, s, it_interval);
624		TV_CP(s32, s, it_value);
625		error = copyout(&s, p, sizeof(s));
626		if (error)
627			return (error);
628	}
629	op32 = uap->oitv;
630	if (op32) {
631		sg = stackgap_init();
632		op = stackgap_alloc(&sg, sizeof(struct itimerval));
633		uap->oitv = (struct itimerval32 *)op;
634	}
635	error = setitimer(td, (struct setitimer_args *) uap);
636	if (error)
637		return (error);
638	if (op32) {
639		error = copyin(op, &s, sizeof(s));
640		if (error)
641			return (error);
642		TV_CP(s, s32, it_interval);
643		TV_CP(s, s32, it_value);
644		error = copyout(&s32, op32, sizeof(s32));
645	}
646	return (error);
647}
648
649int
650freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
651{
652	int error;
653	caddr_t sg;
654	struct timeval32 *p32, s32;
655	struct timeval *p = NULL, s;
656
657	p32 = uap->tv;
658	if (p32) {
659		sg = stackgap_init();
660		p = stackgap_alloc(&sg, sizeof(struct timeval));
661		uap->tv = (struct timeval32 *)p;
662		error = copyin(p32, &s32, sizeof(s32));
663		if (error)
664			return (error);
665		CP(s32, s, tv_sec);
666		CP(s32, s, tv_usec);
667		error = copyout(&s, p, sizeof(s));
668		if (error)
669			return (error);
670	}
671	/*
672	 * XXX big-endian needs to convert the fd_sets too.
673	 */
674	return (select(td, (struct select_args *) uap));
675}
676
677struct kevent32 {
678	u_int32_t	ident;		/* identifier for this event */
679	short		filter;		/* filter for event */
680	u_short		flags;
681	u_int		fflags;
682	int32_t		data;
683	u_int32_t	udata;		/* opaque user data identifier */
684};
685
686CTASSERT(sizeof(struct kevent32) == 20);
687
688int
689freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
690{
691	int error;
692	caddr_t sg;
693	struct timespec32 ts32;
694	struct timespec ts;
695	struct kevent32 ks32;
696	struct kevent *ks;
697	struct kevent_args a;
698	int i;
699
700	sg = stackgap_init();
701
702	a.fd = uap->fd;
703	a.changelist = uap->changelist;
704	a.nchanges = uap->nchanges;
705	a.eventlist = uap->eventlist;
706	a.nevents = uap->nevents;
707	a.timeout = NULL;
708
709	if (uap->timeout) {
710		a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
711		error = copyin(uap->timeout, &ts32, sizeof(ts32));
712		if (error)
713			return (error);
714		CP(ts32, ts, tv_sec);
715		CP(ts32, ts, tv_nsec);
716		error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
717		if (error)
718			return (error);
719	}
720	if (uap->changelist) {
721		a.changelist = (struct kevent *)stackgap_alloc(&sg,
722		    uap->nchanges * sizeof(struct kevent));
723		for (i = 0; i < uap->nchanges; i++) {
724			error = copyin(&uap->changelist[i], &ks32,
725			    sizeof(ks32));
726			if (error)
727				return (error);
728			ks = (struct kevent *)(uintptr_t)&a.changelist[i];
729			CP(ks32, *ks, ident);
730			CP(ks32, *ks, filter);
731			CP(ks32, *ks, flags);
732			CP(ks32, *ks, fflags);
733			CP(ks32, *ks, data);
734			PTRIN_CP(ks32, *ks, udata);
735		}
736	}
737	if (uap->eventlist) {
738		a.eventlist = stackgap_alloc(&sg,
739		    uap->nevents * sizeof(struct kevent));
740	}
741	error = kevent(td, &a);
742	if (uap->eventlist && error > 0) {
743		for (i = 0; i < error; i++) {
744			ks = &a.eventlist[i];
745			CP(*ks, ks32, ident);
746			CP(*ks, ks32, filter);
747			CP(*ks, ks32, flags);
748			CP(*ks, ks32, fflags);
749			CP(*ks, ks32, data);
750			PTROUT_CP(*ks, ks32, udata);
751			error = copyout(&ks32, &uap->eventlist[i],
752			    sizeof(ks32));
753			if (error)
754				return (error);
755		}
756	}
757	return error;
758}
759
760int
761freebsd32_gettimeofday(struct thread *td,
762		       struct freebsd32_gettimeofday_args *uap)
763{
764	int error;
765	caddr_t sg;
766	struct timeval32 *p32, s32;
767	struct timeval *p = NULL, s;
768
769	p32 = uap->tp;
770	if (p32) {
771		sg = stackgap_init();
772		p = stackgap_alloc(&sg, sizeof(struct timeval));
773		uap->tp = (struct timeval32 *)p;
774	}
775	error = gettimeofday(td, (struct gettimeofday_args *) uap);
776	if (error)
777		return (error);
778	if (p32) {
779		error = copyin(p, &s, sizeof(s));
780		if (error)
781			return (error);
782		CP(s, s32, tv_sec);
783		CP(s, s32, tv_usec);
784		error = copyout(&s32, p32, sizeof(s32));
785		if (error)
786			return (error);
787	}
788	return (error);
789}
790
791int
792freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
793{
794	int error;
795	caddr_t sg;
796	struct rusage32 *p32, s32;
797	struct rusage *p = NULL, s;
798
799	p32 = uap->rusage;
800	if (p32) {
801		sg = stackgap_init();
802		p = stackgap_alloc(&sg, sizeof(struct rusage));
803		uap->rusage = (struct rusage32 *)p;
804	}
805	error = getrusage(td, (struct getrusage_args *) uap);
806	if (error)
807		return (error);
808	if (p32) {
809		error = copyin(p, &s, sizeof(s));
810		if (error)
811			return (error);
812		TV_CP(s, s32, ru_utime);
813		TV_CP(s, s32, ru_stime);
814		CP(s, s32, ru_maxrss);
815		CP(s, s32, ru_ixrss);
816		CP(s, s32, ru_idrss);
817		CP(s, s32, ru_isrss);
818		CP(s, s32, ru_minflt);
819		CP(s, s32, ru_majflt);
820		CP(s, s32, ru_nswap);
821		CP(s, s32, ru_inblock);
822		CP(s, s32, ru_oublock);
823		CP(s, s32, ru_msgsnd);
824		CP(s, s32, ru_msgrcv);
825		CP(s, s32, ru_nsignals);
826		CP(s, s32, ru_nvcsw);
827		CP(s, s32, ru_nivcsw);
828		error = copyout(&s32, p32, sizeof(s32));
829	}
830	return (error);
831}
832
833struct iovec32 {
834	u_int32_t iov_base;
835	int	iov_len;
836};
837#define	STACKGAPLEN	400
838
839CTASSERT(sizeof(struct iovec32) == 8);
840
841int
842freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
843{
844	int error, osize, nsize, i;
845	caddr_t sg;
846	struct readv_args /* {
847		syscallarg(int) fd;
848		syscallarg(struct iovec *) iovp;
849		syscallarg(u_int) iovcnt;
850	} */ a;
851	struct iovec32 *oio;
852	struct iovec *nio;
853
854	sg = stackgap_init();
855
856	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
857		return (EINVAL);
858
859	osize = uap->iovcnt * sizeof (struct iovec32);
860	nsize = uap->iovcnt * sizeof (struct iovec);
861
862	oio = malloc(osize, M_TEMP, M_WAITOK);
863	nio = malloc(nsize, M_TEMP, M_WAITOK);
864
865	error = 0;
866	if ((error = copyin(uap->iovp, oio, osize)))
867		goto punt;
868	for (i = 0; i < uap->iovcnt; i++) {
869		nio[i].iov_base = PTRIN(oio[i].iov_base);
870		nio[i].iov_len = oio[i].iov_len;
871	}
872
873	a.fd = uap->fd;
874	a.iovp = stackgap_alloc(&sg, nsize);
875	a.iovcnt = uap->iovcnt;
876
877	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
878		goto punt;
879	error = readv(td, &a);
880
881punt:
882	free(oio, M_TEMP);
883	free(nio, M_TEMP);
884	return (error);
885}
886
887int
888freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
889{
890	int error, i, nsize, osize;
891	caddr_t sg;
892	struct writev_args /* {
893		syscallarg(int) fd;
894		syscallarg(struct iovec *) iovp;
895		syscallarg(u_int) iovcnt;
896	} */ a;
897	struct iovec32 *oio;
898	struct iovec *nio;
899
900	sg = stackgap_init();
901
902	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
903		return (EINVAL);
904
905	osize = uap->iovcnt * sizeof (struct iovec32);
906	nsize = uap->iovcnt * sizeof (struct iovec);
907
908	oio = malloc(osize, M_TEMP, M_WAITOK);
909	nio = malloc(nsize, M_TEMP, M_WAITOK);
910
911	error = 0;
912	if ((error = copyin(uap->iovp, oio, osize)))
913		goto punt;
914	for (i = 0; i < uap->iovcnt; i++) {
915		nio[i].iov_base = PTRIN(oio[i].iov_base);
916		nio[i].iov_len = oio[i].iov_len;
917	}
918
919	a.fd = uap->fd;
920	a.iovp = stackgap_alloc(&sg, nsize);
921	a.iovcnt = uap->iovcnt;
922
923	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
924		goto punt;
925	error = writev(td, &a);
926
927punt:
928	free(oio, M_TEMP);
929	free(nio, M_TEMP);
930	return (error);
931}
932
933int
934freebsd32_settimeofday(struct thread *td,
935		       struct freebsd32_settimeofday_args *uap)
936{
937	int error;
938	caddr_t sg;
939	struct timeval32 *p32, s32;
940	struct timeval *p = NULL, s;
941
942	p32 = uap->tv;
943	if (p32) {
944		sg = stackgap_init();
945		p = stackgap_alloc(&sg, sizeof(struct timeval));
946		uap->tv = (struct timeval32 *)p;
947		error = copyin(p32, &s32, sizeof(s32));
948		if (error)
949			return (error);
950		CP(s32, s, tv_sec);
951		CP(s32, s, tv_usec);
952		error = copyout(&s, p, sizeof(s));
953		if (error)
954			return (error);
955	}
956	return (settimeofday(td, (struct settimeofday_args *) uap));
957}
958
959int
960freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
961{
962	int error;
963	caddr_t sg;
964	struct timeval32 *p32, s32[2];
965	struct timeval *p = NULL, s[2];
966
967	p32 = uap->tptr;
968	if (p32) {
969		sg = stackgap_init();
970		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
971		uap->tptr = (struct timeval32 *)p;
972		error = copyin(p32, s32, sizeof(s32));
973		if (error)
974			return (error);
975		CP(s32[0], s[0], tv_sec);
976		CP(s32[0], s[0], tv_usec);
977		CP(s32[1], s[1], tv_sec);
978		CP(s32[1], s[1], tv_usec);
979		error = copyout(s, p, sizeof(s));
980		if (error)
981			return (error);
982	}
983	return (utimes(td, (struct utimes_args *) uap));
984}
985
986int
987freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
988{
989	int error;
990	caddr_t sg;
991	struct timeval32 *p32, *op32, s32;
992	struct timeval *p = NULL, *op = NULL, s;
993
994	p32 = uap->delta;
995	if (p32) {
996		sg = stackgap_init();
997		p = stackgap_alloc(&sg, sizeof(struct timeval));
998		uap->delta = (struct timeval32 *)p;
999		error = copyin(p32, &s32, sizeof(s32));
1000		if (error)
1001			return (error);
1002		CP(s32, s, tv_sec);
1003		CP(s32, s, tv_usec);
1004		error = copyout(&s, p, sizeof(s));
1005		if (error)
1006			return (error);
1007	}
1008	op32 = uap->olddelta;
1009	if (op32) {
1010		sg = stackgap_init();
1011		op = stackgap_alloc(&sg, sizeof(struct timeval));
1012		uap->olddelta = (struct timeval32 *)op;
1013	}
1014	error = utimes(td, (struct utimes_args *) uap);
1015	if (error)
1016		return error;
1017	if (op32) {
1018		error = copyin(op, &s, sizeof(s));
1019		if (error)
1020			return (error);
1021		CP(s, s32, tv_sec);
1022		CP(s, s32, tv_usec);
1023		error = copyout(&s32, op32, sizeof(s32));
1024	}
1025	return (error);
1026}
1027
1028int
1029freebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap)
1030{
1031	int error;
1032	caddr_t sg;
1033	struct statfs32 *p32, s32;
1034	struct statfs *p = NULL, s;
1035
1036	p32 = uap->buf;
1037	if (p32) {
1038		sg = stackgap_init();
1039		p = stackgap_alloc(&sg, sizeof(struct statfs));
1040		uap->buf = (struct statfs32 *)p;
1041	}
1042	error = statfs(td, (struct statfs_args *) uap);
1043	if (error)
1044		return (error);
1045	if (p32) {
1046		error = copyin(p, &s, sizeof(s));
1047		if (error)
1048			return (error);
1049		copy_statfs(&s, &s32);
1050		error = copyout(&s32, p32, sizeof(s32));
1051	}
1052	return (error);
1053}
1054
1055int
1056freebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap)
1057{
1058	int error;
1059	caddr_t sg;
1060	struct statfs32 *p32, s32;
1061	struct statfs *p = NULL, s;
1062
1063	p32 = uap->buf;
1064	if (p32) {
1065		sg = stackgap_init();
1066		p = stackgap_alloc(&sg, sizeof(struct statfs));
1067		uap->buf = (struct statfs32 *)p;
1068	}
1069	error = fstatfs(td, (struct fstatfs_args *) uap);
1070	if (error)
1071		return (error);
1072	if (p32) {
1073		error = copyin(p, &s, sizeof(s));
1074		if (error)
1075			return (error);
1076		copy_statfs(&s, &s32);
1077		error = copyout(&s32, p32, sizeof(s32));
1078	}
1079	return (error);
1080}
1081
1082int
1083freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1084{
1085	/*
1086	 * Vector through to semsys if it is loaded.
1087	 */
1088	return sysent[169].sy_call(td, uap);
1089}
1090
1091int
1092freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1093{
1094	/*
1095	 * Vector through to msgsys if it is loaded.
1096	 */
1097	return sysent[170].sy_call(td, uap);
1098}
1099
1100int
1101freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1102{
1103	/*
1104	 * Vector through to shmsys if it is loaded.
1105	 */
1106	return sysent[171].sy_call(td, uap);
1107}
1108
1109int
1110freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1111{
1112	struct pread_args ap;
1113
1114	ap.fd = uap->fd;
1115	ap.buf = uap->buf;
1116	ap.nbyte = uap->nbyte;
1117	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1118	return (pread(td, &ap));
1119}
1120
1121int
1122freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1123{
1124	struct pwrite_args ap;
1125
1126	ap.fd = uap->fd;
1127	ap.buf = uap->buf;
1128	ap.nbyte = uap->nbyte;
1129	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1130	return (pwrite(td, &ap));
1131}
1132
1133int
1134freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1135{
1136	int error;
1137	struct lseek_args ap;
1138	off_t pos;
1139
1140	ap.fd = uap->fd;
1141	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1142	ap.whence = uap->whence;
1143	error = lseek(td, &ap);
1144	/* Expand the quad return into two parts for eax and edx */
1145	pos = *(off_t *)(td->td_retval);
1146	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1147	td->td_retval[1] = pos >> 32;		/* %edx */
1148	return error;
1149}
1150
1151int
1152freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1153{
1154	struct truncate_args ap;
1155
1156	ap.path = uap->path;
1157	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1158	return (truncate(td, &ap));
1159}
1160
1161int
1162freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1163{
1164	struct ftruncate_args ap;
1165
1166	ap.fd = uap->fd;
1167	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1168	return (ftruncate(td, &ap));
1169}
1170
1171#ifdef COMPAT_FREEBSD4
1172int
1173freebsd4_freebsd32_sendfile(struct thread *td,
1174    struct freebsd4_freebsd32_sendfile_args *uap)
1175{
1176	struct freebsd4_sendfile_args ap;
1177
1178	ap.fd = uap->fd;
1179	ap.s = uap->s;
1180	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1181	ap.nbytes = uap->nbytes;	/* XXX check */
1182	ap.hdtr = uap->hdtr;		/* XXX check */
1183	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1184	ap.flags = uap->flags;
1185	return (freebsd4_sendfile(td, &ap));
1186}
1187#endif
1188
1189int
1190freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1191{
1192	struct sendfile_args ap;
1193
1194	ap.fd = uap->fd;
1195	ap.s = uap->s;
1196	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1197	ap.nbytes = uap->nbytes;	/* XXX check */
1198	ap.hdtr = uap->hdtr;		/* XXX check */
1199	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1200	ap.flags = uap->flags;
1201	return (sendfile(td, &ap));
1202}
1203
1204struct stat32 {
1205	udev_t	st_dev;
1206	ino_t	st_ino;
1207	mode_t	st_mode;
1208	nlink_t	st_nlink;
1209	uid_t	st_uid;
1210	gid_t	st_gid;
1211	udev_t	st_rdev;
1212	struct timespec32 st_atimespec;
1213	struct timespec32 st_mtimespec;
1214	struct timespec32 st_ctimespec;
1215	off_t	st_size;
1216	int64_t	st_blocks;
1217	u_int32_t st_blksize;
1218	u_int32_t st_flags;
1219	u_int32_t st_gen;
1220	struct timespec32 st_birthtimespec;
1221	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1222	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1223};
1224
1225
1226CTASSERT(sizeof(struct stat32) == 96);
1227
1228static void
1229copy_stat( struct stat *in, struct stat32 *out)
1230{
1231	CP(*in, *out, st_dev);
1232	CP(*in, *out, st_ino);
1233	CP(*in, *out, st_mode);
1234	CP(*in, *out, st_nlink);
1235	CP(*in, *out, st_uid);
1236	CP(*in, *out, st_gid);
1237	CP(*in, *out, st_rdev);
1238	TS_CP(*in, *out, st_atimespec);
1239	TS_CP(*in, *out, st_mtimespec);
1240	TS_CP(*in, *out, st_ctimespec);
1241	CP(*in, *out, st_size);
1242	CP(*in, *out, st_blocks);
1243	CP(*in, *out, st_blksize);
1244	CP(*in, *out, st_flags);
1245	CP(*in, *out, st_gen);
1246}
1247
1248int
1249freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1250{
1251	int error;
1252	caddr_t sg;
1253	struct stat32 *p32, s32;
1254	struct stat *p = NULL, s;
1255
1256	p32 = uap->ub;
1257	if (p32) {
1258		sg = stackgap_init();
1259		p = stackgap_alloc(&sg, sizeof(struct stat));
1260		uap->ub = (struct stat32 *)p;
1261	}
1262	error = stat(td, (struct stat_args *) uap);
1263	if (error)
1264		return (error);
1265	if (p32) {
1266		error = copyin(p, &s, sizeof(s));
1267		if (error)
1268			return (error);
1269		copy_stat(&s, &s32);
1270		error = copyout(&s32, p32, sizeof(s32));
1271	}
1272	return (error);
1273}
1274
1275int
1276freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1277{
1278	int error;
1279	caddr_t sg;
1280	struct stat32 *p32, s32;
1281	struct stat *p = NULL, s;
1282
1283	p32 = uap->ub;
1284	if (p32) {
1285		sg = stackgap_init();
1286		p = stackgap_alloc(&sg, sizeof(struct stat));
1287		uap->ub = (struct stat32 *)p;
1288	}
1289	error = fstat(td, (struct fstat_args *) uap);
1290	if (error)
1291		return (error);
1292	if (p32) {
1293		error = copyin(p, &s, sizeof(s));
1294		if (error)
1295			return (error);
1296		copy_stat(&s, &s32);
1297		error = copyout(&s32, p32, sizeof(s32));
1298	}
1299	return (error);
1300}
1301
1302int
1303freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1304{
1305	int error;
1306	caddr_t sg;
1307	struct stat32 *p32, s32;
1308	struct stat *p = NULL, s;
1309
1310	p32 = uap->ub;
1311	if (p32) {
1312		sg = stackgap_init();
1313		p = stackgap_alloc(&sg, sizeof(struct stat));
1314		uap->ub = (struct stat32 *)p;
1315	}
1316	error = lstat(td, (struct lstat_args *) uap);
1317	if (error)
1318		return (error);
1319	if (p32) {
1320		error = copyin(p, &s, sizeof(s));
1321		if (error)
1322			return (error);
1323		copy_stat(&s, &s32);
1324		error = copyout(&s32, p32, sizeof(s32));
1325	}
1326	return (error);
1327}
1328
1329/*
1330 * MPSAFE
1331 */
1332int
1333freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1334{
1335	int error, name[CTL_MAXNAME];
1336	size_t j, oldlen;
1337
1338	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1339		return (EINVAL);
1340
1341 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1342 	if (error)
1343		return (error);
1344
1345	mtx_lock(&Giant);
1346
1347	if (uap->oldlenp)
1348		oldlen = fuword32(uap->oldlenp);
1349	else
1350		oldlen = 0;
1351	error = userland_sysctl(td, name, uap->namelen,
1352		uap->old, &oldlen, 1,
1353		uap->new, uap->newlen, &j);
1354	if (error && error != ENOMEM)
1355		goto done2;
1356	if (uap->oldlenp) {
1357		suword32(uap->oldlenp, j);
1358	}
1359done2:
1360	mtx_unlock(&Giant);
1361	return (error);
1362}
1363
1364struct sigaction32 {
1365	u_int32_t	sa_u;
1366	int		sa_flags;
1367	sigset_t	sa_mask;
1368};
1369
1370CTASSERT(sizeof(struct sigaction32) == 24);
1371
1372int
1373freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1374{
1375	struct sigaction32 s32;
1376	struct sigaction sa, osa, *sap;
1377	int error;
1378
1379	if (uap->act) {
1380		error = copyin(uap->act, &s32, sizeof(s32));
1381		if (error)
1382			return (error);
1383		sa.sa_handler = PTRIN(s32.sa_u);
1384		CP(s32, sa, sa_flags);
1385		CP(s32, sa, sa_mask);
1386		sap = &sa;
1387	} else
1388		sap = NULL;
1389	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1390	if (error != 0 && uap->oact != NULL) {
1391		s32.sa_u = PTROUT(osa.sa_handler);
1392		CP(osa, s32, sa_flags);
1393		CP(osa, s32, sa_mask);
1394		error = copyout(&s32, uap->oact, sizeof(s32));
1395	}
1396	return (error);
1397}
1398
1399#ifdef COMPAT_FREEBSD4
1400int
1401freebsd4_freebsd32_sigaction(struct thread *td,
1402			     struct freebsd4_freebsd32_sigaction_args *uap)
1403{
1404	struct sigaction32 s32;
1405	struct sigaction sa, osa, *sap;
1406	int error;
1407
1408	if (uap->act) {
1409		error = copyin(uap->act, &s32, sizeof(s32));
1410		if (error)
1411			return (error);
1412		sa.sa_handler = PTRIN(s32.sa_u);
1413		CP(s32, sa, sa_flags);
1414		CP(s32, sa, sa_mask);
1415		sap = &sa;
1416	} else
1417		sap = NULL;
1418	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1419	if (error != 0 && uap->oact != NULL) {
1420		s32.sa_u = PTROUT(osa.sa_handler);
1421		CP(osa, s32, sa_flags);
1422		CP(osa, s32, sa_mask);
1423		error = copyout(&s32, uap->oact, sizeof(s32));
1424	}
1425	return (error);
1426}
1427#endif
1428
1429#if 0
1430
1431int
1432freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1433{
1434	int error;
1435	caddr_t sg;
1436	struct yyy32 *p32, s32;
1437	struct yyy *p = NULL, s;
1438
1439	p32 = uap->zzz;
1440	if (p32) {
1441		sg = stackgap_init();
1442		p = stackgap_alloc(&sg, sizeof(struct yyy));
1443		uap->zzz = (struct yyy32 *)p;
1444		error = copyin(p32, &s32, sizeof(s32));
1445		if (error)
1446			return (error);
1447		/* translate in */
1448		error = copyout(&s, p, sizeof(s));
1449		if (error)
1450			return (error);
1451	}
1452	error = xxx(td, (struct xxx_args *) uap);
1453	if (error)
1454		return (error);
1455	if (p32) {
1456		error = copyin(p, &s, sizeof(s));
1457		if (error)
1458			return (error);
1459		/* translate out */
1460		error = copyout(&s32, p32, sizeof(s32));
1461	}
1462	return (error);
1463}
1464
1465#endif
1466