freebsd32_misc.c revision 147302
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 147302 2005-06-11 14:58:20Z pjd $");
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/namei.h>
39#include <sys/imgact.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>
42#include <sys/malloc.h>
43#include <sys/file.h>		/* Must come after sys/malloc.h */
44#include <sys/mman.h>
45#include <sys/module.h>
46#include <sys/mount.h>
47#include <sys/mutex.h>
48#include <sys/namei.h>
49#include <sys/param.h>
50#include <sys/proc.h>
51#include <sys/reboot.h>
52#include <sys/resource.h>
53#include <sys/resourcevar.h>
54#include <sys/selinfo.h>
55#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
56#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
57#include <sys/signal.h>
58#include <sys/signalvar.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/stat.h>
62#include <sys/syscallsubr.h>
63#include <sys/sysctl.h>
64#include <sys/sysent.h>
65#include <sys/sysproto.h>
66#include <sys/systm.h>
67#include <sys/unistd.h>
68#include <sys/vnode.h>
69#include <sys/wait.h>
70
71#include <vm/vm.h>
72#include <vm/vm_kern.h>
73#include <vm/vm_param.h>
74#include <vm/pmap.h>
75#include <vm/vm_map.h>
76#include <vm/vm_object.h>
77#include <vm/vm_extern.h>
78
79#include <compat/freebsd32/freebsd32_util.h>
80#include <compat/freebsd32/freebsd32.h>
81#include <compat/freebsd32/freebsd32_proto.h>
82
83CTASSERT(sizeof(struct timeval32) == 8);
84CTASSERT(sizeof(struct timespec32) == 8);
85CTASSERT(sizeof(struct statfs32) == 256);
86CTASSERT(sizeof(struct rusage32) == 72);
87
88int
89freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
90{
91	int error, status;
92	struct rusage32 ru32;
93	struct rusage ru, *rup;
94
95	if (uap->rusage != NULL)
96		rup = &ru;
97	else
98		rup = NULL;
99	error = kern_wait(td, uap->pid, &status, uap->options, rup);
100	if (error)
101		return (error);
102	if (uap->status != NULL)
103		error = copyout(&status, uap->status, sizeof(status));
104	if (uap->rusage != NULL && error == 0) {
105		TV_CP(ru, ru32, ru_utime);
106		TV_CP(ru, ru32, ru_stime);
107		CP(ru, ru32, ru_maxrss);
108		CP(ru, ru32, ru_ixrss);
109		CP(ru, ru32, ru_idrss);
110		CP(ru, ru32, ru_isrss);
111		CP(ru, ru32, ru_minflt);
112		CP(ru, ru32, ru_majflt);
113		CP(ru, ru32, ru_nswap);
114		CP(ru, ru32, ru_inblock);
115		CP(ru, ru32, ru_oublock);
116		CP(ru, ru32, ru_msgsnd);
117		CP(ru, ru32, ru_msgrcv);
118		CP(ru, ru32, ru_nsignals);
119		CP(ru, ru32, ru_nvcsw);
120		CP(ru, ru32, ru_nivcsw);
121		error = copyout(&ru32, uap->rusage, sizeof(ru32));
122	}
123	return (error);
124}
125
126#ifdef COMPAT_FREEBSD4
127static void
128copy_statfs(struct statfs *in, struct statfs32 *out)
129{
130	CP(*in, *out, f_bsize);
131	CP(*in, *out, f_iosize);
132	CP(*in, *out, f_blocks);
133	CP(*in, *out, f_bfree);
134	CP(*in, *out, f_bavail);
135	CP(*in, *out, f_files);
136	CP(*in, *out, f_ffree);
137	CP(*in, *out, f_fsid);
138	CP(*in, *out, f_owner);
139	CP(*in, *out, f_type);
140	CP(*in, *out, f_flags);
141	CP(*in, *out, f_flags);
142	CP(*in, *out, f_syncwrites);
143	CP(*in, *out, f_asyncwrites);
144	bcopy(in->f_fstypename,
145	      out->f_fstypename, MFSNAMELEN);
146	bcopy(in->f_mntonname,
147	      out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
148	CP(*in, *out, f_syncreads);
149	CP(*in, *out, f_asyncreads);
150	bcopy(in->f_mntfromname,
151	      out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
152}
153#endif
154
155#ifdef COMPAT_FREEBSD4
156int
157freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
158{
159	struct statfs *buf, *sp;
160	struct statfs32 stat32;
161	size_t count, size;
162	int error;
163
164	count = uap->bufsize / sizeof(struct statfs32);
165	size = count * sizeof(struct statfs);
166	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
167	if (size > 0) {
168		count = td->td_retval[0];
169		sp = buf;
170		while (count > 0 && error == 0) {
171			copy_statfs(sp, &stat32);
172			error = copyout(&stat32, uap->buf, sizeof(stat32));
173			sp++;
174			uap->buf++;
175			count--;
176		}
177		free(buf, M_TEMP);
178	}
179	return (error);
180}
181#endif
182
183struct sigaltstack32 {
184	u_int32_t	ss_sp;
185	u_int32_t	ss_size;
186	int		ss_flags;
187};
188
189CTASSERT(sizeof(struct sigaltstack32) == 12);
190
191int
192freebsd32_sigaltstack(struct thread *td,
193		      struct freebsd32_sigaltstack_args *uap)
194{
195	struct sigaltstack32 s32;
196	struct sigaltstack ss, oss, *ssp;
197	int error;
198
199	if (uap->ss != NULL) {
200		error = copyin(uap->ss, &s32, sizeof(s32));
201		if (error)
202			return (error);
203		PTRIN_CP(s32, ss, ss_sp);
204		CP(s32, ss, ss_size);
205		CP(s32, ss, ss_flags);
206		ssp = &ss;
207	} else
208		ssp = NULL;
209	error = kern_sigaltstack(td, ssp, &oss);
210	if (error == 0 && uap->oss != NULL) {
211		PTROUT_CP(oss, s32, ss_sp);
212		CP(oss, s32, ss_size);
213		CP(oss, s32, ss_flags);
214		error = copyout(&s32, uap->oss, sizeof(s32));
215	}
216	return (error);
217}
218
219/*
220 * Custom version of exec_copyin_args() so that we can translate
221 * the pointers.
222 */
223static int
224freebsd32_exec_copyin_args(struct image_args *args, char *fname,
225    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
226{
227	char *argp, *envp;
228	u_int32_t *p32, arg;
229	size_t length;
230	int error;
231
232	bzero(args, sizeof(*args));
233	if (argv == NULL)
234		return (EFAULT);
235
236	/*
237	 * Allocate temporary demand zeroed space for argument and
238	 *	environment strings
239	 */
240	args->buf = (char *) kmem_alloc_wait(exec_map, PATH_MAX + ARG_MAX);
241	if (args->buf == NULL)
242		return (ENOMEM);
243	args->begin_argv = args->buf;
244	args->endp = args->begin_argv;
245	args->stringspace = ARG_MAX;
246
247	args->fname = args->buf + ARG_MAX;
248
249	/*
250	 * Copy the file name.
251	 */
252	error = (segflg == UIO_SYSSPACE) ?
253	    copystr(fname, args->fname, PATH_MAX, &length) :
254	    copyinstr(fname, args->fname, PATH_MAX, &length);
255	if (error != 0)
256		return (error);
257
258	/*
259	 * extract arguments first
260	 */
261	p32 = argv;
262	for (;;) {
263		error = copyin(p32++, &arg, sizeof(arg));
264		if (error)
265			return (error);
266		if (arg == 0)
267			break;
268		argp = PTRIN(arg);
269		error = copyinstr(argp, args->endp, args->stringspace, &length);
270		if (error) {
271			if (error == ENAMETOOLONG)
272				return (E2BIG);
273			else
274				return (error);
275		}
276		args->stringspace -= length;
277		args->endp += length;
278		args->argc++;
279	}
280
281	args->begin_envv = args->endp;
282
283	/*
284	 * extract environment strings
285	 */
286	if (envv) {
287		p32 = envv;
288		for (;;) {
289			error = copyin(p32++, &arg, sizeof(arg));
290			if (error)
291				return (error);
292			if (arg == 0)
293				break;
294			envp = PTRIN(arg);
295			error = copyinstr(envp, args->endp, args->stringspace,
296			    &length);
297			if (error) {
298				if (error == ENAMETOOLONG)
299					return (E2BIG);
300				else
301					return (error);
302			}
303			args->stringspace -= length;
304			args->endp += length;
305			args->envc++;
306		}
307	}
308
309	return (0);
310}
311
312int
313freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
314{
315	struct image_args eargs;
316	int error;
317
318	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
319	    uap->argv, uap->envv);
320	if (error == 0)
321		error = kern_execve(td, &eargs, NULL);
322	exec_free_args(&eargs);
323	return (error);
324}
325
326#ifdef __ia64__
327static int
328freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
329		       int prot, int fd, off_t pos)
330{
331	vm_map_t map;
332	vm_map_entry_t entry;
333	int rv;
334
335	map = &td->td_proc->p_vmspace->vm_map;
336	if (fd != -1)
337		prot |= VM_PROT_WRITE;
338
339	if (vm_map_lookup_entry(map, start, &entry)) {
340		if ((entry->protection & prot) != prot) {
341			rv = vm_map_protect(map,
342					    trunc_page(start),
343					    round_page(end),
344					    entry->protection | prot,
345					    FALSE);
346			if (rv != KERN_SUCCESS)
347				return (EINVAL);
348		}
349	} else {
350		vm_offset_t addr = trunc_page(start);
351		rv = vm_map_find(map, 0, 0,
352				 &addr, PAGE_SIZE, FALSE, prot,
353				 VM_PROT_ALL, 0);
354		if (rv != KERN_SUCCESS)
355			return (EINVAL);
356	}
357
358	if (fd != -1) {
359		struct pread_args r;
360		r.fd = fd;
361		r.buf = (void *) start;
362		r.nbyte = end - start;
363		r.offset = pos;
364		return (pread(td, &r));
365	} else {
366		while (start < end) {
367			subyte((void *) start, 0);
368			start++;
369		}
370		return (0);
371	}
372}
373#endif
374
375int
376freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
377{
378	struct mmap_args ap;
379	vm_offset_t addr = (vm_offset_t) uap->addr;
380	vm_size_t len	 = uap->len;
381	int prot	 = uap->prot;
382	int flags	 = uap->flags;
383	int fd		 = uap->fd;
384	off_t pos	 = (uap->poslo
385			    | ((off_t)uap->poshi << 32));
386#ifdef __ia64__
387	vm_size_t pageoff;
388	int error;
389
390	/*
391	 * Attempt to handle page size hassles.
392	 */
393	pageoff = (pos & PAGE_MASK);
394	if (flags & MAP_FIXED) {
395		vm_offset_t start, end;
396		start = addr;
397		end = addr + len;
398
399		if (start != trunc_page(start)) {
400			error = freebsd32_mmap_partial(td, start,
401						       round_page(start), prot,
402						       fd, pos);
403			if (fd != -1)
404				pos += round_page(start) - start;
405			start = round_page(start);
406		}
407		if (end != round_page(end)) {
408			vm_offset_t t = trunc_page(end);
409			error = freebsd32_mmap_partial(td, t, end,
410						  prot, fd,
411						  pos + t - start);
412			end = trunc_page(end);
413		}
414		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
415			/*
416			 * We can't map this region at all. The specified
417			 * address doesn't have the same alignment as the file
418			 * position. Fake the mapping by simply reading the
419			 * entire region into memory. First we need to make
420			 * sure the region exists.
421			 */
422			vm_map_t map;
423			struct pread_args r;
424			int rv;
425
426			prot |= VM_PROT_WRITE;
427			map = &td->td_proc->p_vmspace->vm_map;
428			rv = vm_map_remove(map, start, end);
429			if (rv != KERN_SUCCESS)
430				return (EINVAL);
431			rv = vm_map_find(map, 0, 0,
432					 &start, end - start, FALSE,
433					 prot, VM_PROT_ALL, 0);
434			if (rv != KERN_SUCCESS)
435				return (EINVAL);
436			r.fd = fd;
437			r.buf = (void *) start;
438			r.nbyte = end - start;
439			r.offset = pos;
440			error = pread(td, &r);
441			if (error)
442				return (error);
443
444			td->td_retval[0] = addr;
445			return (0);
446		}
447		if (end == start) {
448			/*
449			 * After dealing with the ragged ends, there
450			 * might be none left.
451			 */
452			td->td_retval[0] = addr;
453			return (0);
454		}
455		addr = start;
456		len = end - start;
457	}
458#endif
459
460	ap.addr = (void *) addr;
461	ap.len = len;
462	ap.prot = prot;
463	ap.flags = flags;
464	ap.fd = fd;
465	ap.pos = pos;
466
467	return (mmap(td, &ap));
468}
469
470struct itimerval32 {
471	struct timeval32 it_interval;
472	struct timeval32 it_value;
473};
474
475CTASSERT(sizeof(struct itimerval32) == 16);
476
477int
478freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
479{
480	struct itimerval itv, oitv, *itvp;
481	struct itimerval32 i32;
482	int error;
483
484	if (uap->itv != NULL) {
485		error = copyin(uap->itv, &i32, sizeof(i32));
486		if (error)
487			return (error);
488		TV_CP(i32, itv, it_interval);
489		TV_CP(i32, itv, it_value);
490		itvp = &itv;
491	} else
492		itvp = NULL;
493	error = kern_setitimer(td, uap->which, itvp, &oitv);
494	if (error || uap->oitv == NULL)
495		return (error);
496	TV_CP(oitv, i32, it_interval);
497	TV_CP(oitv, i32, it_value);
498	return (copyout(&i32, uap->oitv, sizeof(i32)));
499}
500
501int
502freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
503{
504	struct itimerval itv;
505	struct itimerval32 i32;
506	int error;
507
508	error = kern_getitimer(td, uap->which, &itv);
509	if (error || uap->itv == NULL)
510		return (error);
511	TV_CP(itv, i32, it_interval);
512	TV_CP(itv, i32, it_value);
513	return (copyout(&i32, uap->itv, sizeof(i32)));
514}
515
516int
517freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
518{
519	struct timeval32 tv32;
520	struct timeval tv, *tvp;
521	int error;
522
523	if (uap->tv != NULL) {
524		error = copyin(uap->tv, &tv32, sizeof(tv32));
525		if (error)
526			return (error);
527		CP(tv32, tv, tv_sec);
528		CP(tv32, tv, tv_usec);
529		tvp = &tv;
530	} else
531		tvp = NULL;
532	/*
533	 * XXX big-endian needs to convert the fd_sets too.
534	 * XXX Do pointers need PTRIN()?
535	 */
536	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
537}
538
539struct kevent32 {
540	u_int32_t	ident;		/* identifier for this event */
541	short		filter;		/* filter for event */
542	u_short		flags;
543	u_int		fflags;
544	int32_t		data;
545	u_int32_t	udata;		/* opaque user data identifier */
546};
547
548CTASSERT(sizeof(struct kevent32) == 20);
549static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
550static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
551
552/*
553 * Copy 'count' items into the destination list pointed to by uap->eventlist.
554 */
555static int
556freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
557{
558	struct freebsd32_kevent_args *uap;
559	struct kevent32	ks32[KQ_NEVENTS];
560	int i, error = 0;
561
562	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
563	uap = (struct freebsd32_kevent_args *)arg;
564
565	for (i = 0; i < count; i++) {
566		CP(kevp[i], ks32[i], ident);
567		CP(kevp[i], ks32[i], filter);
568		CP(kevp[i], ks32[i], flags);
569		CP(kevp[i], ks32[i], fflags);
570		CP(kevp[i], ks32[i], data);
571		PTROUT_CP(kevp[i], ks32[i], udata);
572	}
573	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
574	if (error == 0)
575		uap->eventlist += count;
576	return (error);
577}
578
579/*
580 * Copy 'count' items from the list pointed to by uap->changelist.
581 */
582static int
583freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
584{
585	struct freebsd32_kevent_args *uap;
586	struct kevent32	ks32[KQ_NEVENTS];
587	int i, error = 0;
588
589	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
590	uap = (struct freebsd32_kevent_args *)arg;
591
592	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
593	if (error)
594		goto done;
595	uap->changelist += count;
596
597	for (i = 0; i < count; i++) {
598		CP(ks32[i], kevp[i], ident);
599		CP(ks32[i], kevp[i], filter);
600		CP(ks32[i], kevp[i], flags);
601		CP(ks32[i], kevp[i], fflags);
602		CP(ks32[i], kevp[i], data);
603		PTRIN_CP(ks32[i], kevp[i], udata);
604	}
605done:
606	return (error);
607}
608
609int
610freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
611{
612	struct timespec32 ts32;
613	struct timespec ts, *tsp;
614	struct kevent_copyops k_ops = { uap,
615					freebsd32_kevent_copyout,
616					freebsd32_kevent_copyin};
617	int error;
618
619
620	if (uap->timeout) {
621		error = copyin(uap->timeout, &ts32, sizeof(ts32));
622		if (error)
623			return (error);
624		CP(ts32, ts, tv_sec);
625		CP(ts32, ts, tv_nsec);
626		tsp = &ts;
627	} else
628		tsp = NULL;
629	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
630	    &k_ops, tsp);
631	return (error);
632}
633
634int
635freebsd32_gettimeofday(struct thread *td,
636		       struct freebsd32_gettimeofday_args *uap)
637{
638	struct timeval atv;
639	struct timeval32 atv32;
640	struct timezone rtz;
641	int error = 0;
642
643	if (uap->tp) {
644		microtime(&atv);
645		CP(atv, atv32, tv_sec);
646		CP(atv, atv32, tv_usec);
647		error = copyout(&atv32, uap->tp, sizeof (atv32));
648	}
649	if (error == 0 && uap->tzp != NULL) {
650		rtz.tz_minuteswest = tz_minuteswest;
651		rtz.tz_dsttime = tz_dsttime;
652		error = copyout(&rtz, uap->tzp, sizeof (rtz));
653	}
654	return (error);
655}
656
657int
658freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
659{
660	struct rusage32 s32;
661	struct rusage s;
662	int error;
663
664	error = kern_getrusage(td, uap->who, &s);
665	if (error)
666		return (error);
667	if (uap->rusage != NULL) {
668		TV_CP(s, s32, ru_utime);
669		TV_CP(s, s32, ru_stime);
670		CP(s, s32, ru_maxrss);
671		CP(s, s32, ru_ixrss);
672		CP(s, s32, ru_idrss);
673		CP(s, s32, ru_isrss);
674		CP(s, s32, ru_minflt);
675		CP(s, s32, ru_majflt);
676		CP(s, s32, ru_nswap);
677		CP(s, s32, ru_inblock);
678		CP(s, s32, ru_oublock);
679		CP(s, s32, ru_msgsnd);
680		CP(s, s32, ru_msgrcv);
681		CP(s, s32, ru_nsignals);
682		CP(s, s32, ru_nvcsw);
683		CP(s, s32, ru_nivcsw);
684		error = copyout(&s32, uap->rusage, sizeof(s32));
685	}
686	return (error);
687}
688
689struct iovec32 {
690	u_int32_t iov_base;
691	int	iov_len;
692};
693
694CTASSERT(sizeof(struct iovec32) == 8);
695
696static int
697freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
698{
699	struct iovec32 iov32;
700	struct iovec *iov;
701	struct uio *uio;
702	u_int iovlen;
703	int error, i;
704
705	*uiop = NULL;
706	if (iovcnt > UIO_MAXIOV)
707		return (EINVAL);
708	iovlen = iovcnt * sizeof(struct iovec);
709	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
710	iov = (struct iovec *)(uio + 1);
711	for (i = 0; i < iovcnt; i++) {
712		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
713		if (error) {
714			free(uio, M_IOV);
715			return (error);
716		}
717		iov[i].iov_base = PTRIN(iov32.iov_base);
718		iov[i].iov_len = iov32.iov_len;
719	}
720	uio->uio_iov = iov;
721	uio->uio_iovcnt = iovcnt;
722	uio->uio_segflg = UIO_USERSPACE;
723	uio->uio_offset = -1;
724	uio->uio_resid = 0;
725	for (i = 0; i < iovcnt; i++) {
726		if (iov->iov_len > INT_MAX - uio->uio_resid) {
727			free(uio, M_IOV);
728			return (EINVAL);
729		}
730		uio->uio_resid += iov->iov_len;
731		iov++;
732	}
733	*uiop = uio;
734	return (0);
735}
736
737int
738freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
739{
740	struct uio *auio;
741	int error;
742
743	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
744	if (error)
745		return (error);
746	error = kern_readv(td, uap->fd, auio);
747	free(auio, M_IOV);
748	return (error);
749}
750
751int
752freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
753{
754	struct uio *auio;
755	int error;
756
757	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
758	if (error)
759		return (error);
760	error = kern_writev(td, uap->fd, auio);
761	free(auio, M_IOV);
762	return (error);
763}
764
765int
766freebsd32_settimeofday(struct thread *td,
767		       struct freebsd32_settimeofday_args *uap)
768{
769	struct timeval32 tv32;
770	struct timeval tv, *tvp;
771	struct timezone tz, *tzp;
772	int error;
773
774	if (uap->tv) {
775		error = copyin(uap->tv, &tv32, sizeof(tv32));
776		if (error)
777			return (error);
778		CP(tv32, tv, tv_sec);
779		CP(tv32, tv, tv_usec);
780		tvp = &tv;
781	} else
782		tvp = NULL;
783	if (uap->tzp) {
784		error = copyin(uap->tzp, &tz, sizeof(tz));
785		if (error)
786			return (error);
787		tzp = &tz;
788	} else
789		tzp = NULL;
790	return (kern_settimeofday(td, tvp, tzp));
791}
792
793int
794freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
795{
796	struct timeval32 s32[2];
797	struct timeval s[2], *sp;
798	int error;
799
800	if (uap->tptr != NULL) {
801		error = copyin(uap->tptr, s32, sizeof(s32));
802		if (error)
803			return (error);
804		CP(s32[0], s[0], tv_sec);
805		CP(s32[0], s[0], tv_usec);
806		CP(s32[1], s[1], tv_sec);
807		CP(s32[1], s[1], tv_usec);
808		sp = s;
809	} else
810		sp = NULL;
811	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
812}
813
814int
815freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
816{
817	struct timeval32 tv32;
818	struct timeval delta, olddelta, *deltap;
819	int error;
820
821	if (uap->delta) {
822		error = copyin(uap->delta, &tv32, sizeof(tv32));
823		if (error)
824			return (error);
825		CP(tv32, delta, tv_sec);
826		CP(tv32, delta, tv_usec);
827		deltap = &delta;
828	} else
829		deltap = NULL;
830	error = kern_adjtime(td, deltap, &olddelta);
831	if (uap->olddelta && error == 0) {
832		CP(olddelta, tv32, tv_sec);
833		CP(olddelta, tv32, tv_usec);
834		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
835	}
836	return (error);
837}
838
839#ifdef COMPAT_FREEBSD4
840int
841freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
842{
843	struct statfs32 s32;
844	struct statfs s;
845	int error;
846
847	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
848	if (error)
849		return (error);
850	copy_statfs(&s, &s32);
851	return (copyout(&s32, uap->buf, sizeof(s32)));
852}
853#endif
854
855#ifdef COMPAT_FREEBSD4
856int
857freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
858{
859	struct statfs32 s32;
860	struct statfs s;
861	int error;
862
863	error = kern_fstatfs(td, uap->fd, &s);
864	if (error)
865		return (error);
866	copy_statfs(&s, &s32);
867	return (copyout(&s32, uap->buf, sizeof(s32)));
868}
869#endif
870
871#ifdef COMPAT_FREEBSD4
872int
873freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
874{
875	struct statfs32 s32;
876	struct statfs s;
877	fhandle_t fh;
878	int error;
879
880	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
881		return (error);
882	error = kern_fhstatfs(td, fh, &s);
883	if (error)
884		return (error);
885	copy_statfs(&s, &s32);
886	return (copyout(&s32, uap->buf, sizeof(s32)));
887}
888#endif
889
890int
891freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
892{
893	/*
894	 * Vector through to semsys if it is loaded.
895	 */
896	return sysent[169].sy_call(td, uap);
897}
898
899int
900freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
901{
902	/*
903	 * Vector through to msgsys if it is loaded.
904	 */
905	return sysent[170].sy_call(td, uap);
906}
907
908int
909freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
910{
911	/*
912	 * Vector through to shmsys if it is loaded.
913	 */
914	return sysent[171].sy_call(td, uap);
915}
916
917int
918freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
919{
920	struct pread_args ap;
921
922	ap.fd = uap->fd;
923	ap.buf = uap->buf;
924	ap.nbyte = uap->nbyte;
925	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
926	return (pread(td, &ap));
927}
928
929int
930freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
931{
932	struct pwrite_args ap;
933
934	ap.fd = uap->fd;
935	ap.buf = uap->buf;
936	ap.nbyte = uap->nbyte;
937	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
938	return (pwrite(td, &ap));
939}
940
941int
942freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
943{
944	int error;
945	struct lseek_args ap;
946	off_t pos;
947
948	ap.fd = uap->fd;
949	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
950	ap.whence = uap->whence;
951	error = lseek(td, &ap);
952	/* Expand the quad return into two parts for eax and edx */
953	pos = *(off_t *)(td->td_retval);
954	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
955	td->td_retval[1] = pos >> 32;		/* %edx */
956	return error;
957}
958
959int
960freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
961{
962	struct truncate_args ap;
963
964	ap.path = uap->path;
965	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
966	return (truncate(td, &ap));
967}
968
969int
970freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
971{
972	struct ftruncate_args ap;
973
974	ap.fd = uap->fd;
975	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
976	return (ftruncate(td, &ap));
977}
978
979#ifdef COMPAT_FREEBSD4
980int
981freebsd4_freebsd32_sendfile(struct thread *td,
982    struct freebsd4_freebsd32_sendfile_args *uap)
983{
984	struct freebsd4_sendfile_args ap;
985
986	ap.fd = uap->fd;
987	ap.s = uap->s;
988	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
989	ap.nbytes = uap->nbytes;	/* XXX check */
990	ap.hdtr = uap->hdtr;		/* XXX check */
991	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
992	ap.flags = uap->flags;
993	return (freebsd4_sendfile(td, &ap));
994}
995#endif
996
997int
998freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
999{
1000	struct sendfile_args ap;
1001
1002	ap.fd = uap->fd;
1003	ap.s = uap->s;
1004	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1005	ap.nbytes = uap->nbytes;	/* XXX check */
1006	ap.hdtr = uap->hdtr;		/* XXX check */
1007	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1008	ap.flags = uap->flags;
1009	return (sendfile(td, &ap));
1010}
1011
1012struct stat32 {
1013	dev_t	st_dev;
1014	ino_t	st_ino;
1015	mode_t	st_mode;
1016	nlink_t	st_nlink;
1017	uid_t	st_uid;
1018	gid_t	st_gid;
1019	dev_t	st_rdev;
1020	struct timespec32 st_atimespec;
1021	struct timespec32 st_mtimespec;
1022	struct timespec32 st_ctimespec;
1023	off_t	st_size;
1024	int64_t	st_blocks;
1025	u_int32_t st_blksize;
1026	u_int32_t st_flags;
1027	u_int32_t st_gen;
1028	struct timespec32 st_birthtimespec;
1029	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1030	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1031};
1032
1033
1034CTASSERT(sizeof(struct stat32) == 96);
1035
1036static void
1037copy_stat( struct stat *in, struct stat32 *out)
1038{
1039	CP(*in, *out, st_dev);
1040	CP(*in, *out, st_ino);
1041	CP(*in, *out, st_mode);
1042	CP(*in, *out, st_nlink);
1043	CP(*in, *out, st_uid);
1044	CP(*in, *out, st_gid);
1045	CP(*in, *out, st_rdev);
1046	TS_CP(*in, *out, st_atimespec);
1047	TS_CP(*in, *out, st_mtimespec);
1048	TS_CP(*in, *out, st_ctimespec);
1049	CP(*in, *out, st_size);
1050	CP(*in, *out, st_blocks);
1051	CP(*in, *out, st_blksize);
1052	CP(*in, *out, st_flags);
1053	CP(*in, *out, st_gen);
1054}
1055
1056int
1057freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1058{
1059	struct stat sb;
1060	struct stat32 sb32;
1061	int error;
1062
1063	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1064	if (error)
1065		return (error);
1066	copy_stat(&sb, &sb32);
1067	error = copyout(&sb32, uap->ub, sizeof (sb32));
1068	return (error);
1069}
1070
1071int
1072freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1073{
1074	struct stat ub;
1075	struct stat32 ub32;
1076	int error;
1077
1078	error = kern_fstat(td, uap->fd, &ub);
1079	if (error)
1080		return (error);
1081	copy_stat(&ub, &ub32);
1082	error = copyout(&ub32, uap->ub, sizeof(ub32));
1083	return (error);
1084}
1085
1086int
1087freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1088{
1089	struct stat sb;
1090	struct stat32 sb32;
1091	int error;
1092
1093	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1094	if (error)
1095		return (error);
1096	copy_stat(&sb, &sb32);
1097	error = copyout(&sb32, uap->ub, sizeof (sb32));
1098	return (error);
1099}
1100
1101/*
1102 * MPSAFE
1103 */
1104int
1105freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1106{
1107	int error, name[CTL_MAXNAME];
1108	size_t j, oldlen;
1109
1110	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1111		return (EINVAL);
1112 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1113 	if (error)
1114		return (error);
1115	mtx_lock(&Giant);
1116	if (uap->oldlenp)
1117		oldlen = fuword32(uap->oldlenp);
1118	else
1119		oldlen = 0;
1120	error = userland_sysctl(td, name, uap->namelen,
1121		uap->old, &oldlen, 1,
1122		uap->new, uap->newlen, &j, SCTL_MASK32);
1123	if (error && error != ENOMEM)
1124		goto done2;
1125	if (uap->oldlenp)
1126		suword32(uap->oldlenp, j);
1127done2:
1128	mtx_unlock(&Giant);
1129	return (error);
1130}
1131
1132struct sigaction32 {
1133	u_int32_t	sa_u;
1134	int		sa_flags;
1135	sigset_t	sa_mask;
1136};
1137
1138CTASSERT(sizeof(struct sigaction32) == 24);
1139
1140int
1141freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1142{
1143	struct sigaction32 s32;
1144	struct sigaction sa, osa, *sap;
1145	int error;
1146
1147	if (uap->act) {
1148		error = copyin(uap->act, &s32, sizeof(s32));
1149		if (error)
1150			return (error);
1151		sa.sa_handler = PTRIN(s32.sa_u);
1152		CP(s32, sa, sa_flags);
1153		CP(s32, sa, sa_mask);
1154		sap = &sa;
1155	} else
1156		sap = NULL;
1157	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1158	if (error == 0 && uap->oact != NULL) {
1159		s32.sa_u = PTROUT(osa.sa_handler);
1160		CP(osa, s32, sa_flags);
1161		CP(osa, s32, sa_mask);
1162		error = copyout(&s32, uap->oact, sizeof(s32));
1163	}
1164	return (error);
1165}
1166
1167#ifdef COMPAT_FREEBSD4
1168int
1169freebsd4_freebsd32_sigaction(struct thread *td,
1170			     struct freebsd4_freebsd32_sigaction_args *uap)
1171{
1172	struct sigaction32 s32;
1173	struct sigaction sa, osa, *sap;
1174	int error;
1175
1176	if (uap->act) {
1177		error = copyin(uap->act, &s32, sizeof(s32));
1178		if (error)
1179			return (error);
1180		sa.sa_handler = PTRIN(s32.sa_u);
1181		CP(s32, sa, sa_flags);
1182		CP(s32, sa, sa_mask);
1183		sap = &sa;
1184	} else
1185		sap = NULL;
1186	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1187	if (error == 0 && uap->oact != NULL) {
1188		s32.sa_u = PTROUT(osa.sa_handler);
1189		CP(osa, s32, sa_flags);
1190		CP(osa, s32, sa_mask);
1191		error = copyout(&s32, uap->oact, sizeof(s32));
1192	}
1193	return (error);
1194}
1195#endif
1196
1197int
1198freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1199{
1200	struct timespec32 rmt32, rqt32;
1201	struct timespec rmt, rqt;
1202	int error;
1203
1204	error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1205	if (error)
1206		return (error);
1207
1208	CP(rqt32, rqt, tv_sec);
1209	CP(rqt32, rqt, tv_nsec);
1210
1211	if (uap->rmtp &&
1212	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1213		return (EFAULT);
1214	error = kern_nanosleep(td, &rqt, &rmt);
1215	if (error && uap->rmtp) {
1216		int error2;
1217
1218		CP(rmt, rmt32, tv_sec);
1219		CP(rmt, rmt32, tv_nsec);
1220
1221		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1222		if (error2)
1223			error = error2;
1224	}
1225	return (error);
1226}
1227
1228#if 0
1229
1230int
1231freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1232{
1233	int error;
1234	caddr_t sg;
1235	struct yyy32 *p32, s32;
1236	struct yyy *p = NULL, s;
1237
1238	p32 = uap->zzz;
1239	if (p32) {
1240		sg = stackgap_init();
1241		p = stackgap_alloc(&sg, sizeof(struct yyy));
1242		uap->zzz = (struct yyy32 *)p;
1243		error = copyin(p32, &s32, sizeof(s32));
1244		if (error)
1245			return (error);
1246		/* translate in */
1247		error = copyout(&s, p, sizeof(s));
1248		if (error)
1249			return (error);
1250	}
1251	error = xxx(td, (struct xxx_args *) uap);
1252	if (error)
1253		return (error);
1254	if (p32) {
1255		error = copyin(p, &s, sizeof(s));
1256		if (error)
1257			return (error);
1258		/* translate out */
1259		error = copyout(&s32, p32, sizeof(s32));
1260	}
1261	return (error);
1262}
1263
1264#endif
1265