xref: /freebsd/sys/compat/freebsd32/freebsd32_misc.c (revision 87569f75a91f298c52a71823c04d41cf53c88889)
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$");
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/mbuf.h>
45 #include <sys/mman.h>
46 #include <sys/module.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/namei.h>
50 #include <sys/param.h>
51 #include <sys/proc.h>
52 #include <sys/reboot.h>
53 #include <sys/resource.h>
54 #include <sys/resourcevar.h>
55 #include <sys/selinfo.h>
56 #include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
57 #include <sys/pipe.h>		/* Must come after sys/selinfo.h */
58 #include <sys/signal.h>
59 #include <sys/signalvar.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
62 #include <sys/stat.h>
63 #include <sys/syscall.h>
64 #include <sys/syscallsubr.h>
65 #include <sys/sysctl.h>
66 #include <sys/sysent.h>
67 #include <sys/sysproto.h>
68 #include <sys/systm.h>
69 #include <sys/unistd.h>
70 #include <sys/vnode.h>
71 #include <sys/wait.h>
72 
73 #include <vm/vm.h>
74 #include <vm/vm_kern.h>
75 #include <vm/vm_param.h>
76 #include <vm/pmap.h>
77 #include <vm/vm_map.h>
78 #include <vm/vm_object.h>
79 #include <vm/vm_extern.h>
80 
81 #include <machine/cpu.h>
82 
83 #include <compat/freebsd32/freebsd32_util.h>
84 #include <compat/freebsd32/freebsd32.h>
85 #include <compat/freebsd32/freebsd32_proto.h>
86 
87 CTASSERT(sizeof(struct timeval32) == 8);
88 CTASSERT(sizeof(struct timespec32) == 8);
89 CTASSERT(sizeof(struct statfs32) == 256);
90 CTASSERT(sizeof(struct rusage32) == 72);
91 
92 int
93 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
94 {
95 	int error, status;
96 	struct rusage32 ru32;
97 	struct rusage ru, *rup;
98 
99 	if (uap->rusage != NULL)
100 		rup = &ru;
101 	else
102 		rup = NULL;
103 	error = kern_wait(td, uap->pid, &status, uap->options, rup);
104 	if (error)
105 		return (error);
106 	if (uap->status != NULL)
107 		error = copyout(&status, uap->status, sizeof(status));
108 	if (uap->rusage != NULL && error == 0) {
109 		TV_CP(ru, ru32, ru_utime);
110 		TV_CP(ru, ru32, ru_stime);
111 		CP(ru, ru32, ru_maxrss);
112 		CP(ru, ru32, ru_ixrss);
113 		CP(ru, ru32, ru_idrss);
114 		CP(ru, ru32, ru_isrss);
115 		CP(ru, ru32, ru_minflt);
116 		CP(ru, ru32, ru_majflt);
117 		CP(ru, ru32, ru_nswap);
118 		CP(ru, ru32, ru_inblock);
119 		CP(ru, ru32, ru_oublock);
120 		CP(ru, ru32, ru_msgsnd);
121 		CP(ru, ru32, ru_msgrcv);
122 		CP(ru, ru32, ru_nsignals);
123 		CP(ru, ru32, ru_nvcsw);
124 		CP(ru, ru32, ru_nivcsw);
125 		error = copyout(&ru32, uap->rusage, sizeof(ru32));
126 	}
127 	return (error);
128 }
129 
130 #ifdef COMPAT_FREEBSD4
131 static void
132 copy_statfs(struct statfs *in, struct statfs32 *out)
133 {
134 
135 	bzero(out, sizeof(*out));
136 	CP(*in, *out, f_bsize);
137 	CP(*in, *out, f_iosize);
138 	CP(*in, *out, f_blocks);
139 	CP(*in, *out, f_bfree);
140 	CP(*in, *out, f_bavail);
141 	CP(*in, *out, f_files);
142 	CP(*in, *out, f_ffree);
143 	CP(*in, *out, f_fsid);
144 	CP(*in, *out, f_owner);
145 	CP(*in, *out, f_type);
146 	CP(*in, *out, f_flags);
147 	CP(*in, *out, f_flags);
148 	CP(*in, *out, f_syncwrites);
149 	CP(*in, *out, f_asyncwrites);
150 	strlcpy(out->f_fstypename,
151 	      in->f_fstypename, MFSNAMELEN);
152 	strlcpy(out->f_mntonname,
153 	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
154 	CP(*in, *out, f_syncreads);
155 	CP(*in, *out, f_asyncreads);
156 	strlcpy(out->f_mntfromname,
157 	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
158 }
159 #endif
160 
161 #ifdef COMPAT_FREEBSD4
162 int
163 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
164 {
165 	struct statfs *buf, *sp;
166 	struct statfs32 stat32;
167 	size_t count, size;
168 	int error;
169 
170 	count = uap->bufsize / sizeof(struct statfs32);
171 	size = count * sizeof(struct statfs);
172 	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
173 	if (size > 0) {
174 		count = td->td_retval[0];
175 		sp = buf;
176 		while (count > 0 && error == 0) {
177 			copy_statfs(sp, &stat32);
178 			error = copyout(&stat32, uap->buf, sizeof(stat32));
179 			sp++;
180 			uap->buf++;
181 			count--;
182 		}
183 		free(buf, M_TEMP);
184 	}
185 	return (error);
186 }
187 #endif
188 
189 struct sigaltstack32 {
190 	u_int32_t	ss_sp;
191 	u_int32_t	ss_size;
192 	int		ss_flags;
193 };
194 
195 CTASSERT(sizeof(struct sigaltstack32) == 12);
196 
197 int
198 freebsd32_sigaltstack(struct thread *td,
199 		      struct freebsd32_sigaltstack_args *uap)
200 {
201 	struct sigaltstack32 s32;
202 	struct sigaltstack ss, oss, *ssp;
203 	int error;
204 
205 	if (uap->ss != NULL) {
206 		error = copyin(uap->ss, &s32, sizeof(s32));
207 		if (error)
208 			return (error);
209 		PTRIN_CP(s32, ss, ss_sp);
210 		CP(s32, ss, ss_size);
211 		CP(s32, ss, ss_flags);
212 		ssp = &ss;
213 	} else
214 		ssp = NULL;
215 	error = kern_sigaltstack(td, ssp, &oss);
216 	if (error == 0 && uap->oss != NULL) {
217 		PTROUT_CP(oss, s32, ss_sp);
218 		CP(oss, s32, ss_size);
219 		CP(oss, s32, ss_flags);
220 		error = copyout(&s32, uap->oss, sizeof(s32));
221 	}
222 	return (error);
223 }
224 
225 /*
226  * Custom version of exec_copyin_args() so that we can translate
227  * the pointers.
228  */
229 static int
230 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
231     enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
232 {
233 	char *argp, *envp;
234 	u_int32_t *p32, arg;
235 	size_t length;
236 	int error;
237 
238 	bzero(args, sizeof(*args));
239 	if (argv == NULL)
240 		return (EFAULT);
241 
242 	/*
243 	 * Allocate temporary demand zeroed space for argument and
244 	 *	environment strings
245 	 */
246 	args->buf = (char *) kmem_alloc_wait(exec_map,
247 	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
248 	if (args->buf == NULL)
249 		return (ENOMEM);
250 	args->begin_argv = args->buf;
251 	args->endp = args->begin_argv;
252 	args->stringspace = ARG_MAX;
253 
254 	args->fname = args->buf + ARG_MAX;
255 
256 	/*
257 	 * Copy the file name.
258 	 */
259 	error = (segflg == UIO_SYSSPACE) ?
260 	    copystr(fname, args->fname, PATH_MAX, &length) :
261 	    copyinstr(fname, args->fname, PATH_MAX, &length);
262 	if (error != 0)
263 		goto err_exit;
264 
265 	/*
266 	 * extract arguments first
267 	 */
268 	p32 = argv;
269 	for (;;) {
270 		error = copyin(p32++, &arg, sizeof(arg));
271 		if (error)
272 			goto err_exit;
273 		if (arg == 0)
274 			break;
275 		argp = PTRIN(arg);
276 		error = copyinstr(argp, args->endp, args->stringspace, &length);
277 		if (error) {
278 			if (error == ENAMETOOLONG)
279 				error = E2BIG;
280 			goto err_exit;
281 		}
282 		args->stringspace -= length;
283 		args->endp += length;
284 		args->argc++;
285 	}
286 
287 	args->begin_envv = args->endp;
288 
289 	/*
290 	 * extract environment strings
291 	 */
292 	if (envv) {
293 		p32 = envv;
294 		for (;;) {
295 			error = copyin(p32++, &arg, sizeof(arg));
296 			if (error)
297 				goto err_exit;
298 			if (arg == 0)
299 				break;
300 			envp = PTRIN(arg);
301 			error = copyinstr(envp, args->endp, args->stringspace,
302 			    &length);
303 			if (error) {
304 				if (error == ENAMETOOLONG)
305 					error = E2BIG;
306 				goto err_exit;
307 			}
308 			args->stringspace -= length;
309 			args->endp += length;
310 			args->envc++;
311 		}
312 	}
313 
314 	return (0);
315 
316 err_exit:
317 	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
318 	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
319 	args->buf = NULL;
320 	return (error);
321 }
322 
323 int
324 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
325 {
326 	struct image_args eargs;
327 	int error;
328 
329 	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
330 	    uap->argv, uap->envv);
331 	if (error == 0)
332 		error = kern_execve(td, &eargs, NULL);
333 	return (error);
334 }
335 
336 #ifdef __ia64__
337 static int
338 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
339 		       int prot, int fd, off_t pos)
340 {
341 	vm_map_t map;
342 	vm_map_entry_t entry;
343 	int rv;
344 
345 	map = &td->td_proc->p_vmspace->vm_map;
346 	if (fd != -1)
347 		prot |= VM_PROT_WRITE;
348 
349 	if (vm_map_lookup_entry(map, start, &entry)) {
350 		if ((entry->protection & prot) != prot) {
351 			rv = vm_map_protect(map,
352 					    trunc_page(start),
353 					    round_page(end),
354 					    entry->protection | prot,
355 					    FALSE);
356 			if (rv != KERN_SUCCESS)
357 				return (EINVAL);
358 		}
359 	} else {
360 		vm_offset_t addr = trunc_page(start);
361 		rv = vm_map_find(map, 0, 0,
362 				 &addr, PAGE_SIZE, FALSE, prot,
363 				 VM_PROT_ALL, 0);
364 		if (rv != KERN_SUCCESS)
365 			return (EINVAL);
366 	}
367 
368 	if (fd != -1) {
369 		struct pread_args r;
370 		r.fd = fd;
371 		r.buf = (void *) start;
372 		r.nbyte = end - start;
373 		r.offset = pos;
374 		return (pread(td, &r));
375 	} else {
376 		while (start < end) {
377 			subyte((void *) start, 0);
378 			start++;
379 		}
380 		return (0);
381 	}
382 }
383 #endif
384 
385 int
386 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
387 {
388 	struct mmap_args ap;
389 	vm_offset_t addr = (vm_offset_t) uap->addr;
390 	vm_size_t len	 = uap->len;
391 	int prot	 = uap->prot;
392 	int flags	 = uap->flags;
393 	int fd		 = uap->fd;
394 	off_t pos	 = (uap->poslo
395 			    | ((off_t)uap->poshi << 32));
396 #ifdef __ia64__
397 	vm_size_t pageoff;
398 	int error;
399 
400 	/*
401 	 * Attempt to handle page size hassles.
402 	 */
403 	pageoff = (pos & PAGE_MASK);
404 	if (flags & MAP_FIXED) {
405 		vm_offset_t start, end;
406 		start = addr;
407 		end = addr + len;
408 
409 		mtx_lock(&Giant);
410 		if (start != trunc_page(start)) {
411 			error = freebsd32_mmap_partial(td, start,
412 						       round_page(start), prot,
413 						       fd, pos);
414 			if (fd != -1)
415 				pos += round_page(start) - start;
416 			start = round_page(start);
417 		}
418 		if (end != round_page(end)) {
419 			vm_offset_t t = trunc_page(end);
420 			error = freebsd32_mmap_partial(td, t, end,
421 						  prot, fd,
422 						  pos + t - start);
423 			end = trunc_page(end);
424 		}
425 		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
426 			/*
427 			 * We can't map this region at all. The specified
428 			 * address doesn't have the same alignment as the file
429 			 * position. Fake the mapping by simply reading the
430 			 * entire region into memory. First we need to make
431 			 * sure the region exists.
432 			 */
433 			vm_map_t map;
434 			struct pread_args r;
435 			int rv;
436 
437 			prot |= VM_PROT_WRITE;
438 			map = &td->td_proc->p_vmspace->vm_map;
439 			rv = vm_map_remove(map, start, end);
440 			if (rv != KERN_SUCCESS) {
441 				mtx_unlock(&Giant);
442 				return (EINVAL);
443 			}
444 			rv = vm_map_find(map, 0, 0,
445 					 &start, end - start, FALSE,
446 					 prot, VM_PROT_ALL, 0);
447 			mtx_unlock(&Giant);
448 			if (rv != KERN_SUCCESS)
449 				return (EINVAL);
450 			r.fd = fd;
451 			r.buf = (void *) start;
452 			r.nbyte = end - start;
453 			r.offset = pos;
454 			error = pread(td, &r);
455 			if (error)
456 				return (error);
457 
458 			td->td_retval[0] = addr;
459 			return (0);
460 		}
461 		mtx_unlock(&Giant);
462 		if (end == start) {
463 			/*
464 			 * After dealing with the ragged ends, there
465 			 * might be none left.
466 			 */
467 			td->td_retval[0] = addr;
468 			return (0);
469 		}
470 		addr = start;
471 		len = end - start;
472 	}
473 #endif
474 
475 	ap.addr = (void *) addr;
476 	ap.len = len;
477 	ap.prot = prot;
478 	ap.flags = flags;
479 	ap.fd = fd;
480 	ap.pos = pos;
481 
482 	return (mmap(td, &ap));
483 }
484 
485 struct itimerval32 {
486 	struct timeval32 it_interval;
487 	struct timeval32 it_value;
488 };
489 
490 CTASSERT(sizeof(struct itimerval32) == 16);
491 
492 int
493 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
494 {
495 	struct itimerval itv, oitv, *itvp;
496 	struct itimerval32 i32;
497 	int error;
498 
499 	if (uap->itv != NULL) {
500 		error = copyin(uap->itv, &i32, sizeof(i32));
501 		if (error)
502 			return (error);
503 		TV_CP(i32, itv, it_interval);
504 		TV_CP(i32, itv, it_value);
505 		itvp = &itv;
506 	} else
507 		itvp = NULL;
508 	error = kern_setitimer(td, uap->which, itvp, &oitv);
509 	if (error || uap->oitv == NULL)
510 		return (error);
511 	TV_CP(oitv, i32, it_interval);
512 	TV_CP(oitv, i32, it_value);
513 	return (copyout(&i32, uap->oitv, sizeof(i32)));
514 }
515 
516 int
517 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
518 {
519 	struct itimerval itv;
520 	struct itimerval32 i32;
521 	int error;
522 
523 	error = kern_getitimer(td, uap->which, &itv);
524 	if (error || uap->itv == NULL)
525 		return (error);
526 	TV_CP(itv, i32, it_interval);
527 	TV_CP(itv, i32, it_value);
528 	return (copyout(&i32, uap->itv, sizeof(i32)));
529 }
530 
531 int
532 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
533 {
534 	struct timeval32 tv32;
535 	struct timeval tv, *tvp;
536 	int error;
537 
538 	if (uap->tv != NULL) {
539 		error = copyin(uap->tv, &tv32, sizeof(tv32));
540 		if (error)
541 			return (error);
542 		CP(tv32, tv, tv_sec);
543 		CP(tv32, tv, tv_usec);
544 		tvp = &tv;
545 	} else
546 		tvp = NULL;
547 	/*
548 	 * XXX big-endian needs to convert the fd_sets too.
549 	 * XXX Do pointers need PTRIN()?
550 	 */
551 	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
552 }
553 
554 struct kevent32 {
555 	u_int32_t	ident;		/* identifier for this event */
556 	short		filter;		/* filter for event */
557 	u_short		flags;
558 	u_int		fflags;
559 	int32_t		data;
560 	u_int32_t	udata;		/* opaque user data identifier */
561 };
562 
563 CTASSERT(sizeof(struct kevent32) == 20);
564 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
565 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
566 
567 /*
568  * Copy 'count' items into the destination list pointed to by uap->eventlist.
569  */
570 static int
571 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
572 {
573 	struct freebsd32_kevent_args *uap;
574 	struct kevent32	ks32[KQ_NEVENTS];
575 	int i, error = 0;
576 
577 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
578 	uap = (struct freebsd32_kevent_args *)arg;
579 
580 	for (i = 0; i < count; i++) {
581 		CP(kevp[i], ks32[i], ident);
582 		CP(kevp[i], ks32[i], filter);
583 		CP(kevp[i], ks32[i], flags);
584 		CP(kevp[i], ks32[i], fflags);
585 		CP(kevp[i], ks32[i], data);
586 		PTROUT_CP(kevp[i], ks32[i], udata);
587 	}
588 	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
589 	if (error == 0)
590 		uap->eventlist += count;
591 	return (error);
592 }
593 
594 /*
595  * Copy 'count' items from the list pointed to by uap->changelist.
596  */
597 static int
598 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
599 {
600 	struct freebsd32_kevent_args *uap;
601 	struct kevent32	ks32[KQ_NEVENTS];
602 	int i, error = 0;
603 
604 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
605 	uap = (struct freebsd32_kevent_args *)arg;
606 
607 	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
608 	if (error)
609 		goto done;
610 	uap->changelist += count;
611 
612 	for (i = 0; i < count; i++) {
613 		CP(ks32[i], kevp[i], ident);
614 		CP(ks32[i], kevp[i], filter);
615 		CP(ks32[i], kevp[i], flags);
616 		CP(ks32[i], kevp[i], fflags);
617 		CP(ks32[i], kevp[i], data);
618 		PTRIN_CP(ks32[i], kevp[i], udata);
619 	}
620 done:
621 	return (error);
622 }
623 
624 int
625 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
626 {
627 	struct timespec32 ts32;
628 	struct timespec ts, *tsp;
629 	struct kevent_copyops k_ops = { uap,
630 					freebsd32_kevent_copyout,
631 					freebsd32_kevent_copyin};
632 	int error;
633 
634 
635 	if (uap->timeout) {
636 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
637 		if (error)
638 			return (error);
639 		CP(ts32, ts, tv_sec);
640 		CP(ts32, ts, tv_nsec);
641 		tsp = &ts;
642 	} else
643 		tsp = NULL;
644 	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
645 	    &k_ops, tsp);
646 	return (error);
647 }
648 
649 int
650 freebsd32_gettimeofday(struct thread *td,
651 		       struct freebsd32_gettimeofday_args *uap)
652 {
653 	struct timeval atv;
654 	struct timeval32 atv32;
655 	struct timezone rtz;
656 	int error = 0;
657 
658 	if (uap->tp) {
659 		microtime(&atv);
660 		CP(atv, atv32, tv_sec);
661 		CP(atv, atv32, tv_usec);
662 		error = copyout(&atv32, uap->tp, sizeof (atv32));
663 	}
664 	if (error == 0 && uap->tzp != NULL) {
665 		rtz.tz_minuteswest = tz_minuteswest;
666 		rtz.tz_dsttime = tz_dsttime;
667 		error = copyout(&rtz, uap->tzp, sizeof (rtz));
668 	}
669 	return (error);
670 }
671 
672 int
673 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
674 {
675 	struct rusage32 s32;
676 	struct rusage s;
677 	int error;
678 
679 	error = kern_getrusage(td, uap->who, &s);
680 	if (error)
681 		return (error);
682 	if (uap->rusage != NULL) {
683 		TV_CP(s, s32, ru_utime);
684 		TV_CP(s, s32, ru_stime);
685 		CP(s, s32, ru_maxrss);
686 		CP(s, s32, ru_ixrss);
687 		CP(s, s32, ru_idrss);
688 		CP(s, s32, ru_isrss);
689 		CP(s, s32, ru_minflt);
690 		CP(s, s32, ru_majflt);
691 		CP(s, s32, ru_nswap);
692 		CP(s, s32, ru_inblock);
693 		CP(s, s32, ru_oublock);
694 		CP(s, s32, ru_msgsnd);
695 		CP(s, s32, ru_msgrcv);
696 		CP(s, s32, ru_nsignals);
697 		CP(s, s32, ru_nvcsw);
698 		CP(s, s32, ru_nivcsw);
699 		error = copyout(&s32, uap->rusage, sizeof(s32));
700 	}
701 	return (error);
702 }
703 
704 struct iovec32 {
705 	u_int32_t iov_base;
706 	int	iov_len;
707 };
708 
709 CTASSERT(sizeof(struct iovec32) == 8);
710 
711 static int
712 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
713 {
714 	struct iovec32 iov32;
715 	struct iovec *iov;
716 	struct uio *uio;
717 	u_int iovlen;
718 	int error, i;
719 
720 	*uiop = NULL;
721 	if (iovcnt > UIO_MAXIOV)
722 		return (EINVAL);
723 	iovlen = iovcnt * sizeof(struct iovec);
724 	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
725 	iov = (struct iovec *)(uio + 1);
726 	for (i = 0; i < iovcnt; i++) {
727 		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
728 		if (error) {
729 			free(uio, M_IOV);
730 			return (error);
731 		}
732 		iov[i].iov_base = PTRIN(iov32.iov_base);
733 		iov[i].iov_len = iov32.iov_len;
734 	}
735 	uio->uio_iov = iov;
736 	uio->uio_iovcnt = iovcnt;
737 	uio->uio_segflg = UIO_USERSPACE;
738 	uio->uio_offset = -1;
739 	uio->uio_resid = 0;
740 	for (i = 0; i < iovcnt; i++) {
741 		if (iov->iov_len > INT_MAX - uio->uio_resid) {
742 			free(uio, M_IOV);
743 			return (EINVAL);
744 		}
745 		uio->uio_resid += iov->iov_len;
746 		iov++;
747 	}
748 	*uiop = uio;
749 	return (0);
750 }
751 
752 int
753 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
754 {
755 	struct uio *auio;
756 	int error;
757 
758 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
759 	if (error)
760 		return (error);
761 	error = kern_readv(td, uap->fd, auio);
762 	free(auio, M_IOV);
763 	return (error);
764 }
765 
766 int
767 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
768 {
769 	struct uio *auio;
770 	int error;
771 
772 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
773 	if (error)
774 		return (error);
775 	error = kern_writev(td, uap->fd, auio);
776 	free(auio, M_IOV);
777 	return (error);
778 }
779 
780 int
781 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
782 {
783 	struct uio *auio;
784 	int error;
785 
786 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
787 	if (error)
788 		return (error);
789 	error = kern_preadv(td, uap->fd, auio, uap->offset);
790 	free(auio, M_IOV);
791 	return (error);
792 }
793 
794 int
795 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
796 {
797 	struct uio *auio;
798 	int error;
799 
800 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
801 	if (error)
802 		return (error);
803 	error = kern_pwritev(td, uap->fd, auio, uap->offset);
804 	free(auio, M_IOV);
805 	return (error);
806 }
807 
808 static int
809 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
810     int error)
811 {
812 	struct iovec32 iov32;
813 	struct iovec *iov;
814 	u_int iovlen;
815 	int i;
816 
817 	*iovp = NULL;
818 	if (iovcnt > UIO_MAXIOV)
819 		return (error);
820 	iovlen = iovcnt * sizeof(struct iovec);
821 	iov = malloc(iovlen, M_IOV, M_WAITOK);
822 	for (i = 0; i < iovcnt; i++) {
823 		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
824 		if (error) {
825 			free(iov, M_IOV);
826 			return (error);
827 		}
828 		iov[i].iov_base = PTRIN(iov32.iov_base);
829 		iov[i].iov_len = iov32.iov_len;
830 	}
831 	*iovp = iov;
832 	return (0);
833 }
834 
835 static int
836 freebsd32_copyoutiov(struct iovec *iov, u_int iovcnt, struct iovec32 *iovp,
837     int error)
838 {
839 	struct iovec32 iov32;
840 	int i;
841 
842 	if (iovcnt > UIO_MAXIOV)
843 		return (error);
844 	for (i = 0; i < iovcnt; i++) {
845 		iov32.iov_base = PTROUT(iov[i].iov_base);
846 		iov32.iov_len = iov[i].iov_len;
847 		error = copyout(&iov32, &iovp[i], sizeof(iov32));
848 		if (error)
849 			return (error);
850 	}
851 	return (0);
852 }
853 
854 
855 struct msghdr32 {
856 	u_int32_t	 msg_name;
857 	socklen_t	 msg_namelen;
858 	u_int32_t	 msg_iov;
859 	int		 msg_iovlen;
860 	u_int32_t	 msg_control;
861 	socklen_t	 msg_controllen;
862 	int		 msg_flags;
863 };
864 CTASSERT(sizeof(struct msghdr32) == 28);
865 
866 static int
867 freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
868 {
869 	struct msghdr32 m32;
870 	int error;
871 
872 	error = copyin(msg32, &m32, sizeof(m32));
873 	if (error)
874 		return (error);
875 	msg->msg_name = PTRIN(m32.msg_name);
876 	msg->msg_namelen = m32.msg_namelen;
877 	msg->msg_iov = PTRIN(m32.msg_iov);
878 	msg->msg_iovlen = m32.msg_iovlen;
879 	msg->msg_control = PTRIN(m32.msg_control);
880 	msg->msg_controllen = m32.msg_controllen;
881 	msg->msg_flags = m32.msg_flags;
882 	return (0);
883 }
884 
885 static int
886 freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
887 {
888 	struct msghdr32 m32;
889 	int error;
890 
891 	m32.msg_name = PTROUT(msg->msg_name);
892 	m32.msg_namelen = msg->msg_namelen;
893 	m32.msg_iov = PTROUT(msg->msg_iov);
894 	m32.msg_iovlen = msg->msg_iovlen;
895 	m32.msg_control = PTROUT(msg->msg_control);
896 	m32.msg_controllen = msg->msg_controllen;
897 	m32.msg_flags = msg->msg_flags;
898 	error = copyout(&m32, msg32, sizeof(m32));
899 	return (error);
900 }
901 
902 #define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
903 #define FREEBSD32_ALIGN(p)	\
904 	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
905 #define	FREEBSD32_CMSG_SPACE(l)	\
906 	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
907 
908 #define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
909 				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
910 static int
911 freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
912 {
913 	struct cmsghdr *cm;
914 	void *data;
915 	socklen_t clen, datalen;
916 	int error;
917 	caddr_t ctlbuf;
918 	int len, maxlen, copylen;
919 	struct mbuf *m;
920 	error = 0;
921 
922 	len    = msg->msg_controllen;
923 	maxlen = msg->msg_controllen;
924 	msg->msg_controllen = 0;
925 
926 	m = control;
927 	ctlbuf = msg->msg_control;
928 
929 	while (m && len > 0) {
930 		cm = mtod(m, struct cmsghdr *);
931 		clen = m->m_len;
932 
933 		while (cm != NULL) {
934 
935 			if (sizeof(struct cmsghdr) > clen ||
936 			    cm->cmsg_len > clen) {
937 				error = EINVAL;
938 				break;
939 			}
940 
941 			data   = CMSG_DATA(cm);
942 			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
943 
944 			/* Adjust message length */
945 			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
946 			    datalen;
947 
948 
949 			/* Copy cmsghdr */
950 			copylen = sizeof(struct cmsghdr);
951 			if (len < copylen) {
952 				msg->msg_flags |= MSG_CTRUNC;
953 				copylen = len;
954 			}
955 
956 			error = copyout(cm,ctlbuf,copylen);
957 			if (error)
958 				goto exit;
959 
960 			ctlbuf += FREEBSD32_ALIGN(copylen);
961 			len    -= FREEBSD32_ALIGN(copylen);
962 
963 			if (len <= 0)
964 				break;
965 
966 			/* Copy data */
967 			copylen = datalen;
968 			if (len < copylen) {
969 				msg->msg_flags |= MSG_CTRUNC;
970 				copylen = len;
971 			}
972 
973 			error = copyout(data,ctlbuf,copylen);
974 			if (error)
975 				goto exit;
976 
977 			ctlbuf += FREEBSD32_ALIGN(copylen);
978 			len    -= FREEBSD32_ALIGN(copylen);
979 
980 			if (CMSG_SPACE(datalen) < clen) {
981 				clen -= CMSG_SPACE(datalen);
982 				cm = (struct cmsghdr *)
983 					((caddr_t)cm + CMSG_SPACE(datalen));
984 			} else {
985 				clen = 0;
986 				cm = NULL;
987 			}
988 		}
989 		m = m->m_next;
990 	}
991 
992 	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
993 
994 exit:
995 	return (error);
996 
997 }
998 
999 int
1000 freebsd32_recvmsg(td, uap)
1001 	struct thread *td;
1002 	struct freebsd32_recvmsg_args /* {
1003 		int	s;
1004 		struct	msghdr32 *msg;
1005 		int	flags;
1006 	} */ *uap;
1007 {
1008 	struct msghdr msg;
1009 	struct msghdr32 m32;
1010 	struct iovec *uiov, *iov;
1011 	struct mbuf *control = NULL;
1012 	struct mbuf **controlp;
1013 
1014 	int error;
1015 	error = copyin(uap->msg, &m32, sizeof(m32));
1016 	if (error)
1017 		return (error);
1018 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1019 	if (error)
1020 		return (error);
1021 	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
1022 	    m32.msg_iovlen, &iov, EMSGSIZE);
1023 	if (error)
1024 		return (error);
1025 	msg.msg_flags = uap->flags;
1026 	uiov = msg.msg_iov;
1027 	msg.msg_iov = iov;
1028 
1029 	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1030 	error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp);
1031 	if (error == 0) {
1032 		msg.msg_iov = uiov;
1033 
1034 		if (control != NULL)
1035 			error = freebsd32_copy_msg_out(&msg, control);
1036 
1037 		if (error == 0)
1038 			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1039 
1040 		if (error == 0)
1041 			error = freebsd32_copyoutiov(iov, m32.msg_iovlen,
1042 			    (struct iovec32 *)(uintptr_t)m32.msg_iov, EMSGSIZE);
1043 	}
1044 	free(iov, M_IOV);
1045 
1046 	if (control != NULL)
1047 		m_freem(control);
1048 
1049 	return (error);
1050 }
1051 
1052 
1053 static int
1054 freebsd32_convert_msg_in(struct mbuf **controlp)
1055 {
1056 	struct mbuf *control = *controlp;
1057 	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1058 	void *data;
1059 	socklen_t clen = control->m_len, datalen;
1060 	int error;
1061 
1062 	error = 0;
1063 	*controlp = NULL;
1064 
1065 	while (cm != NULL) {
1066 		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1067 			error = EINVAL;
1068 			break;
1069 		}
1070 
1071 		data = FREEBSD32_CMSG_DATA(cm);
1072 		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1073 
1074 		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1075 		    cm->cmsg_level);
1076 		controlp = &(*controlp)->m_next;
1077 
1078 		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1079 			clen -= FREEBSD32_CMSG_SPACE(datalen);
1080 			cm = (struct cmsghdr *)
1081 				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1082 		} else {
1083 			clen = 0;
1084 			cm = NULL;
1085 		}
1086 	}
1087 
1088 	m_freem(control);
1089 	return (error);
1090 }
1091 
1092 
1093 int
1094 freebsd32_sendmsg(struct thread *td,
1095 		  struct freebsd32_sendmsg_args *uap)
1096 {
1097 	struct msghdr msg;
1098 	struct msghdr32 m32;
1099 	struct iovec *iov;
1100 	struct mbuf *control = NULL;
1101 	struct sockaddr *to = NULL;
1102 	int error;
1103 
1104 	error = copyin(uap->msg, &m32, sizeof(m32));
1105 	if (error)
1106 		return (error);
1107 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1108 	if (error)
1109 		return (error);
1110 	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
1111 	    m32.msg_iovlen, &iov, EMSGSIZE);
1112 	if (error)
1113 		return (error);
1114 	msg.msg_iov = iov;
1115 	if (msg.msg_name != NULL) {
1116 		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1117 		if (error) {
1118 			to = NULL;
1119 			goto out;
1120 		}
1121 		msg.msg_name = to;
1122 	}
1123 
1124 	if (msg.msg_control) {
1125 		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1126 			error = EINVAL;
1127 			goto out;
1128 		}
1129 
1130 		error = sockargs(&control, msg.msg_control,
1131 		    msg.msg_controllen, MT_CONTROL);
1132 		if (error)
1133 			goto out;
1134 
1135 		error = freebsd32_convert_msg_in(&control);
1136 		if (error)
1137 			goto out;
1138 	}
1139 
1140 	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1141 	    UIO_USERSPACE);
1142 
1143 out:
1144 	free(iov, M_IOV);
1145 	if (to)
1146 		free(to, M_SONAME);
1147 	return (error);
1148 }
1149 
1150 int
1151 freebsd32_recvfrom(struct thread *td,
1152 		   struct freebsd32_recvfrom_args *uap)
1153 {
1154 	struct msghdr msg;
1155 	struct iovec aiov;
1156 	int error;
1157 
1158 	if (uap->fromlenaddr) {
1159 		error = copyin((void *)(uintptr_t)uap->fromlenaddr,
1160 		    &msg.msg_namelen, sizeof(msg.msg_namelen));
1161 		if (error)
1162 			return (error);
1163 	} else {
1164 		msg.msg_namelen = 0;
1165 	}
1166 
1167 	msg.msg_name = (void *)(uintptr_t)uap->from;
1168 	msg.msg_iov = &aiov;
1169 	msg.msg_iovlen = 1;
1170 	aiov.iov_base = (void *)(uintptr_t)uap->buf;
1171 	aiov.iov_len = uap->len;
1172 	msg.msg_control = 0;
1173 	msg.msg_flags = uap->flags;
1174 	error = kern_recvit(td, uap->s, &msg,
1175 	    (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE, NULL);
1176 	return (error);
1177 }
1178 
1179 int
1180 freebsd32_settimeofday(struct thread *td,
1181 		       struct freebsd32_settimeofday_args *uap)
1182 {
1183 	struct timeval32 tv32;
1184 	struct timeval tv, *tvp;
1185 	struct timezone tz, *tzp;
1186 	int error;
1187 
1188 	if (uap->tv) {
1189 		error = copyin(uap->tv, &tv32, sizeof(tv32));
1190 		if (error)
1191 			return (error);
1192 		CP(tv32, tv, tv_sec);
1193 		CP(tv32, tv, tv_usec);
1194 		tvp = &tv;
1195 	} else
1196 		tvp = NULL;
1197 	if (uap->tzp) {
1198 		error = copyin(uap->tzp, &tz, sizeof(tz));
1199 		if (error)
1200 			return (error);
1201 		tzp = &tz;
1202 	} else
1203 		tzp = NULL;
1204 	return (kern_settimeofday(td, tvp, tzp));
1205 }
1206 
1207 int
1208 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1209 {
1210 	struct timeval32 s32[2];
1211 	struct timeval s[2], *sp;
1212 	int error;
1213 
1214 	if (uap->tptr != NULL) {
1215 		error = copyin(uap->tptr, s32, sizeof(s32));
1216 		if (error)
1217 			return (error);
1218 		CP(s32[0], s[0], tv_sec);
1219 		CP(s32[0], s[0], tv_usec);
1220 		CP(s32[1], s[1], tv_sec);
1221 		CP(s32[1], s[1], tv_usec);
1222 		sp = s;
1223 	} else
1224 		sp = NULL;
1225 	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1226 }
1227 
1228 int
1229 freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1230 {
1231 	struct timeval32 s32[2];
1232 	struct timeval s[2], *sp;
1233 	int error;
1234 
1235 	if (uap->tptr != NULL) {
1236 		error = copyin(uap->tptr, s32, sizeof(s32));
1237 		if (error)
1238 			return (error);
1239 		CP(s32[0], s[0], tv_sec);
1240 		CP(s32[0], s[0], tv_usec);
1241 		CP(s32[1], s[1], tv_sec);
1242 		CP(s32[1], s[1], tv_usec);
1243 		sp = s;
1244 	} else
1245 		sp = NULL;
1246 	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1247 }
1248 
1249 int
1250 freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1251 {
1252 	struct timeval32 s32[2];
1253 	struct timeval s[2], *sp;
1254 	int error;
1255 
1256 	if (uap->tptr != NULL) {
1257 		error = copyin(uap->tptr, s32, sizeof(s32));
1258 		if (error)
1259 			return (error);
1260 		CP(s32[0], s[0], tv_sec);
1261 		CP(s32[0], s[0], tv_usec);
1262 		CP(s32[1], s[1], tv_sec);
1263 		CP(s32[1], s[1], tv_usec);
1264 		sp = s;
1265 	} else
1266 		sp = NULL;
1267 	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1268 }
1269 
1270 
1271 int
1272 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1273 {
1274 	struct timeval32 tv32;
1275 	struct timeval delta, olddelta, *deltap;
1276 	int error;
1277 
1278 	if (uap->delta) {
1279 		error = copyin(uap->delta, &tv32, sizeof(tv32));
1280 		if (error)
1281 			return (error);
1282 		CP(tv32, delta, tv_sec);
1283 		CP(tv32, delta, tv_usec);
1284 		deltap = &delta;
1285 	} else
1286 		deltap = NULL;
1287 	error = kern_adjtime(td, deltap, &olddelta);
1288 	if (uap->olddelta && error == 0) {
1289 		CP(olddelta, tv32, tv_sec);
1290 		CP(olddelta, tv32, tv_usec);
1291 		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1292 	}
1293 	return (error);
1294 }
1295 
1296 #ifdef COMPAT_FREEBSD4
1297 int
1298 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1299 {
1300 	struct statfs32 s32;
1301 	struct statfs s;
1302 	int error;
1303 
1304 	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1305 	if (error)
1306 		return (error);
1307 	copy_statfs(&s, &s32);
1308 	return (copyout(&s32, uap->buf, sizeof(s32)));
1309 }
1310 #endif
1311 
1312 #ifdef COMPAT_FREEBSD4
1313 int
1314 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1315 {
1316 	struct statfs32 s32;
1317 	struct statfs s;
1318 	int error;
1319 
1320 	error = kern_fstatfs(td, uap->fd, &s);
1321 	if (error)
1322 		return (error);
1323 	copy_statfs(&s, &s32);
1324 	return (copyout(&s32, uap->buf, sizeof(s32)));
1325 }
1326 #endif
1327 
1328 #ifdef COMPAT_FREEBSD4
1329 int
1330 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1331 {
1332 	struct statfs32 s32;
1333 	struct statfs s;
1334 	fhandle_t fh;
1335 	int error;
1336 
1337 	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1338 		return (error);
1339 	error = kern_fhstatfs(td, fh, &s);
1340 	if (error)
1341 		return (error);
1342 	copy_statfs(&s, &s32);
1343 	return (copyout(&s32, uap->buf, sizeof(s32)));
1344 }
1345 #endif
1346 
1347 int
1348 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1349 {
1350 	/*
1351 	 * Vector through to semsys if it is loaded.
1352 	 */
1353 	return sysent[SYS_semsys].sy_call(td, uap);
1354 }
1355 
1356 int
1357 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1358 {
1359 	/*
1360 	 * Vector through to msgsys if it is loaded.
1361 	 */
1362 	return sysent[SYS_msgsys].sy_call(td, uap);
1363 }
1364 
1365 int
1366 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1367 {
1368 	/*
1369 	 * Vector through to shmsys if it is loaded.
1370 	 */
1371 	return sysent[SYS_shmsys].sy_call(td, uap);
1372 }
1373 
1374 int
1375 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1376 {
1377 	struct pread_args ap;
1378 
1379 	ap.fd = uap->fd;
1380 	ap.buf = uap->buf;
1381 	ap.nbyte = uap->nbyte;
1382 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1383 	return (pread(td, &ap));
1384 }
1385 
1386 int
1387 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1388 {
1389 	struct pwrite_args ap;
1390 
1391 	ap.fd = uap->fd;
1392 	ap.buf = uap->buf;
1393 	ap.nbyte = uap->nbyte;
1394 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1395 	return (pwrite(td, &ap));
1396 }
1397 
1398 int
1399 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1400 {
1401 	int error;
1402 	struct lseek_args ap;
1403 	off_t pos;
1404 
1405 	ap.fd = uap->fd;
1406 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1407 	ap.whence = uap->whence;
1408 	error = lseek(td, &ap);
1409 	/* Expand the quad return into two parts for eax and edx */
1410 	pos = *(off_t *)(td->td_retval);
1411 	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1412 	td->td_retval[1] = pos >> 32;		/* %edx */
1413 	return error;
1414 }
1415 
1416 int
1417 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1418 {
1419 	struct truncate_args ap;
1420 
1421 	ap.path = uap->path;
1422 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1423 	return (truncate(td, &ap));
1424 }
1425 
1426 int
1427 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1428 {
1429 	struct ftruncate_args ap;
1430 
1431 	ap.fd = uap->fd;
1432 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1433 	return (ftruncate(td, &ap));
1434 }
1435 
1436 struct sf_hdtr32 {
1437 	uint32_t headers;
1438 	int hdr_cnt;
1439 	uint32_t trailers;
1440 	int trl_cnt;
1441 };
1442 
1443 static int
1444 freebsd32_do_sendfile(struct thread *td,
1445     struct freebsd32_sendfile_args *uap, int compat)
1446 {
1447 	struct sendfile_args ap;
1448 	struct sf_hdtr32 hdtr32;
1449 	struct sf_hdtr hdtr;
1450 	struct uio *hdr_uio, *trl_uio;
1451 	struct iovec32 *iov32;
1452 	int error;
1453 
1454 	hdr_uio = trl_uio = NULL;
1455 
1456 	ap.fd = uap->fd;
1457 	ap.s = uap->s;
1458 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1459 	ap.nbytes = uap->nbytes;
1460 	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
1461 	ap.sbytes = uap->sbytes;
1462 	ap.flags = uap->flags;
1463 
1464 	if (uap->hdtr != NULL) {
1465 		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1466 		if (error)
1467 			goto out;
1468 		PTRIN_CP(hdtr32, hdtr, headers);
1469 		CP(hdtr32, hdtr, hdr_cnt);
1470 		PTRIN_CP(hdtr32, hdtr, trailers);
1471 		CP(hdtr32, hdtr, trl_cnt);
1472 
1473 		if (hdtr.headers != NULL) {
1474 			iov32 = (struct iovec32 *)(uintptr_t)hdtr32.headers;
1475 			error = freebsd32_copyinuio(iov32,
1476 			    hdtr32.hdr_cnt, &hdr_uio);
1477 			if (error)
1478 				goto out;
1479 		}
1480 		if (hdtr.trailers != NULL) {
1481 			iov32 = (struct iovec32 *)(uintptr_t)hdtr32.trailers;
1482 			error = freebsd32_copyinuio(iov32,
1483 			    hdtr32.trl_cnt, &trl_uio);
1484 			if (error)
1485 				goto out;
1486 		}
1487 	}
1488 
1489 	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1490 out:
1491 	if (hdr_uio)
1492 		free(hdr_uio, M_IOV);
1493 	if (trl_uio)
1494 		free(trl_uio, M_IOV);
1495 	return (error);
1496 }
1497 
1498 #ifdef COMPAT_FREEBSD4
1499 int
1500 freebsd4_freebsd32_sendfile(struct thread *td,
1501     struct freebsd4_freebsd32_sendfile_args *uap)
1502 {
1503 	return (freebsd32_do_sendfile(td,
1504 	    (struct freebsd32_sendfile_args *)uap, 1));
1505 }
1506 #endif
1507 
1508 int
1509 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1510 {
1511 
1512 	return (freebsd32_do_sendfile(td, uap, 0));
1513 }
1514 
1515 struct stat32 {
1516 	dev_t	st_dev;
1517 	ino_t	st_ino;
1518 	mode_t	st_mode;
1519 	nlink_t	st_nlink;
1520 	uid_t	st_uid;
1521 	gid_t	st_gid;
1522 	dev_t	st_rdev;
1523 	struct timespec32 st_atimespec;
1524 	struct timespec32 st_mtimespec;
1525 	struct timespec32 st_ctimespec;
1526 	off_t	st_size;
1527 	int64_t	st_blocks;
1528 	u_int32_t st_blksize;
1529 	u_int32_t st_flags;
1530 	u_int32_t st_gen;
1531 	struct timespec32 st_birthtimespec;
1532 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1533 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1534 };
1535 
1536 
1537 CTASSERT(sizeof(struct stat32) == 96);
1538 
1539 static void
1540 copy_stat( struct stat *in, struct stat32 *out)
1541 {
1542 	CP(*in, *out, st_dev);
1543 	CP(*in, *out, st_ino);
1544 	CP(*in, *out, st_mode);
1545 	CP(*in, *out, st_nlink);
1546 	CP(*in, *out, st_uid);
1547 	CP(*in, *out, st_gid);
1548 	CP(*in, *out, st_rdev);
1549 	TS_CP(*in, *out, st_atimespec);
1550 	TS_CP(*in, *out, st_mtimespec);
1551 	TS_CP(*in, *out, st_ctimespec);
1552 	CP(*in, *out, st_size);
1553 	CP(*in, *out, st_blocks);
1554 	CP(*in, *out, st_blksize);
1555 	CP(*in, *out, st_flags);
1556 	CP(*in, *out, st_gen);
1557 }
1558 
1559 int
1560 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1561 {
1562 	struct stat sb;
1563 	struct stat32 sb32;
1564 	int error;
1565 
1566 	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1567 	if (error)
1568 		return (error);
1569 	copy_stat(&sb, &sb32);
1570 	error = copyout(&sb32, uap->ub, sizeof (sb32));
1571 	return (error);
1572 }
1573 
1574 int
1575 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1576 {
1577 	struct stat ub;
1578 	struct stat32 ub32;
1579 	int error;
1580 
1581 	error = kern_fstat(td, uap->fd, &ub);
1582 	if (error)
1583 		return (error);
1584 	copy_stat(&ub, &ub32);
1585 	error = copyout(&ub32, uap->ub, sizeof(ub32));
1586 	return (error);
1587 }
1588 
1589 int
1590 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1591 {
1592 	struct stat sb;
1593 	struct stat32 sb32;
1594 	int error;
1595 
1596 	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1597 	if (error)
1598 		return (error);
1599 	copy_stat(&sb, &sb32);
1600 	error = copyout(&sb32, uap->ub, sizeof (sb32));
1601 	return (error);
1602 }
1603 
1604 /*
1605  * MPSAFE
1606  */
1607 int
1608 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1609 {
1610 	int error, name[CTL_MAXNAME];
1611 	size_t j, oldlen;
1612 
1613 	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1614 		return (EINVAL);
1615  	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1616  	if (error)
1617 		return (error);
1618 	mtx_lock(&Giant);
1619 	if (uap->oldlenp)
1620 		oldlen = fuword32(uap->oldlenp);
1621 	else
1622 		oldlen = 0;
1623 	error = userland_sysctl(td, name, uap->namelen,
1624 		uap->old, &oldlen, 1,
1625 		uap->new, uap->newlen, &j, SCTL_MASK32);
1626 	if (error && error != ENOMEM)
1627 		goto done2;
1628 	if (uap->oldlenp)
1629 		suword32(uap->oldlenp, j);
1630 done2:
1631 	mtx_unlock(&Giant);
1632 	return (error);
1633 }
1634 
1635 struct sigaction32 {
1636 	u_int32_t	sa_u;
1637 	int		sa_flags;
1638 	sigset_t	sa_mask;
1639 };
1640 
1641 CTASSERT(sizeof(struct sigaction32) == 24);
1642 
1643 int
1644 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1645 {
1646 	struct sigaction32 s32;
1647 	struct sigaction sa, osa, *sap;
1648 	int error;
1649 
1650 	if (uap->act) {
1651 		error = copyin(uap->act, &s32, sizeof(s32));
1652 		if (error)
1653 			return (error);
1654 		sa.sa_handler = PTRIN(s32.sa_u);
1655 		CP(s32, sa, sa_flags);
1656 		CP(s32, sa, sa_mask);
1657 		sap = &sa;
1658 	} else
1659 		sap = NULL;
1660 	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1661 	if (error == 0 && uap->oact != NULL) {
1662 		s32.sa_u = PTROUT(osa.sa_handler);
1663 		CP(osa, s32, sa_flags);
1664 		CP(osa, s32, sa_mask);
1665 		error = copyout(&s32, uap->oact, sizeof(s32));
1666 	}
1667 	return (error);
1668 }
1669 
1670 #ifdef COMPAT_FREEBSD4
1671 int
1672 freebsd4_freebsd32_sigaction(struct thread *td,
1673 			     struct freebsd4_freebsd32_sigaction_args *uap)
1674 {
1675 	struct sigaction32 s32;
1676 	struct sigaction sa, osa, *sap;
1677 	int error;
1678 
1679 	if (uap->act) {
1680 		error = copyin(uap->act, &s32, sizeof(s32));
1681 		if (error)
1682 			return (error);
1683 		sa.sa_handler = PTRIN(s32.sa_u);
1684 		CP(s32, sa, sa_flags);
1685 		CP(s32, sa, sa_mask);
1686 		sap = &sa;
1687 	} else
1688 		sap = NULL;
1689 	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1690 	if (error == 0 && uap->oact != NULL) {
1691 		s32.sa_u = PTROUT(osa.sa_handler);
1692 		CP(osa, s32, sa_flags);
1693 		CP(osa, s32, sa_mask);
1694 		error = copyout(&s32, uap->oact, sizeof(s32));
1695 	}
1696 	return (error);
1697 }
1698 #endif
1699 
1700 #ifdef COMPAT_43
1701 struct osigaction32 {
1702 	u_int32_t	sa_u;
1703 	osigset_t	sa_mask;
1704 	int		sa_flags;
1705 };
1706 
1707 #define	ONSIG	32
1708 
1709 int
1710 ofreebsd32_sigaction(struct thread *td,
1711 			     struct ofreebsd32_sigaction_args *uap)
1712 {
1713 	struct osigaction32 s32;
1714 	struct sigaction sa, osa, *sap;
1715 	int error;
1716 
1717 	if (uap->signum <= 0 || uap->signum >= ONSIG)
1718 		return (EINVAL);
1719 
1720 	if (uap->nsa) {
1721 		error = copyin(uap->nsa, &s32, sizeof(s32));
1722 		if (error)
1723 			return (error);
1724 		sa.sa_handler = PTRIN(s32.sa_u);
1725 		CP(s32, sa, sa_flags);
1726 		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1727 		sap = &sa;
1728 	} else
1729 		sap = NULL;
1730 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1731 	if (error == 0 && uap->osa != NULL) {
1732 		s32.sa_u = PTROUT(osa.sa_handler);
1733 		CP(osa, s32, sa_flags);
1734 		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1735 		error = copyout(&s32, uap->osa, sizeof(s32));
1736 	}
1737 	return (error);
1738 }
1739 
1740 int
1741 ofreebsd32_sigprocmask(struct thread *td,
1742 			       struct ofreebsd32_sigprocmask_args *uap)
1743 {
1744 	sigset_t set, oset;
1745 	int error;
1746 
1747 	OSIG2SIG(uap->mask, set);
1748 	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1749 	SIG2OSIG(oset, td->td_retval[0]);
1750 	return (error);
1751 }
1752 
1753 int
1754 ofreebsd32_sigpending(struct thread *td,
1755 			      struct ofreebsd32_sigpending_args *uap)
1756 {
1757 	struct proc *p = td->td_proc;
1758 	sigset_t siglist;
1759 
1760 	PROC_LOCK(p);
1761 	siglist = p->p_siglist;
1762 	SIGSETOR(siglist, td->td_siglist);
1763 	PROC_UNLOCK(p);
1764 	SIG2OSIG(siglist, td->td_retval[0]);
1765 	return (0);
1766 }
1767 
1768 struct sigvec32 {
1769 	u_int32_t	sv_handler;
1770 	int		sv_mask;
1771 	int		sv_flags;
1772 };
1773 
1774 int
1775 ofreebsd32_sigvec(struct thread *td,
1776 			  struct ofreebsd32_sigvec_args *uap)
1777 {
1778 	struct sigvec32 vec;
1779 	struct sigaction sa, osa, *sap;
1780 	int error;
1781 
1782 	if (uap->signum <= 0 || uap->signum >= ONSIG)
1783 		return (EINVAL);
1784 
1785 	if (uap->nsv) {
1786 		error = copyin(uap->nsv, &vec, sizeof(vec));
1787 		if (error)
1788 			return (error);
1789 		sa.sa_handler = PTRIN(vec.sv_handler);
1790 		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1791 		sa.sa_flags = vec.sv_flags;
1792 		sa.sa_flags ^= SA_RESTART;
1793 		sap = &sa;
1794 	} else
1795 		sap = NULL;
1796 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1797 	if (error == 0 && uap->osv != NULL) {
1798 		vec.sv_handler = PTROUT(osa.sa_handler);
1799 		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1800 		vec.sv_flags = osa.sa_flags;
1801 		vec.sv_flags &= ~SA_NOCLDWAIT;
1802 		vec.sv_flags ^= SA_RESTART;
1803 		error = copyout(&vec, uap->osv, sizeof(vec));
1804 	}
1805 	return (error);
1806 }
1807 
1808 int
1809 ofreebsd32_sigblock(struct thread *td,
1810 			    struct ofreebsd32_sigblock_args *uap)
1811 {
1812 	struct proc *p = td->td_proc;
1813 	sigset_t set;
1814 
1815 	OSIG2SIG(uap->mask, set);
1816 	SIG_CANTMASK(set);
1817 	PROC_LOCK(p);
1818 	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1819 	SIGSETOR(td->td_sigmask, set);
1820 	PROC_UNLOCK(p);
1821 	return (0);
1822 }
1823 
1824 int
1825 ofreebsd32_sigsetmask(struct thread *td,
1826 			      struct ofreebsd32_sigsetmask_args *uap)
1827 {
1828 	struct proc *p = td->td_proc;
1829 	sigset_t set;
1830 
1831 	OSIG2SIG(uap->mask, set);
1832 	SIG_CANTMASK(set);
1833 	PROC_LOCK(p);
1834 	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1835 	SIGSETLO(td->td_sigmask, set);
1836 	signotify(td);
1837 	PROC_UNLOCK(p);
1838 	return (0);
1839 }
1840 
1841 int
1842 ofreebsd32_sigsuspend(struct thread *td,
1843 			      struct ofreebsd32_sigsuspend_args *uap)
1844 {
1845 	struct proc *p = td->td_proc;
1846 	sigset_t mask;
1847 
1848 	PROC_LOCK(p);
1849 	td->td_oldsigmask = td->td_sigmask;
1850 	td->td_pflags |= TDP_OLDMASK;
1851 	OSIG2SIG(uap->mask, mask);
1852 	SIG_CANTMASK(mask);
1853 	SIGSETLO(td->td_sigmask, mask);
1854 	signotify(td);
1855 	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
1856 		/* void */;
1857 	PROC_UNLOCK(p);
1858 	/* always return EINTR rather than ERESTART... */
1859 	return (EINTR);
1860 }
1861 
1862 struct sigstack32 {
1863 	u_int32_t	ss_sp;
1864 	int		ss_onstack;
1865 };
1866 
1867 int
1868 ofreebsd32_sigstack(struct thread *td,
1869 			    struct ofreebsd32_sigstack_args *uap)
1870 {
1871 	struct sigstack32 s32;
1872 	struct sigstack nss, oss;
1873 	int error = 0;
1874 
1875 	if (uap->nss != NULL) {
1876 		error = copyin(uap->nss, &s32, sizeof(s32));
1877 		if (error)
1878 			return (error);
1879 		nss.ss_sp = PTRIN(s32.ss_sp);
1880 		CP(s32, nss, ss_onstack);
1881 	}
1882 	oss.ss_sp = td->td_sigstk.ss_sp;
1883 	oss.ss_onstack = sigonstack(cpu_getstack(td));
1884 	if (uap->nss != NULL) {
1885 		td->td_sigstk.ss_sp = nss.ss_sp;
1886 		td->td_sigstk.ss_size = 0;
1887 		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
1888 		td->td_pflags |= TDP_ALTSTACK;
1889 	}
1890 	if (uap->oss != NULL) {
1891 		s32.ss_sp = PTROUT(oss.ss_sp);
1892 		CP(oss, s32, ss_onstack);
1893 		error = copyout(&s32, uap->oss, sizeof(s32));
1894 	}
1895 	return (error);
1896 }
1897 #endif
1898 
1899 int
1900 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1901 {
1902 	struct timespec32 rmt32, rqt32;
1903 	struct timespec rmt, rqt;
1904 	int error;
1905 
1906 	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
1907 	if (error)
1908 		return (error);
1909 
1910 	CP(rqt32, rqt, tv_sec);
1911 	CP(rqt32, rqt, tv_nsec);
1912 
1913 	if (uap->rmtp &&
1914 	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1915 		return (EFAULT);
1916 	error = kern_nanosleep(td, &rqt, &rmt);
1917 	if (error && uap->rmtp) {
1918 		int error2;
1919 
1920 		CP(rmt, rmt32, tv_sec);
1921 		CP(rmt, rmt32, tv_nsec);
1922 
1923 		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
1924 		if (error2)
1925 			error = error2;
1926 	}
1927 	return (error);
1928 }
1929 
1930 int
1931 freebsd32_clock_gettime(struct thread *td,
1932 			struct freebsd32_clock_gettime_args *uap)
1933 {
1934 	struct timespec	ats;
1935 	struct timespec32 ats32;
1936 	int error;
1937 
1938 	error = kern_clock_gettime(td, uap->clock_id, &ats);
1939 	if (error == 0) {
1940 		CP(ats, ats32, tv_sec);
1941 		CP(ats, ats32, tv_nsec);
1942 		error = copyout(&ats32, uap->tp, sizeof(ats32));
1943 	}
1944 	return (error);
1945 }
1946 
1947 int
1948 freebsd32_clock_settime(struct thread *td,
1949 			struct freebsd32_clock_settime_args *uap)
1950 {
1951 	struct timespec	ats;
1952 	struct timespec32 ats32;
1953 	int error;
1954 
1955 	error = copyin(uap->tp, &ats32, sizeof(ats32));
1956 	if (error)
1957 		return (error);
1958 	CP(ats32, ats, tv_sec);
1959 	CP(ats32, ats, tv_nsec);
1960 
1961 	return (kern_clock_settime(td, uap->clock_id, &ats));
1962 }
1963 
1964 int
1965 freebsd32_clock_getres(struct thread *td,
1966 		       struct freebsd32_clock_getres_args *uap)
1967 {
1968 	struct timespec	ts;
1969 	struct timespec32 ts32;
1970 	int error;
1971 
1972 	if (uap->tp == NULL)
1973 		return (0);
1974 	error = kern_clock_getres(td, uap->clock_id, &ts);
1975 	if (error == 0) {
1976 		CP(ts, ts32, tv_sec);
1977 		CP(ts, ts32, tv_nsec);
1978 		error = copyout(&ts32, uap->tp, sizeof(ts32));
1979 	}
1980 	return (error);
1981 }
1982 
1983 #if 0
1984 
1985 int
1986 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1987 {
1988 	int error;
1989 	struct yyy32 *p32, s32;
1990 	struct yyy *p = NULL, s;
1991 
1992 	if (uap->zzz) {
1993 		error = copyin(uap->zzz, &s32, sizeof(s32));
1994 		if (error)
1995 			return (error);
1996 		/* translate in */
1997 		p = &s;
1998 	}
1999 	error = kern_xxx(td, p);
2000 	if (error)
2001 		return (error);
2002 	if (uap->zzz) {
2003 		/* translate out */
2004 		error = copyout(&s32, p32, sizeof(s32));
2005 	}
2006 	return (error);
2007 }
2008 
2009 #endif
2010