xref: /freebsd/sys/compat/freebsd32/freebsd32_misc.c (revision 1946089b52e6041fcc7d60aa8ecbad332865a3e1)
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 #include "opt_inet.h"
32 #include "opt_inet6.h"
33 
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/clock.h>
37 #include <sys/exec.h>
38 #include <sys/fcntl.h>
39 #include <sys/filedesc.h>
40 #include <sys/imgact.h>
41 #include <sys/jail.h>
42 #include <sys/kernel.h>
43 #include <sys/limits.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/file.h>		/* Must come after sys/malloc.h */
47 #include <sys/mbuf.h>
48 #include <sys/mman.h>
49 #include <sys/module.h>
50 #include <sys/mount.h>
51 #include <sys/mutex.h>
52 #include <sys/namei.h>
53 #include <sys/proc.h>
54 #include <sys/reboot.h>
55 #include <sys/resource.h>
56 #include <sys/resourcevar.h>
57 #include <sys/selinfo.h>
58 #include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
59 #include <sys/pipe.h>		/* Must come after sys/selinfo.h */
60 #include <sys/signal.h>
61 #include <sys/signalvar.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/stat.h>
65 #include <sys/syscall.h>
66 #include <sys/syscallsubr.h>
67 #include <sys/sysctl.h>
68 #include <sys/sysent.h>
69 #include <sys/sysproto.h>
70 #include <sys/systm.h>
71 #include <sys/thr.h>
72 #include <sys/unistd.h>
73 #include <sys/ucontext.h>
74 #include <sys/vnode.h>
75 #include <sys/wait.h>
76 #include <sys/ipc.h>
77 #include <sys/msg.h>
78 #include <sys/sem.h>
79 #include <sys/shm.h>
80 
81 #ifdef INET
82 #include <netinet/in.h>
83 #endif
84 
85 #include <vm/vm.h>
86 #include <vm/vm_kern.h>
87 #include <vm/vm_param.h>
88 #include <vm/pmap.h>
89 #include <vm/vm_map.h>
90 #include <vm/vm_object.h>
91 #include <vm/vm_extern.h>
92 
93 #include <machine/cpu.h>
94 
95 #include <security/audit/audit.h>
96 
97 #include <compat/freebsd32/freebsd32_util.h>
98 #include <compat/freebsd32/freebsd32.h>
99 #include <compat/freebsd32/freebsd32_ipc.h>
100 #include <compat/freebsd32/freebsd32_signal.h>
101 #include <compat/freebsd32/freebsd32_proto.h>
102 
103 CTASSERT(sizeof(struct timeval32) == 8);
104 CTASSERT(sizeof(struct timespec32) == 8);
105 CTASSERT(sizeof(struct itimerval32) == 16);
106 CTASSERT(sizeof(struct statfs32) == 256);
107 CTASSERT(sizeof(struct rusage32) == 72);
108 CTASSERT(sizeof(struct sigaltstack32) == 12);
109 CTASSERT(sizeof(struct kevent32) == 20);
110 CTASSERT(sizeof(struct iovec32) == 8);
111 CTASSERT(sizeof(struct msghdr32) == 28);
112 CTASSERT(sizeof(struct stat32) == 96);
113 CTASSERT(sizeof(struct sigaction32) == 24);
114 
115 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
116 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
117 
118 int
119 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
120 {
121 	int error, status;
122 	struct rusage32 ru32;
123 	struct rusage ru, *rup;
124 
125 	if (uap->rusage != NULL)
126 		rup = &ru;
127 	else
128 		rup = NULL;
129 	error = kern_wait(td, uap->pid, &status, uap->options, rup);
130 	if (error)
131 		return (error);
132 	if (uap->status != NULL)
133 		error = copyout(&status, uap->status, sizeof(status));
134 	if (uap->rusage != NULL && error == 0) {
135 		TV_CP(ru, ru32, ru_utime);
136 		TV_CP(ru, ru32, ru_stime);
137 		CP(ru, ru32, ru_maxrss);
138 		CP(ru, ru32, ru_ixrss);
139 		CP(ru, ru32, ru_idrss);
140 		CP(ru, ru32, ru_isrss);
141 		CP(ru, ru32, ru_minflt);
142 		CP(ru, ru32, ru_majflt);
143 		CP(ru, ru32, ru_nswap);
144 		CP(ru, ru32, ru_inblock);
145 		CP(ru, ru32, ru_oublock);
146 		CP(ru, ru32, ru_msgsnd);
147 		CP(ru, ru32, ru_msgrcv);
148 		CP(ru, ru32, ru_nsignals);
149 		CP(ru, ru32, ru_nvcsw);
150 		CP(ru, ru32, ru_nivcsw);
151 		error = copyout(&ru32, uap->rusage, sizeof(ru32));
152 	}
153 	return (error);
154 }
155 
156 #ifdef COMPAT_FREEBSD4
157 static void
158 copy_statfs(struct statfs *in, struct statfs32 *out)
159 {
160 
161 	statfs_scale_blocks(in, INT32_MAX);
162 	bzero(out, sizeof(*out));
163 	CP(*in, *out, f_bsize);
164 	out->f_iosize = MIN(in->f_iosize, INT32_MAX);
165 	CP(*in, *out, f_blocks);
166 	CP(*in, *out, f_bfree);
167 	CP(*in, *out, f_bavail);
168 	out->f_files = MIN(in->f_files, INT32_MAX);
169 	out->f_ffree = MIN(in->f_ffree, INT32_MAX);
170 	CP(*in, *out, f_fsid);
171 	CP(*in, *out, f_owner);
172 	CP(*in, *out, f_type);
173 	CP(*in, *out, f_flags);
174 	out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
175 	out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
176 	strlcpy(out->f_fstypename,
177 	      in->f_fstypename, MFSNAMELEN);
178 	strlcpy(out->f_mntonname,
179 	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
180 	out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
181 	out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
182 	strlcpy(out->f_mntfromname,
183 	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
184 }
185 #endif
186 
187 #ifdef COMPAT_FREEBSD4
188 int
189 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
190 {
191 	struct statfs *buf, *sp;
192 	struct statfs32 stat32;
193 	size_t count, size;
194 	int error;
195 
196 	count = uap->bufsize / sizeof(struct statfs32);
197 	size = count * sizeof(struct statfs);
198 	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
199 	if (size > 0) {
200 		count = td->td_retval[0];
201 		sp = buf;
202 		while (count > 0 && error == 0) {
203 			copy_statfs(sp, &stat32);
204 			error = copyout(&stat32, uap->buf, sizeof(stat32));
205 			sp++;
206 			uap->buf++;
207 			count--;
208 		}
209 		free(buf, M_TEMP);
210 	}
211 	return (error);
212 }
213 #endif
214 
215 int
216 freebsd32_sigaltstack(struct thread *td,
217 		      struct freebsd32_sigaltstack_args *uap)
218 {
219 	struct sigaltstack32 s32;
220 	struct sigaltstack ss, oss, *ssp;
221 	int error;
222 
223 	if (uap->ss != NULL) {
224 		error = copyin(uap->ss, &s32, sizeof(s32));
225 		if (error)
226 			return (error);
227 		PTRIN_CP(s32, ss, ss_sp);
228 		CP(s32, ss, ss_size);
229 		CP(s32, ss, ss_flags);
230 		ssp = &ss;
231 	} else
232 		ssp = NULL;
233 	error = kern_sigaltstack(td, ssp, &oss);
234 	if (error == 0 && uap->oss != NULL) {
235 		PTROUT_CP(oss, s32, ss_sp);
236 		CP(oss, s32, ss_size);
237 		CP(oss, s32, ss_flags);
238 		error = copyout(&s32, uap->oss, sizeof(s32));
239 	}
240 	return (error);
241 }
242 
243 /*
244  * Custom version of exec_copyin_args() so that we can translate
245  * the pointers.
246  */
247 static int
248 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
249     enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
250 {
251 	char *argp, *envp;
252 	u_int32_t *p32, arg;
253 	size_t length;
254 	int error;
255 
256 	bzero(args, sizeof(*args));
257 	if (argv == NULL)
258 		return (EFAULT);
259 
260 	/*
261 	 * Allocate temporary demand zeroed space for argument and
262 	 *	environment strings
263 	 */
264 	args->buf = (char *) kmem_alloc_wait(exec_map,
265 	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
266 	if (args->buf == NULL)
267 		return (ENOMEM);
268 	args->begin_argv = args->buf;
269 	args->endp = args->begin_argv;
270 	args->stringspace = ARG_MAX;
271 
272 	/*
273 	 * Copy the file name.
274 	 */
275 	if (fname != NULL) {
276 		args->fname = args->buf + ARG_MAX;
277 		error = (segflg == UIO_SYSSPACE) ?
278 		    copystr(fname, args->fname, PATH_MAX, &length) :
279 		    copyinstr(fname, args->fname, PATH_MAX, &length);
280 		if (error != 0)
281 			goto err_exit;
282 	} else
283 		args->fname = NULL;
284 
285 	/*
286 	 * extract arguments first
287 	 */
288 	p32 = argv;
289 	for (;;) {
290 		error = copyin(p32++, &arg, sizeof(arg));
291 		if (error)
292 			goto err_exit;
293 		if (arg == 0)
294 			break;
295 		argp = PTRIN(arg);
296 		error = copyinstr(argp, args->endp, args->stringspace, &length);
297 		if (error) {
298 			if (error == ENAMETOOLONG)
299 				error = E2BIG;
300 			goto err_exit;
301 		}
302 		args->stringspace -= length;
303 		args->endp += length;
304 		args->argc++;
305 	}
306 
307 	args->begin_envv = args->endp;
308 
309 	/*
310 	 * extract environment strings
311 	 */
312 	if (envv) {
313 		p32 = envv;
314 		for (;;) {
315 			error = copyin(p32++, &arg, sizeof(arg));
316 			if (error)
317 				goto err_exit;
318 			if (arg == 0)
319 				break;
320 			envp = PTRIN(arg);
321 			error = copyinstr(envp, args->endp, args->stringspace,
322 			    &length);
323 			if (error) {
324 				if (error == ENAMETOOLONG)
325 					error = E2BIG;
326 				goto err_exit;
327 			}
328 			args->stringspace -= length;
329 			args->endp += length;
330 			args->envc++;
331 		}
332 	}
333 
334 	return (0);
335 
336 err_exit:
337 	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
338 	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
339 	args->buf = NULL;
340 	return (error);
341 }
342 
343 int
344 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
345 {
346 	struct image_args eargs;
347 	int error;
348 
349 	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
350 	    uap->argv, uap->envv);
351 	if (error == 0)
352 		error = kern_execve(td, &eargs, NULL);
353 	return (error);
354 }
355 
356 int
357 freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
358 {
359 	struct image_args eargs;
360 	int error;
361 
362 	error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
363 	    uap->argv, uap->envv);
364 	if (error == 0) {
365 		eargs.fd = uap->fd;
366 		error = kern_execve(td, &eargs, NULL);
367 	}
368 	return (error);
369 }
370 
371 #ifdef __ia64__
372 static int
373 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
374 		       int prot, int fd, off_t pos)
375 {
376 	vm_map_t map;
377 	vm_map_entry_t entry;
378 	int rv;
379 
380 	map = &td->td_proc->p_vmspace->vm_map;
381 	if (fd != -1)
382 		prot |= VM_PROT_WRITE;
383 
384 	if (vm_map_lookup_entry(map, start, &entry)) {
385 		if ((entry->protection & prot) != prot) {
386 			rv = vm_map_protect(map,
387 					    trunc_page(start),
388 					    round_page(end),
389 					    entry->protection | prot,
390 					    FALSE);
391 			if (rv != KERN_SUCCESS)
392 				return (EINVAL);
393 		}
394 	} else {
395 		vm_offset_t addr = trunc_page(start);
396 		rv = vm_map_find(map, 0, 0,
397 				 &addr, PAGE_SIZE, FALSE, prot,
398 				 VM_PROT_ALL, 0);
399 		if (rv != KERN_SUCCESS)
400 			return (EINVAL);
401 	}
402 
403 	if (fd != -1) {
404 		struct pread_args r;
405 		r.fd = fd;
406 		r.buf = (void *) start;
407 		r.nbyte = end - start;
408 		r.offset = pos;
409 		return (pread(td, &r));
410 	} else {
411 		while (start < end) {
412 			subyte((void *) start, 0);
413 			start++;
414 		}
415 		return (0);
416 	}
417 }
418 #endif
419 
420 int
421 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
422 {
423 	struct mmap_args ap;
424 	vm_offset_t addr = (vm_offset_t) uap->addr;
425 	vm_size_t len	 = uap->len;
426 	int prot	 = uap->prot;
427 	int flags	 = uap->flags;
428 	int fd		 = uap->fd;
429 	off_t pos	 = (uap->poslo
430 			    | ((off_t)uap->poshi << 32));
431 #ifdef __ia64__
432 	vm_size_t pageoff;
433 	int error;
434 
435 	/*
436 	 * Attempt to handle page size hassles.
437 	 */
438 	pageoff = (pos & PAGE_MASK);
439 	if (flags & MAP_FIXED) {
440 		vm_offset_t start, end;
441 		start = addr;
442 		end = addr + len;
443 
444 		if (start != trunc_page(start)) {
445 			error = freebsd32_mmap_partial(td, start,
446 						       round_page(start), prot,
447 						       fd, pos);
448 			if (fd != -1)
449 				pos += round_page(start) - start;
450 			start = round_page(start);
451 		}
452 		if (end != round_page(end)) {
453 			vm_offset_t t = trunc_page(end);
454 			error = freebsd32_mmap_partial(td, t, end,
455 						  prot, fd,
456 						  pos + t - start);
457 			end = trunc_page(end);
458 		}
459 		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
460 			/*
461 			 * We can't map this region at all. The specified
462 			 * address doesn't have the same alignment as the file
463 			 * position. Fake the mapping by simply reading the
464 			 * entire region into memory. First we need to make
465 			 * sure the region exists.
466 			 */
467 			vm_map_t map;
468 			struct pread_args r;
469 			int rv;
470 
471 			prot |= VM_PROT_WRITE;
472 			map = &td->td_proc->p_vmspace->vm_map;
473 			rv = vm_map_remove(map, start, end);
474 			if (rv != KERN_SUCCESS)
475 				return (EINVAL);
476 			rv = vm_map_find(map, 0, 0,
477 					 &start, end - start, FALSE,
478 					 prot, VM_PROT_ALL, 0);
479 			if (rv != KERN_SUCCESS)
480 				return (EINVAL);
481 			r.fd = fd;
482 			r.buf = (void *) start;
483 			r.nbyte = end - start;
484 			r.offset = pos;
485 			error = pread(td, &r);
486 			if (error)
487 				return (error);
488 
489 			td->td_retval[0] = addr;
490 			return (0);
491 		}
492 		if (end == start) {
493 			/*
494 			 * After dealing with the ragged ends, there
495 			 * might be none left.
496 			 */
497 			td->td_retval[0] = addr;
498 			return (0);
499 		}
500 		addr = start;
501 		len = end - start;
502 	}
503 #endif
504 
505 	ap.addr = (void *) addr;
506 	ap.len = len;
507 	ap.prot = prot;
508 	ap.flags = flags;
509 	ap.fd = fd;
510 	ap.pos = pos;
511 
512 	return (mmap(td, &ap));
513 }
514 
515 #ifdef COMPAT_FREEBSD6
516 int
517 freebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
518 {
519 	struct freebsd32_mmap_args ap;
520 
521 	ap.addr = uap->addr;
522 	ap.len = uap->len;
523 	ap.prot = uap->prot;
524 	ap.flags = uap->flags;
525 	ap.fd = uap->fd;
526 	ap.poslo = uap->poslo;
527 	ap.poshi = uap->poshi;
528 
529 	return (freebsd32_mmap(td, &ap));
530 }
531 #endif
532 
533 int
534 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
535 {
536 	struct itimerval itv, oitv, *itvp;
537 	struct itimerval32 i32;
538 	int error;
539 
540 	if (uap->itv != NULL) {
541 		error = copyin(uap->itv, &i32, sizeof(i32));
542 		if (error)
543 			return (error);
544 		TV_CP(i32, itv, it_interval);
545 		TV_CP(i32, itv, it_value);
546 		itvp = &itv;
547 	} else
548 		itvp = NULL;
549 	error = kern_setitimer(td, uap->which, itvp, &oitv);
550 	if (error || uap->oitv == NULL)
551 		return (error);
552 	TV_CP(oitv, i32, it_interval);
553 	TV_CP(oitv, i32, it_value);
554 	return (copyout(&i32, uap->oitv, sizeof(i32)));
555 }
556 
557 int
558 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
559 {
560 	struct itimerval itv;
561 	struct itimerval32 i32;
562 	int error;
563 
564 	error = kern_getitimer(td, uap->which, &itv);
565 	if (error || uap->itv == NULL)
566 		return (error);
567 	TV_CP(itv, i32, it_interval);
568 	TV_CP(itv, i32, it_value);
569 	return (copyout(&i32, uap->itv, sizeof(i32)));
570 }
571 
572 int
573 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
574 {
575 	struct timeval32 tv32;
576 	struct timeval tv, *tvp;
577 	int error;
578 
579 	if (uap->tv != NULL) {
580 		error = copyin(uap->tv, &tv32, sizeof(tv32));
581 		if (error)
582 			return (error);
583 		CP(tv32, tv, tv_sec);
584 		CP(tv32, tv, tv_usec);
585 		tvp = &tv;
586 	} else
587 		tvp = NULL;
588 	/*
589 	 * XXX big-endian needs to convert the fd_sets too.
590 	 * XXX Do pointers need PTRIN()?
591 	 */
592 	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
593 }
594 
595 /*
596  * Copy 'count' items into the destination list pointed to by uap->eventlist.
597  */
598 static int
599 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
600 {
601 	struct freebsd32_kevent_args *uap;
602 	struct kevent32	ks32[KQ_NEVENTS];
603 	int i, error = 0;
604 
605 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
606 	uap = (struct freebsd32_kevent_args *)arg;
607 
608 	for (i = 0; i < count; i++) {
609 		CP(kevp[i], ks32[i], ident);
610 		CP(kevp[i], ks32[i], filter);
611 		CP(kevp[i], ks32[i], flags);
612 		CP(kevp[i], ks32[i], fflags);
613 		CP(kevp[i], ks32[i], data);
614 		PTROUT_CP(kevp[i], ks32[i], udata);
615 	}
616 	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
617 	if (error == 0)
618 		uap->eventlist += count;
619 	return (error);
620 }
621 
622 /*
623  * Copy 'count' items from the list pointed to by uap->changelist.
624  */
625 static int
626 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
627 {
628 	struct freebsd32_kevent_args *uap;
629 	struct kevent32	ks32[KQ_NEVENTS];
630 	int i, error = 0;
631 
632 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
633 	uap = (struct freebsd32_kevent_args *)arg;
634 
635 	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
636 	if (error)
637 		goto done;
638 	uap->changelist += count;
639 
640 	for (i = 0; i < count; i++) {
641 		CP(ks32[i], kevp[i], ident);
642 		CP(ks32[i], kevp[i], filter);
643 		CP(ks32[i], kevp[i], flags);
644 		CP(ks32[i], kevp[i], fflags);
645 		CP(ks32[i], kevp[i], data);
646 		PTRIN_CP(ks32[i], kevp[i], udata);
647 	}
648 done:
649 	return (error);
650 }
651 
652 int
653 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
654 {
655 	struct timespec32 ts32;
656 	struct timespec ts, *tsp;
657 	struct kevent_copyops k_ops = { uap,
658 					freebsd32_kevent_copyout,
659 					freebsd32_kevent_copyin};
660 	int error;
661 
662 
663 	if (uap->timeout) {
664 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
665 		if (error)
666 			return (error);
667 		CP(ts32, ts, tv_sec);
668 		CP(ts32, ts, tv_nsec);
669 		tsp = &ts;
670 	} else
671 		tsp = NULL;
672 	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
673 	    &k_ops, tsp);
674 	return (error);
675 }
676 
677 int
678 freebsd32_gettimeofday(struct thread *td,
679 		       struct freebsd32_gettimeofday_args *uap)
680 {
681 	struct timeval atv;
682 	struct timeval32 atv32;
683 	struct timezone rtz;
684 	int error = 0;
685 
686 	if (uap->tp) {
687 		microtime(&atv);
688 		CP(atv, atv32, tv_sec);
689 		CP(atv, atv32, tv_usec);
690 		error = copyout(&atv32, uap->tp, sizeof (atv32));
691 	}
692 	if (error == 0 && uap->tzp != NULL) {
693 		rtz.tz_minuteswest = tz_minuteswest;
694 		rtz.tz_dsttime = tz_dsttime;
695 		error = copyout(&rtz, uap->tzp, sizeof (rtz));
696 	}
697 	return (error);
698 }
699 
700 int
701 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
702 {
703 	struct rusage32 s32;
704 	struct rusage s;
705 	int error;
706 
707 	error = kern_getrusage(td, uap->who, &s);
708 	if (error)
709 		return (error);
710 	if (uap->rusage != NULL) {
711 		TV_CP(s, s32, ru_utime);
712 		TV_CP(s, s32, ru_stime);
713 		CP(s, s32, ru_maxrss);
714 		CP(s, s32, ru_ixrss);
715 		CP(s, s32, ru_idrss);
716 		CP(s, s32, ru_isrss);
717 		CP(s, s32, ru_minflt);
718 		CP(s, s32, ru_majflt);
719 		CP(s, s32, ru_nswap);
720 		CP(s, s32, ru_inblock);
721 		CP(s, s32, ru_oublock);
722 		CP(s, s32, ru_msgsnd);
723 		CP(s, s32, ru_msgrcv);
724 		CP(s, s32, ru_nsignals);
725 		CP(s, s32, ru_nvcsw);
726 		CP(s, s32, ru_nivcsw);
727 		error = copyout(&s32, uap->rusage, sizeof(s32));
728 	}
729 	return (error);
730 }
731 
732 static int
733 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
734 {
735 	struct iovec32 iov32;
736 	struct iovec *iov;
737 	struct uio *uio;
738 	u_int iovlen;
739 	int error, i;
740 
741 	*uiop = NULL;
742 	if (iovcnt > UIO_MAXIOV)
743 		return (EINVAL);
744 	iovlen = iovcnt * sizeof(struct iovec);
745 	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
746 	iov = (struct iovec *)(uio + 1);
747 	for (i = 0; i < iovcnt; i++) {
748 		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
749 		if (error) {
750 			free(uio, M_IOV);
751 			return (error);
752 		}
753 		iov[i].iov_base = PTRIN(iov32.iov_base);
754 		iov[i].iov_len = iov32.iov_len;
755 	}
756 	uio->uio_iov = iov;
757 	uio->uio_iovcnt = iovcnt;
758 	uio->uio_segflg = UIO_USERSPACE;
759 	uio->uio_offset = -1;
760 	uio->uio_resid = 0;
761 	for (i = 0; i < iovcnt; i++) {
762 		if (iov->iov_len > INT_MAX - uio->uio_resid) {
763 			free(uio, M_IOV);
764 			return (EINVAL);
765 		}
766 		uio->uio_resid += iov->iov_len;
767 		iov++;
768 	}
769 	*uiop = uio;
770 	return (0);
771 }
772 
773 int
774 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
775 {
776 	struct uio *auio;
777 	int error;
778 
779 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
780 	if (error)
781 		return (error);
782 	error = kern_readv(td, uap->fd, auio);
783 	free(auio, M_IOV);
784 	return (error);
785 }
786 
787 int
788 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
789 {
790 	struct uio *auio;
791 	int error;
792 
793 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
794 	if (error)
795 		return (error);
796 	error = kern_writev(td, uap->fd, auio);
797 	free(auio, M_IOV);
798 	return (error);
799 }
800 
801 int
802 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
803 {
804 	struct uio *auio;
805 	int error;
806 
807 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
808 	if (error)
809 		return (error);
810 	error = kern_preadv(td, uap->fd, auio, uap->offset);
811 	free(auio, M_IOV);
812 	return (error);
813 }
814 
815 int
816 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
817 {
818 	struct uio *auio;
819 	int error;
820 
821 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
822 	if (error)
823 		return (error);
824 	error = kern_pwritev(td, uap->fd, auio, uap->offset);
825 	free(auio, M_IOV);
826 	return (error);
827 }
828 
829 static int
830 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
831     int error)
832 {
833 	struct iovec32 iov32;
834 	struct iovec *iov;
835 	u_int iovlen;
836 	int i;
837 
838 	*iovp = NULL;
839 	if (iovcnt > UIO_MAXIOV)
840 		return (error);
841 	iovlen = iovcnt * sizeof(struct iovec);
842 	iov = malloc(iovlen, M_IOV, M_WAITOK);
843 	for (i = 0; i < iovcnt; i++) {
844 		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
845 		if (error) {
846 			free(iov, M_IOV);
847 			return (error);
848 		}
849 		iov[i].iov_base = PTRIN(iov32.iov_base);
850 		iov[i].iov_len = iov32.iov_len;
851 	}
852 	*iovp = iov;
853 	return (0);
854 }
855 
856 static int
857 freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
858 {
859 	struct msghdr32 m32;
860 	int error;
861 
862 	error = copyin(msg32, &m32, sizeof(m32));
863 	if (error)
864 		return (error);
865 	msg->msg_name = PTRIN(m32.msg_name);
866 	msg->msg_namelen = m32.msg_namelen;
867 	msg->msg_iov = PTRIN(m32.msg_iov);
868 	msg->msg_iovlen = m32.msg_iovlen;
869 	msg->msg_control = PTRIN(m32.msg_control);
870 	msg->msg_controllen = m32.msg_controllen;
871 	msg->msg_flags = m32.msg_flags;
872 	return (0);
873 }
874 
875 static int
876 freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
877 {
878 	struct msghdr32 m32;
879 	int error;
880 
881 	m32.msg_name = PTROUT(msg->msg_name);
882 	m32.msg_namelen = msg->msg_namelen;
883 	m32.msg_iov = PTROUT(msg->msg_iov);
884 	m32.msg_iovlen = msg->msg_iovlen;
885 	m32.msg_control = PTROUT(msg->msg_control);
886 	m32.msg_controllen = msg->msg_controllen;
887 	m32.msg_flags = msg->msg_flags;
888 	error = copyout(&m32, msg32, sizeof(m32));
889 	return (error);
890 }
891 
892 #define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
893 #define FREEBSD32_ALIGN(p)	\
894 	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
895 #define	FREEBSD32_CMSG_SPACE(l)	\
896 	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
897 
898 #define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
899 				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
900 static int
901 freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
902 {
903 	struct cmsghdr *cm;
904 	void *data;
905 	socklen_t clen, datalen;
906 	int error;
907 	caddr_t ctlbuf;
908 	int len, maxlen, copylen;
909 	struct mbuf *m;
910 	error = 0;
911 
912 	len    = msg->msg_controllen;
913 	maxlen = msg->msg_controllen;
914 	msg->msg_controllen = 0;
915 
916 	m = control;
917 	ctlbuf = msg->msg_control;
918 
919 	while (m && len > 0) {
920 		cm = mtod(m, struct cmsghdr *);
921 		clen = m->m_len;
922 
923 		while (cm != NULL) {
924 
925 			if (sizeof(struct cmsghdr) > clen ||
926 			    cm->cmsg_len > clen) {
927 				error = EINVAL;
928 				break;
929 			}
930 
931 			data   = CMSG_DATA(cm);
932 			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
933 
934 			/* Adjust message length */
935 			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
936 			    datalen;
937 
938 
939 			/* Copy cmsghdr */
940 			copylen = sizeof(struct cmsghdr);
941 			if (len < copylen) {
942 				msg->msg_flags |= MSG_CTRUNC;
943 				copylen = len;
944 			}
945 
946 			error = copyout(cm,ctlbuf,copylen);
947 			if (error)
948 				goto exit;
949 
950 			ctlbuf += FREEBSD32_ALIGN(copylen);
951 			len    -= FREEBSD32_ALIGN(copylen);
952 
953 			if (len <= 0)
954 				break;
955 
956 			/* Copy data */
957 			copylen = datalen;
958 			if (len < copylen) {
959 				msg->msg_flags |= MSG_CTRUNC;
960 				copylen = len;
961 			}
962 
963 			error = copyout(data,ctlbuf,copylen);
964 			if (error)
965 				goto exit;
966 
967 			ctlbuf += FREEBSD32_ALIGN(copylen);
968 			len    -= FREEBSD32_ALIGN(copylen);
969 
970 			if (CMSG_SPACE(datalen) < clen) {
971 				clen -= CMSG_SPACE(datalen);
972 				cm = (struct cmsghdr *)
973 					((caddr_t)cm + CMSG_SPACE(datalen));
974 			} else {
975 				clen = 0;
976 				cm = NULL;
977 			}
978 		}
979 		m = m->m_next;
980 	}
981 
982 	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
983 
984 exit:
985 	return (error);
986 
987 }
988 
989 int
990 freebsd32_recvmsg(td, uap)
991 	struct thread *td;
992 	struct freebsd32_recvmsg_args /* {
993 		int	s;
994 		struct	msghdr32 *msg;
995 		int	flags;
996 	} */ *uap;
997 {
998 	struct msghdr msg;
999 	struct msghdr32 m32;
1000 	struct iovec *uiov, *iov;
1001 	struct mbuf *control = NULL;
1002 	struct mbuf **controlp;
1003 
1004 	int error;
1005 	error = copyin(uap->msg, &m32, sizeof(m32));
1006 	if (error)
1007 		return (error);
1008 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1009 	if (error)
1010 		return (error);
1011 	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1012 	    EMSGSIZE);
1013 	if (error)
1014 		return (error);
1015 	msg.msg_flags = uap->flags;
1016 	uiov = msg.msg_iov;
1017 	msg.msg_iov = iov;
1018 
1019 	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1020 	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1021 	if (error == 0) {
1022 		msg.msg_iov = uiov;
1023 
1024 		if (control != NULL)
1025 			error = freebsd32_copy_msg_out(&msg, control);
1026 
1027 		if (error == 0)
1028 			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1029 	}
1030 	free(iov, M_IOV);
1031 
1032 	if (control != NULL)
1033 		m_freem(control);
1034 
1035 	return (error);
1036 }
1037 
1038 
1039 static int
1040 freebsd32_convert_msg_in(struct mbuf **controlp)
1041 {
1042 	struct mbuf *control = *controlp;
1043 	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1044 	void *data;
1045 	socklen_t clen = control->m_len, datalen;
1046 	int error;
1047 
1048 	error = 0;
1049 	*controlp = NULL;
1050 
1051 	while (cm != NULL) {
1052 		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1053 			error = EINVAL;
1054 			break;
1055 		}
1056 
1057 		data = FREEBSD32_CMSG_DATA(cm);
1058 		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1059 
1060 		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1061 		    cm->cmsg_level);
1062 		controlp = &(*controlp)->m_next;
1063 
1064 		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1065 			clen -= FREEBSD32_CMSG_SPACE(datalen);
1066 			cm = (struct cmsghdr *)
1067 				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1068 		} else {
1069 			clen = 0;
1070 			cm = NULL;
1071 		}
1072 	}
1073 
1074 	m_freem(control);
1075 	return (error);
1076 }
1077 
1078 
1079 int
1080 freebsd32_sendmsg(struct thread *td,
1081 		  struct freebsd32_sendmsg_args *uap)
1082 {
1083 	struct msghdr msg;
1084 	struct msghdr32 m32;
1085 	struct iovec *iov;
1086 	struct mbuf *control = NULL;
1087 	struct sockaddr *to = NULL;
1088 	int error;
1089 
1090 	error = copyin(uap->msg, &m32, sizeof(m32));
1091 	if (error)
1092 		return (error);
1093 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1094 	if (error)
1095 		return (error);
1096 	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1097 	    EMSGSIZE);
1098 	if (error)
1099 		return (error);
1100 	msg.msg_iov = iov;
1101 	if (msg.msg_name != NULL) {
1102 		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1103 		if (error) {
1104 			to = NULL;
1105 			goto out;
1106 		}
1107 		msg.msg_name = to;
1108 	}
1109 
1110 	if (msg.msg_control) {
1111 		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1112 			error = EINVAL;
1113 			goto out;
1114 		}
1115 
1116 		error = sockargs(&control, msg.msg_control,
1117 		    msg.msg_controllen, MT_CONTROL);
1118 		if (error)
1119 			goto out;
1120 
1121 		error = freebsd32_convert_msg_in(&control);
1122 		if (error)
1123 			goto out;
1124 	}
1125 
1126 	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1127 	    UIO_USERSPACE);
1128 
1129 out:
1130 	free(iov, M_IOV);
1131 	if (to)
1132 		free(to, M_SONAME);
1133 	return (error);
1134 }
1135 
1136 int
1137 freebsd32_recvfrom(struct thread *td,
1138 		   struct freebsd32_recvfrom_args *uap)
1139 {
1140 	struct msghdr msg;
1141 	struct iovec aiov;
1142 	int error;
1143 
1144 	if (uap->fromlenaddr) {
1145 		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1146 		    sizeof(msg.msg_namelen));
1147 		if (error)
1148 			return (error);
1149 	} else {
1150 		msg.msg_namelen = 0;
1151 	}
1152 
1153 	msg.msg_name = PTRIN(uap->from);
1154 	msg.msg_iov = &aiov;
1155 	msg.msg_iovlen = 1;
1156 	aiov.iov_base = PTRIN(uap->buf);
1157 	aiov.iov_len = uap->len;
1158 	msg.msg_control = NULL;
1159 	msg.msg_flags = uap->flags;
1160 	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1161 	if (error == 0 && uap->fromlenaddr)
1162 		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1163 		    sizeof (msg.msg_namelen));
1164 	return (error);
1165 }
1166 
1167 int
1168 freebsd32_settimeofday(struct thread *td,
1169 		       struct freebsd32_settimeofday_args *uap)
1170 {
1171 	struct timeval32 tv32;
1172 	struct timeval tv, *tvp;
1173 	struct timezone tz, *tzp;
1174 	int error;
1175 
1176 	if (uap->tv) {
1177 		error = copyin(uap->tv, &tv32, sizeof(tv32));
1178 		if (error)
1179 			return (error);
1180 		CP(tv32, tv, tv_sec);
1181 		CP(tv32, tv, tv_usec);
1182 		tvp = &tv;
1183 	} else
1184 		tvp = NULL;
1185 	if (uap->tzp) {
1186 		error = copyin(uap->tzp, &tz, sizeof(tz));
1187 		if (error)
1188 			return (error);
1189 		tzp = &tz;
1190 	} else
1191 		tzp = NULL;
1192 	return (kern_settimeofday(td, tvp, tzp));
1193 }
1194 
1195 int
1196 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1197 {
1198 	struct timeval32 s32[2];
1199 	struct timeval s[2], *sp;
1200 	int error;
1201 
1202 	if (uap->tptr != NULL) {
1203 		error = copyin(uap->tptr, s32, sizeof(s32));
1204 		if (error)
1205 			return (error);
1206 		CP(s32[0], s[0], tv_sec);
1207 		CP(s32[0], s[0], tv_usec);
1208 		CP(s32[1], s[1], tv_sec);
1209 		CP(s32[1], s[1], tv_usec);
1210 		sp = s;
1211 	} else
1212 		sp = NULL;
1213 	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1214 }
1215 
1216 int
1217 freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1218 {
1219 	struct timeval32 s32[2];
1220 	struct timeval s[2], *sp;
1221 	int error;
1222 
1223 	if (uap->tptr != NULL) {
1224 		error = copyin(uap->tptr, s32, sizeof(s32));
1225 		if (error)
1226 			return (error);
1227 		CP(s32[0], s[0], tv_sec);
1228 		CP(s32[0], s[0], tv_usec);
1229 		CP(s32[1], s[1], tv_sec);
1230 		CP(s32[1], s[1], tv_usec);
1231 		sp = s;
1232 	} else
1233 		sp = NULL;
1234 	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1235 }
1236 
1237 int
1238 freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1239 {
1240 	struct timeval32 s32[2];
1241 	struct timeval s[2], *sp;
1242 	int error;
1243 
1244 	if (uap->tptr != NULL) {
1245 		error = copyin(uap->tptr, s32, sizeof(s32));
1246 		if (error)
1247 			return (error);
1248 		CP(s32[0], s[0], tv_sec);
1249 		CP(s32[0], s[0], tv_usec);
1250 		CP(s32[1], s[1], tv_sec);
1251 		CP(s32[1], s[1], tv_usec);
1252 		sp = s;
1253 	} else
1254 		sp = NULL;
1255 	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1256 }
1257 
1258 int
1259 freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
1260 {
1261 	struct timeval32 s32[2];
1262 	struct timeval s[2], *sp;
1263 	int error;
1264 
1265 	if (uap->times != NULL) {
1266 		error = copyin(uap->times, s32, sizeof(s32));
1267 		if (error)
1268 			return (error);
1269 		CP(s32[0], s[0], tv_sec);
1270 		CP(s32[0], s[0], tv_usec);
1271 		CP(s32[1], s[1], tv_sec);
1272 		CP(s32[1], s[1], tv_usec);
1273 		sp = s;
1274 	} else
1275 		sp = NULL;
1276 	return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
1277 		sp, UIO_SYSSPACE));
1278 }
1279 
1280 int
1281 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1282 {
1283 	struct timeval32 tv32;
1284 	struct timeval delta, olddelta, *deltap;
1285 	int error;
1286 
1287 	if (uap->delta) {
1288 		error = copyin(uap->delta, &tv32, sizeof(tv32));
1289 		if (error)
1290 			return (error);
1291 		CP(tv32, delta, tv_sec);
1292 		CP(tv32, delta, tv_usec);
1293 		deltap = &delta;
1294 	} else
1295 		deltap = NULL;
1296 	error = kern_adjtime(td, deltap, &olddelta);
1297 	if (uap->olddelta && error == 0) {
1298 		CP(olddelta, tv32, tv_sec);
1299 		CP(olddelta, tv32, tv_usec);
1300 		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1301 	}
1302 	return (error);
1303 }
1304 
1305 #ifdef COMPAT_FREEBSD4
1306 int
1307 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1308 {
1309 	struct statfs32 s32;
1310 	struct statfs s;
1311 	int error;
1312 
1313 	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1314 	if (error)
1315 		return (error);
1316 	copy_statfs(&s, &s32);
1317 	return (copyout(&s32, uap->buf, sizeof(s32)));
1318 }
1319 #endif
1320 
1321 #ifdef COMPAT_FREEBSD4
1322 int
1323 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1324 {
1325 	struct statfs32 s32;
1326 	struct statfs s;
1327 	int error;
1328 
1329 	error = kern_fstatfs(td, uap->fd, &s);
1330 	if (error)
1331 		return (error);
1332 	copy_statfs(&s, &s32);
1333 	return (copyout(&s32, uap->buf, sizeof(s32)));
1334 }
1335 #endif
1336 
1337 #ifdef COMPAT_FREEBSD4
1338 int
1339 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1340 {
1341 	struct statfs32 s32;
1342 	struct statfs s;
1343 	fhandle_t fh;
1344 	int error;
1345 
1346 	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1347 		return (error);
1348 	error = kern_fhstatfs(td, fh, &s);
1349 	if (error)
1350 		return (error);
1351 	copy_statfs(&s, &s32);
1352 	return (copyout(&s32, uap->buf, sizeof(s32)));
1353 }
1354 #endif
1355 
1356 static void
1357 freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
1358 {
1359 
1360 	CP(*ip32, *ip, cuid);
1361 	CP(*ip32, *ip, cgid);
1362 	CP(*ip32, *ip, uid);
1363 	CP(*ip32, *ip, gid);
1364 	CP(*ip32, *ip, mode);
1365 	CP(*ip32, *ip, seq);
1366 	CP(*ip32, *ip, key);
1367 }
1368 
1369 static void
1370 freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32)
1371 {
1372 
1373 	CP(*ip, *ip32, cuid);
1374 	CP(*ip, *ip32, cgid);
1375 	CP(*ip, *ip32, uid);
1376 	CP(*ip, *ip32, gid);
1377 	CP(*ip, *ip32, mode);
1378 	CP(*ip, *ip32, seq);
1379 	CP(*ip, *ip32, key);
1380 }
1381 
1382 int
1383 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1384 {
1385 
1386 	switch (uap->which) {
1387 	case 0:
1388 		return (freebsd32_semctl(td,
1389 		    (struct freebsd32_semctl_args *)&uap->a2));
1390 	default:
1391 		return (semsys(td, (struct semsys_args *)uap));
1392 	}
1393 }
1394 
1395 int
1396 freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
1397 {
1398 	struct semid_ds32 dsbuf32;
1399 	struct semid_ds dsbuf;
1400 	union semun semun;
1401 	union semun32 arg;
1402 	register_t rval;
1403 	int error;
1404 
1405 	switch (uap->cmd) {
1406 	case SEM_STAT:
1407 	case IPC_SET:
1408 	case IPC_STAT:
1409 	case GETALL:
1410 	case SETVAL:
1411 	case SETALL:
1412 		error = copyin(uap->arg, &arg, sizeof(arg));
1413 		if (error)
1414 			return (error);
1415 		break;
1416 	}
1417 
1418 	switch (uap->cmd) {
1419 	case SEM_STAT:
1420 	case IPC_STAT:
1421 		semun.buf = &dsbuf;
1422 		break;
1423 	case IPC_SET:
1424 		error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1425 		if (error)
1426 			return (error);
1427 		freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1428 		PTRIN_CP(dsbuf32, dsbuf, sem_base);
1429 		CP(dsbuf32, dsbuf, sem_nsems);
1430 		CP(dsbuf32, dsbuf, sem_otime);
1431 		CP(dsbuf32, dsbuf, sem_pad1);
1432 		CP(dsbuf32, dsbuf, sem_ctime);
1433 		CP(dsbuf32, dsbuf, sem_pad2);
1434 		CP(dsbuf32, dsbuf, sem_pad3[0]);
1435 		CP(dsbuf32, dsbuf, sem_pad3[1]);
1436 		CP(dsbuf32, dsbuf, sem_pad3[2]);
1437 		CP(dsbuf32, dsbuf, sem_pad3[3]);
1438 		semun.buf = &dsbuf;
1439 		break;
1440 	case GETALL:
1441 	case SETALL:
1442 		semun.array = PTRIN(arg.array);
1443 		break;
1444 	case SETVAL:
1445 		semun.val = arg.val;
1446 		break;
1447 	}
1448 
1449 	error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1450 	    &rval);
1451 	if (error)
1452 		return (error);
1453 
1454 	switch (uap->cmd) {
1455 	case SEM_STAT:
1456 	case IPC_STAT:
1457 		freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1458 		PTROUT_CP(dsbuf, dsbuf32, sem_base);
1459 		CP(dsbuf, dsbuf32, sem_nsems);
1460 		CP(dsbuf, dsbuf32, sem_otime);
1461 		CP(dsbuf, dsbuf32, sem_pad1);
1462 		CP(dsbuf, dsbuf32, sem_ctime);
1463 		CP(dsbuf, dsbuf32, sem_pad2);
1464 		CP(dsbuf, dsbuf32, sem_pad3[0]);
1465 		CP(dsbuf, dsbuf32, sem_pad3[1]);
1466 		CP(dsbuf, dsbuf32, sem_pad3[2]);
1467 		CP(dsbuf, dsbuf32, sem_pad3[3]);
1468 		error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1469 		break;
1470 	}
1471 
1472 	if (error == 0)
1473 		td->td_retval[0] = rval;
1474 	return (error);
1475 }
1476 
1477 int
1478 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1479 {
1480 
1481 	switch (uap->which) {
1482 	case 0:
1483 		return (freebsd32_msgctl(td,
1484 		    (struct freebsd32_msgctl_args *)&uap->a2));
1485 	case 2:
1486 		return (freebsd32_msgsnd(td,
1487 		    (struct freebsd32_msgsnd_args *)&uap->a2));
1488 	case 3:
1489 		return (freebsd32_msgrcv(td,
1490 		    (struct freebsd32_msgrcv_args *)&uap->a2));
1491 	default:
1492 		return (msgsys(td, (struct msgsys_args *)uap));
1493 	}
1494 }
1495 
1496 int
1497 freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
1498 {
1499 	struct msqid_ds msqbuf;
1500 	struct msqid_ds32 msqbuf32;
1501 	int error;
1502 
1503 	if (uap->cmd == IPC_SET) {
1504 		error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1505 		if (error)
1506 			return (error);
1507 		freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1508 		PTRIN_CP(msqbuf32, msqbuf, msg_first);
1509 		PTRIN_CP(msqbuf32, msqbuf, msg_last);
1510 		CP(msqbuf32, msqbuf, msg_cbytes);
1511 		CP(msqbuf32, msqbuf, msg_qnum);
1512 		CP(msqbuf32, msqbuf, msg_qbytes);
1513 		CP(msqbuf32, msqbuf, msg_lspid);
1514 		CP(msqbuf32, msqbuf, msg_lrpid);
1515 		CP(msqbuf32, msqbuf, msg_stime);
1516 		CP(msqbuf32, msqbuf, msg_pad1);
1517 		CP(msqbuf32, msqbuf, msg_rtime);
1518 		CP(msqbuf32, msqbuf, msg_pad2);
1519 		CP(msqbuf32, msqbuf, msg_ctime);
1520 		CP(msqbuf32, msqbuf, msg_pad3);
1521 		CP(msqbuf32, msqbuf, msg_pad4[0]);
1522 		CP(msqbuf32, msqbuf, msg_pad4[1]);
1523 		CP(msqbuf32, msqbuf, msg_pad4[2]);
1524 		CP(msqbuf32, msqbuf, msg_pad4[3]);
1525 	}
1526 	error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1527 	if (error)
1528 		return (error);
1529 	if (uap->cmd == IPC_STAT) {
1530 		freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1531 		PTROUT_CP(msqbuf, msqbuf32, msg_first);
1532 		PTROUT_CP(msqbuf, msqbuf32, msg_last);
1533 		CP(msqbuf, msqbuf32, msg_cbytes);
1534 		CP(msqbuf, msqbuf32, msg_qnum);
1535 		CP(msqbuf, msqbuf32, msg_qbytes);
1536 		CP(msqbuf, msqbuf32, msg_lspid);
1537 		CP(msqbuf, msqbuf32, msg_lrpid);
1538 		CP(msqbuf, msqbuf32, msg_stime);
1539 		CP(msqbuf, msqbuf32, msg_pad1);
1540 		CP(msqbuf, msqbuf32, msg_rtime);
1541 		CP(msqbuf, msqbuf32, msg_pad2);
1542 		CP(msqbuf, msqbuf32, msg_ctime);
1543 		CP(msqbuf, msqbuf32, msg_pad3);
1544 		CP(msqbuf, msqbuf32, msg_pad4[0]);
1545 		CP(msqbuf, msqbuf32, msg_pad4[1]);
1546 		CP(msqbuf, msqbuf32, msg_pad4[2]);
1547 		CP(msqbuf, msqbuf32, msg_pad4[3]);
1548 		error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1549 	}
1550 	return (error);
1551 }
1552 
1553 int
1554 freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1555 {
1556 	const void *msgp;
1557 	long mtype;
1558 	int32_t mtype32;
1559 	int error;
1560 
1561 	msgp = PTRIN(uap->msgp);
1562 	if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1563 		return (error);
1564 	mtype = mtype32;
1565 	return (kern_msgsnd(td, uap->msqid,
1566 	    (const char *)msgp + sizeof(mtype32),
1567 	    uap->msgsz, uap->msgflg, mtype));
1568 }
1569 
1570 int
1571 freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1572 {
1573 	void *msgp;
1574 	long mtype;
1575 	int32_t mtype32;
1576 	int error;
1577 
1578 	msgp = PTRIN(uap->msgp);
1579 	if ((error = kern_msgrcv(td, uap->msqid,
1580 	    (char *)msgp + sizeof(mtype32), uap->msgsz,
1581 	    uap->msgtyp, uap->msgflg, &mtype)) != 0)
1582 		return (error);
1583 	mtype32 = (int32_t)mtype;
1584 	return (copyout(&mtype32, msgp, sizeof(mtype32)));
1585 }
1586 
1587 int
1588 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1589 {
1590 
1591 	switch (uap->which) {
1592 	case 0:	{	/* shmat */
1593 		struct shmat_args ap;
1594 
1595 		ap.shmid = uap->a2;
1596 		ap.shmaddr = PTRIN(uap->a3);
1597 		ap.shmflg = uap->a4;
1598 		return (sysent[SYS_shmat].sy_call(td, &ap));
1599 	}
1600 	case 2: {	/* shmdt */
1601 		struct shmdt_args ap;
1602 
1603 		ap.shmaddr = PTRIN(uap->a2);
1604 		return (sysent[SYS_shmdt].sy_call(td, &ap));
1605 	}
1606 	case 3: {	/* shmget */
1607 		struct shmget_args ap;
1608 
1609 		ap.key = uap->a2;
1610 		ap.size = uap->a3;
1611 		ap.shmflg = uap->a4;
1612 		return (sysent[SYS_shmget].sy_call(td, &ap));
1613 	}
1614 	case 4: {	/* shmctl */
1615 		struct freebsd32_shmctl_args ap;
1616 
1617 		ap.shmid = uap->a2;
1618 		ap.cmd = uap->a3;
1619 		ap.buf = PTRIN(uap->a4);
1620 		return (freebsd32_shmctl(td, &ap));
1621 	}
1622 	case 1:		/* oshmctl */
1623 	default:
1624 		return (EINVAL);
1625 	}
1626 }
1627 
1628 int
1629 freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1630 {
1631 	int error = 0;
1632 	union {
1633 		struct shmid_ds shmid_ds;
1634 		struct shm_info shm_info;
1635 		struct shminfo shminfo;
1636 	} u;
1637 	union {
1638 		struct shmid_ds32 shmid_ds32;
1639 		struct shm_info32 shm_info32;
1640 		struct shminfo32 shminfo32;
1641 	} u32;
1642 	size_t sz;
1643 
1644 	if (uap->cmd == IPC_SET) {
1645 		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1646 		    sizeof(u32.shmid_ds32))))
1647 			goto done;
1648 		freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
1649 		    &u.shmid_ds.shm_perm);
1650 		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1651 		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1652 		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1653 		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1654 		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1655 		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1656 		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1657 		PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
1658 	}
1659 
1660 	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1661 	if (error)
1662 		goto done;
1663 
1664 	/* Cases in which we need to copyout */
1665 	switch (uap->cmd) {
1666 	case IPC_INFO:
1667 		CP(u.shminfo, u32.shminfo32, shmmax);
1668 		CP(u.shminfo, u32.shminfo32, shmmin);
1669 		CP(u.shminfo, u32.shminfo32, shmmni);
1670 		CP(u.shminfo, u32.shminfo32, shmseg);
1671 		CP(u.shminfo, u32.shminfo32, shmall);
1672 		error = copyout(&u32.shminfo32, uap->buf,
1673 		    sizeof(u32.shminfo32));
1674 		break;
1675 	case SHM_INFO:
1676 		CP(u.shm_info, u32.shm_info32, used_ids);
1677 		CP(u.shm_info, u32.shm_info32, shm_rss);
1678 		CP(u.shm_info, u32.shm_info32, shm_tot);
1679 		CP(u.shm_info, u32.shm_info32, shm_swp);
1680 		CP(u.shm_info, u32.shm_info32, swap_attempts);
1681 		CP(u.shm_info, u32.shm_info32, swap_successes);
1682 		error = copyout(&u32.shm_info32, uap->buf,
1683 		    sizeof(u32.shm_info32));
1684 		break;
1685 	case SHM_STAT:
1686 	case IPC_STAT:
1687 		freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
1688 		    &u32.shmid_ds32.shm_perm);
1689 		CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1690 		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1691 		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1692 		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1693 		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1694 		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1695 		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1696 		PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
1697 		error = copyout(&u32.shmid_ds32, uap->buf,
1698 		    sizeof(u32.shmid_ds32));
1699 		break;
1700 	}
1701 
1702 done:
1703 	if (error) {
1704 		/* Invalidate the return value */
1705 		td->td_retval[0] = -1;
1706 	}
1707 	return (error);
1708 }
1709 
1710 int
1711 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1712 {
1713 	struct pread_args ap;
1714 
1715 	ap.fd = uap->fd;
1716 	ap.buf = uap->buf;
1717 	ap.nbyte = uap->nbyte;
1718 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1719 	return (pread(td, &ap));
1720 }
1721 
1722 int
1723 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1724 {
1725 	struct pwrite_args ap;
1726 
1727 	ap.fd = uap->fd;
1728 	ap.buf = uap->buf;
1729 	ap.nbyte = uap->nbyte;
1730 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1731 	return (pwrite(td, &ap));
1732 }
1733 
1734 int
1735 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1736 {
1737 	int error;
1738 	struct lseek_args ap;
1739 	off_t pos;
1740 
1741 	ap.fd = uap->fd;
1742 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1743 	ap.whence = uap->whence;
1744 	error = lseek(td, &ap);
1745 	/* Expand the quad return into two parts for eax and edx */
1746 	pos = *(off_t *)(td->td_retval);
1747 	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1748 	td->td_retval[1] = pos >> 32;		/* %edx */
1749 	return error;
1750 }
1751 
1752 int
1753 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1754 {
1755 	struct truncate_args ap;
1756 
1757 	ap.path = uap->path;
1758 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1759 	return (truncate(td, &ap));
1760 }
1761 
1762 int
1763 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1764 {
1765 	struct ftruncate_args ap;
1766 
1767 	ap.fd = uap->fd;
1768 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1769 	return (ftruncate(td, &ap));
1770 }
1771 
1772 int
1773 freebsd32_getdirentries(struct thread *td,
1774     struct freebsd32_getdirentries_args *uap)
1775 {
1776 	long base;
1777 	int32_t base32;
1778 	int error;
1779 
1780 	error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
1781 	if (error)
1782 		return (error);
1783 	if (uap->basep != NULL) {
1784 		base32 = base;
1785 		error = copyout(&base32, uap->basep, sizeof(int32_t));
1786 	}
1787 	return (error);
1788 }
1789 
1790 #ifdef COMPAT_FREEBSD6
1791 /* versions with the 'int pad' argument */
1792 int
1793 freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
1794 {
1795 	struct pread_args ap;
1796 
1797 	ap.fd = uap->fd;
1798 	ap.buf = uap->buf;
1799 	ap.nbyte = uap->nbyte;
1800 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1801 	return (pread(td, &ap));
1802 }
1803 
1804 int
1805 freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
1806 {
1807 	struct pwrite_args ap;
1808 
1809 	ap.fd = uap->fd;
1810 	ap.buf = uap->buf;
1811 	ap.nbyte = uap->nbyte;
1812 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1813 	return (pwrite(td, &ap));
1814 }
1815 
1816 int
1817 freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
1818 {
1819 	int error;
1820 	struct lseek_args ap;
1821 	off_t pos;
1822 
1823 	ap.fd = uap->fd;
1824 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1825 	ap.whence = uap->whence;
1826 	error = lseek(td, &ap);
1827 	/* Expand the quad return into two parts for eax and edx */
1828 	pos = *(off_t *)(td->td_retval);
1829 	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1830 	td->td_retval[1] = pos >> 32;		/* %edx */
1831 	return error;
1832 }
1833 
1834 int
1835 freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
1836 {
1837 	struct truncate_args ap;
1838 
1839 	ap.path = uap->path;
1840 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1841 	return (truncate(td, &ap));
1842 }
1843 
1844 int
1845 freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
1846 {
1847 	struct ftruncate_args ap;
1848 
1849 	ap.fd = uap->fd;
1850 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1851 	return (ftruncate(td, &ap));
1852 }
1853 #endif /* COMPAT_FREEBSD6 */
1854 
1855 struct sf_hdtr32 {
1856 	uint32_t headers;
1857 	int hdr_cnt;
1858 	uint32_t trailers;
1859 	int trl_cnt;
1860 };
1861 
1862 static int
1863 freebsd32_do_sendfile(struct thread *td,
1864     struct freebsd32_sendfile_args *uap, int compat)
1865 {
1866 	struct sendfile_args ap;
1867 	struct sf_hdtr32 hdtr32;
1868 	struct sf_hdtr hdtr;
1869 	struct uio *hdr_uio, *trl_uio;
1870 	struct iovec32 *iov32;
1871 	int error;
1872 
1873 	hdr_uio = trl_uio = NULL;
1874 
1875 	ap.fd = uap->fd;
1876 	ap.s = uap->s;
1877 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1878 	ap.nbytes = uap->nbytes;
1879 	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
1880 	ap.sbytes = uap->sbytes;
1881 	ap.flags = uap->flags;
1882 
1883 	if (uap->hdtr != NULL) {
1884 		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1885 		if (error)
1886 			goto out;
1887 		PTRIN_CP(hdtr32, hdtr, headers);
1888 		CP(hdtr32, hdtr, hdr_cnt);
1889 		PTRIN_CP(hdtr32, hdtr, trailers);
1890 		CP(hdtr32, hdtr, trl_cnt);
1891 
1892 		if (hdtr.headers != NULL) {
1893 			iov32 = PTRIN(hdtr32.headers);
1894 			error = freebsd32_copyinuio(iov32,
1895 			    hdtr32.hdr_cnt, &hdr_uio);
1896 			if (error)
1897 				goto out;
1898 		}
1899 		if (hdtr.trailers != NULL) {
1900 			iov32 = PTRIN(hdtr32.trailers);
1901 			error = freebsd32_copyinuio(iov32,
1902 			    hdtr32.trl_cnt, &trl_uio);
1903 			if (error)
1904 				goto out;
1905 		}
1906 	}
1907 
1908 	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1909 out:
1910 	if (hdr_uio)
1911 		free(hdr_uio, M_IOV);
1912 	if (trl_uio)
1913 		free(trl_uio, M_IOV);
1914 	return (error);
1915 }
1916 
1917 #ifdef COMPAT_FREEBSD4
1918 int
1919 freebsd4_freebsd32_sendfile(struct thread *td,
1920     struct freebsd4_freebsd32_sendfile_args *uap)
1921 {
1922 	return (freebsd32_do_sendfile(td,
1923 	    (struct freebsd32_sendfile_args *)uap, 1));
1924 }
1925 #endif
1926 
1927 int
1928 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1929 {
1930 
1931 	return (freebsd32_do_sendfile(td, uap, 0));
1932 }
1933 
1934 static void
1935 copy_stat( struct stat *in, struct stat32 *out)
1936 {
1937 	CP(*in, *out, st_dev);
1938 	CP(*in, *out, st_ino);
1939 	CP(*in, *out, st_mode);
1940 	CP(*in, *out, st_nlink);
1941 	CP(*in, *out, st_uid);
1942 	CP(*in, *out, st_gid);
1943 	CP(*in, *out, st_rdev);
1944 	TS_CP(*in, *out, st_atimespec);
1945 	TS_CP(*in, *out, st_mtimespec);
1946 	TS_CP(*in, *out, st_ctimespec);
1947 	CP(*in, *out, st_size);
1948 	CP(*in, *out, st_blocks);
1949 	CP(*in, *out, st_blksize);
1950 	CP(*in, *out, st_flags);
1951 	CP(*in, *out, st_gen);
1952 }
1953 
1954 int
1955 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1956 {
1957 	struct stat sb;
1958 	struct stat32 sb32;
1959 	int error;
1960 
1961 	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1962 	if (error)
1963 		return (error);
1964 	copy_stat(&sb, &sb32);
1965 	error = copyout(&sb32, uap->ub, sizeof (sb32));
1966 	return (error);
1967 }
1968 
1969 int
1970 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1971 {
1972 	struct stat ub;
1973 	struct stat32 ub32;
1974 	int error;
1975 
1976 	error = kern_fstat(td, uap->fd, &ub);
1977 	if (error)
1978 		return (error);
1979 	copy_stat(&ub, &ub32);
1980 	error = copyout(&ub32, uap->ub, sizeof(ub32));
1981 	return (error);
1982 }
1983 
1984 int
1985 freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
1986 {
1987 	struct stat ub;
1988 	struct stat32 ub32;
1989 	int error;
1990 
1991 	error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
1992 	if (error)
1993 		return (error);
1994 	copy_stat(&ub, &ub32);
1995 	error = copyout(&ub32, uap->buf, sizeof(ub32));
1996 	return (error);
1997 }
1998 
1999 int
2000 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
2001 {
2002 	struct stat sb;
2003 	struct stat32 sb32;
2004 	int error;
2005 
2006 	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2007 	if (error)
2008 		return (error);
2009 	copy_stat(&sb, &sb32);
2010 	error = copyout(&sb32, uap->ub, sizeof (sb32));
2011 	return (error);
2012 }
2013 
2014 /*
2015  * MPSAFE
2016  */
2017 int
2018 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
2019 {
2020 	int error, name[CTL_MAXNAME];
2021 	size_t j, oldlen;
2022 
2023 	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
2024 		return (EINVAL);
2025  	error = copyin(uap->name, name, uap->namelen * sizeof(int));
2026  	if (error)
2027 		return (error);
2028 	if (uap->oldlenp)
2029 		oldlen = fuword32(uap->oldlenp);
2030 	else
2031 		oldlen = 0;
2032 	error = userland_sysctl(td, name, uap->namelen,
2033 		uap->old, &oldlen, 1,
2034 		uap->new, uap->newlen, &j, SCTL_MASK32);
2035 	if (error && error != ENOMEM)
2036 		return (error);
2037 	if (uap->oldlenp)
2038 		suword32(uap->oldlenp, j);
2039 	return (0);
2040 }
2041 
2042 int
2043 freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
2044 {
2045 	uint32_t version;
2046 	int error;
2047 	struct jail j;
2048 
2049 	error = copyin(uap->jail, &version, sizeof(uint32_t));
2050 	if (error)
2051 		return (error);
2052 
2053 	switch (version) {
2054 	case 0:
2055 	{
2056 		/* FreeBSD single IPv4 jails. */
2057 		struct jail32_v0 j32_v0;
2058 
2059 		bzero(&j, sizeof(struct jail));
2060 		error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
2061 		if (error)
2062 			return (error);
2063 		CP(j32_v0, j, version);
2064 		PTRIN_CP(j32_v0, j, path);
2065 		PTRIN_CP(j32_v0, j, hostname);
2066 		j.ip4s = j32_v0.ip_number;
2067 		break;
2068 	}
2069 
2070 	case 1:
2071 		/*
2072 		 * Version 1 was used by multi-IPv4 jail implementations
2073 		 * that never made it into the official kernel.
2074 		 */
2075 		return (EINVAL);
2076 
2077 	case 2:	/* JAIL_API_VERSION */
2078 	{
2079 		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
2080 		struct jail32 j32;
2081 
2082 		error = copyin(uap->jail, &j32, sizeof(struct jail32));
2083 		if (error)
2084 			return (error);
2085 		CP(j32, j, version);
2086 		PTRIN_CP(j32, j, path);
2087 		PTRIN_CP(j32, j, hostname);
2088 		PTRIN_CP(j32, j, jailname);
2089 		CP(j32, j, ip4s);
2090 		CP(j32, j, ip6s);
2091 		PTRIN_CP(j32, j, ip4);
2092 		PTRIN_CP(j32, j, ip6);
2093 		break;
2094 	}
2095 
2096 	default:
2097 		/* Sci-Fi jails are not supported, sorry. */
2098 		return (EINVAL);
2099 	}
2100 	return (kern_jail(td, &j));
2101 }
2102 
2103 int
2104 freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
2105 {
2106 	struct uio *auio;
2107 	int error;
2108 
2109 	/* Check that we have an even number of iovecs. */
2110 	if (uap->iovcnt & 1)
2111 		return (EINVAL);
2112 
2113 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2114 	if (error)
2115 		return (error);
2116 	error = kern_jail_set(td, auio, uap->flags);
2117 	free(auio, M_IOV);
2118 	return (error);
2119 }
2120 
2121 int
2122 freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
2123 {
2124 	struct iovec32 iov32;
2125 	struct uio *auio;
2126 	int error, i;
2127 
2128 	/* Check that we have an even number of iovecs. */
2129 	if (uap->iovcnt & 1)
2130 		return (EINVAL);
2131 
2132 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2133 	if (error)
2134 		return (error);
2135 	error = kern_jail_get(td, auio, uap->flags);
2136 	if (error == 0)
2137 		for (i = 0; i < uap->iovcnt; i++) {
2138 			PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
2139 			CP(auio->uio_iov[i], iov32, iov_len);
2140 			error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
2141 			if (error != 0)
2142 				break;
2143 		}
2144 	free(auio, M_IOV);
2145 	return (error);
2146 }
2147 
2148 int
2149 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
2150 {
2151 	struct sigaction32 s32;
2152 	struct sigaction sa, osa, *sap;
2153 	int error;
2154 
2155 	if (uap->act) {
2156 		error = copyin(uap->act, &s32, sizeof(s32));
2157 		if (error)
2158 			return (error);
2159 		sa.sa_handler = PTRIN(s32.sa_u);
2160 		CP(s32, sa, sa_flags);
2161 		CP(s32, sa, sa_mask);
2162 		sap = &sa;
2163 	} else
2164 		sap = NULL;
2165 	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
2166 	if (error == 0 && uap->oact != NULL) {
2167 		s32.sa_u = PTROUT(osa.sa_handler);
2168 		CP(osa, s32, sa_flags);
2169 		CP(osa, s32, sa_mask);
2170 		error = copyout(&s32, uap->oact, sizeof(s32));
2171 	}
2172 	return (error);
2173 }
2174 
2175 #ifdef COMPAT_FREEBSD4
2176 int
2177 freebsd4_freebsd32_sigaction(struct thread *td,
2178 			     struct freebsd4_freebsd32_sigaction_args *uap)
2179 {
2180 	struct sigaction32 s32;
2181 	struct sigaction sa, osa, *sap;
2182 	int error;
2183 
2184 	if (uap->act) {
2185 		error = copyin(uap->act, &s32, sizeof(s32));
2186 		if (error)
2187 			return (error);
2188 		sa.sa_handler = PTRIN(s32.sa_u);
2189 		CP(s32, sa, sa_flags);
2190 		CP(s32, sa, sa_mask);
2191 		sap = &sa;
2192 	} else
2193 		sap = NULL;
2194 	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
2195 	if (error == 0 && uap->oact != NULL) {
2196 		s32.sa_u = PTROUT(osa.sa_handler);
2197 		CP(osa, s32, sa_flags);
2198 		CP(osa, s32, sa_mask);
2199 		error = copyout(&s32, uap->oact, sizeof(s32));
2200 	}
2201 	return (error);
2202 }
2203 #endif
2204 
2205 #ifdef COMPAT_43
2206 struct osigaction32 {
2207 	u_int32_t	sa_u;
2208 	osigset_t	sa_mask;
2209 	int		sa_flags;
2210 };
2211 
2212 #define	ONSIG	32
2213 
2214 int
2215 ofreebsd32_sigaction(struct thread *td,
2216 			     struct ofreebsd32_sigaction_args *uap)
2217 {
2218 	struct osigaction32 s32;
2219 	struct sigaction sa, osa, *sap;
2220 	int error;
2221 
2222 	if (uap->signum <= 0 || uap->signum >= ONSIG)
2223 		return (EINVAL);
2224 
2225 	if (uap->nsa) {
2226 		error = copyin(uap->nsa, &s32, sizeof(s32));
2227 		if (error)
2228 			return (error);
2229 		sa.sa_handler = PTRIN(s32.sa_u);
2230 		CP(s32, sa, sa_flags);
2231 		OSIG2SIG(s32.sa_mask, sa.sa_mask);
2232 		sap = &sa;
2233 	} else
2234 		sap = NULL;
2235 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2236 	if (error == 0 && uap->osa != NULL) {
2237 		s32.sa_u = PTROUT(osa.sa_handler);
2238 		CP(osa, s32, sa_flags);
2239 		SIG2OSIG(osa.sa_mask, s32.sa_mask);
2240 		error = copyout(&s32, uap->osa, sizeof(s32));
2241 	}
2242 	return (error);
2243 }
2244 
2245 int
2246 ofreebsd32_sigprocmask(struct thread *td,
2247 			       struct ofreebsd32_sigprocmask_args *uap)
2248 {
2249 	sigset_t set, oset;
2250 	int error;
2251 
2252 	OSIG2SIG(uap->mask, set);
2253 	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
2254 	SIG2OSIG(oset, td->td_retval[0]);
2255 	return (error);
2256 }
2257 
2258 int
2259 ofreebsd32_sigpending(struct thread *td,
2260 			      struct ofreebsd32_sigpending_args *uap)
2261 {
2262 	struct proc *p = td->td_proc;
2263 	sigset_t siglist;
2264 
2265 	PROC_LOCK(p);
2266 	siglist = p->p_siglist;
2267 	SIGSETOR(siglist, td->td_siglist);
2268 	PROC_UNLOCK(p);
2269 	SIG2OSIG(siglist, td->td_retval[0]);
2270 	return (0);
2271 }
2272 
2273 struct sigvec32 {
2274 	u_int32_t	sv_handler;
2275 	int		sv_mask;
2276 	int		sv_flags;
2277 };
2278 
2279 int
2280 ofreebsd32_sigvec(struct thread *td,
2281 			  struct ofreebsd32_sigvec_args *uap)
2282 {
2283 	struct sigvec32 vec;
2284 	struct sigaction sa, osa, *sap;
2285 	int error;
2286 
2287 	if (uap->signum <= 0 || uap->signum >= ONSIG)
2288 		return (EINVAL);
2289 
2290 	if (uap->nsv) {
2291 		error = copyin(uap->nsv, &vec, sizeof(vec));
2292 		if (error)
2293 			return (error);
2294 		sa.sa_handler = PTRIN(vec.sv_handler);
2295 		OSIG2SIG(vec.sv_mask, sa.sa_mask);
2296 		sa.sa_flags = vec.sv_flags;
2297 		sa.sa_flags ^= SA_RESTART;
2298 		sap = &sa;
2299 	} else
2300 		sap = NULL;
2301 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2302 	if (error == 0 && uap->osv != NULL) {
2303 		vec.sv_handler = PTROUT(osa.sa_handler);
2304 		SIG2OSIG(osa.sa_mask, vec.sv_mask);
2305 		vec.sv_flags = osa.sa_flags;
2306 		vec.sv_flags &= ~SA_NOCLDWAIT;
2307 		vec.sv_flags ^= SA_RESTART;
2308 		error = copyout(&vec, uap->osv, sizeof(vec));
2309 	}
2310 	return (error);
2311 }
2312 
2313 int
2314 ofreebsd32_sigblock(struct thread *td,
2315 			    struct ofreebsd32_sigblock_args *uap)
2316 {
2317 	struct proc *p = td->td_proc;
2318 	sigset_t set;
2319 
2320 	OSIG2SIG(uap->mask, set);
2321 	SIG_CANTMASK(set);
2322 	PROC_LOCK(p);
2323 	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2324 	SIGSETOR(td->td_sigmask, set);
2325 	PROC_UNLOCK(p);
2326 	return (0);
2327 }
2328 
2329 int
2330 ofreebsd32_sigsetmask(struct thread *td,
2331 			      struct ofreebsd32_sigsetmask_args *uap)
2332 {
2333 	struct proc *p = td->td_proc;
2334 	sigset_t set;
2335 
2336 	OSIG2SIG(uap->mask, set);
2337 	SIG_CANTMASK(set);
2338 	PROC_LOCK(p);
2339 	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2340 	SIGSETLO(td->td_sigmask, set);
2341 	signotify(td);
2342 	PROC_UNLOCK(p);
2343 	return (0);
2344 }
2345 
2346 int
2347 ofreebsd32_sigsuspend(struct thread *td,
2348 			      struct ofreebsd32_sigsuspend_args *uap)
2349 {
2350 	struct proc *p = td->td_proc;
2351 	sigset_t mask;
2352 
2353 	PROC_LOCK(p);
2354 	td->td_oldsigmask = td->td_sigmask;
2355 	td->td_pflags |= TDP_OLDMASK;
2356 	OSIG2SIG(uap->mask, mask);
2357 	SIG_CANTMASK(mask);
2358 	SIGSETLO(td->td_sigmask, mask);
2359 	signotify(td);
2360 	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
2361 		/* void */;
2362 	PROC_UNLOCK(p);
2363 	/* always return EINTR rather than ERESTART... */
2364 	return (EINTR);
2365 }
2366 
2367 struct sigstack32 {
2368 	u_int32_t	ss_sp;
2369 	int		ss_onstack;
2370 };
2371 
2372 int
2373 ofreebsd32_sigstack(struct thread *td,
2374 			    struct ofreebsd32_sigstack_args *uap)
2375 {
2376 	struct sigstack32 s32;
2377 	struct sigstack nss, oss;
2378 	int error = 0, unss;
2379 
2380 	if (uap->nss != NULL) {
2381 		error = copyin(uap->nss, &s32, sizeof(s32));
2382 		if (error)
2383 			return (error);
2384 		nss.ss_sp = PTRIN(s32.ss_sp);
2385 		CP(s32, nss, ss_onstack);
2386 		unss = 1;
2387 	} else {
2388 		unss = 0;
2389 	}
2390 	oss.ss_sp = td->td_sigstk.ss_sp;
2391 	oss.ss_onstack = sigonstack(cpu_getstack(td));
2392 	if (unss) {
2393 		td->td_sigstk.ss_sp = nss.ss_sp;
2394 		td->td_sigstk.ss_size = 0;
2395 		td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
2396 		td->td_pflags |= TDP_ALTSTACK;
2397 	}
2398 	if (uap->oss != NULL) {
2399 		s32.ss_sp = PTROUT(oss.ss_sp);
2400 		CP(oss, s32, ss_onstack);
2401 		error = copyout(&s32, uap->oss, sizeof(s32));
2402 	}
2403 	return (error);
2404 }
2405 #endif
2406 
2407 int
2408 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2409 {
2410 	struct timespec32 rmt32, rqt32;
2411 	struct timespec rmt, rqt;
2412 	int error;
2413 
2414 	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2415 	if (error)
2416 		return (error);
2417 
2418 	CP(rqt32, rqt, tv_sec);
2419 	CP(rqt32, rqt, tv_nsec);
2420 
2421 	if (uap->rmtp &&
2422 	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2423 		return (EFAULT);
2424 	error = kern_nanosleep(td, &rqt, &rmt);
2425 	if (error && uap->rmtp) {
2426 		int error2;
2427 
2428 		CP(rmt, rmt32, tv_sec);
2429 		CP(rmt, rmt32, tv_nsec);
2430 
2431 		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2432 		if (error2)
2433 			error = error2;
2434 	}
2435 	return (error);
2436 }
2437 
2438 int
2439 freebsd32_clock_gettime(struct thread *td,
2440 			struct freebsd32_clock_gettime_args *uap)
2441 {
2442 	struct timespec	ats;
2443 	struct timespec32 ats32;
2444 	int error;
2445 
2446 	error = kern_clock_gettime(td, uap->clock_id, &ats);
2447 	if (error == 0) {
2448 		CP(ats, ats32, tv_sec);
2449 		CP(ats, ats32, tv_nsec);
2450 		error = copyout(&ats32, uap->tp, sizeof(ats32));
2451 	}
2452 	return (error);
2453 }
2454 
2455 int
2456 freebsd32_clock_settime(struct thread *td,
2457 			struct freebsd32_clock_settime_args *uap)
2458 {
2459 	struct timespec	ats;
2460 	struct timespec32 ats32;
2461 	int error;
2462 
2463 	error = copyin(uap->tp, &ats32, sizeof(ats32));
2464 	if (error)
2465 		return (error);
2466 	CP(ats32, ats, tv_sec);
2467 	CP(ats32, ats, tv_nsec);
2468 
2469 	return (kern_clock_settime(td, uap->clock_id, &ats));
2470 }
2471 
2472 int
2473 freebsd32_clock_getres(struct thread *td,
2474 		       struct freebsd32_clock_getres_args *uap)
2475 {
2476 	struct timespec	ts;
2477 	struct timespec32 ts32;
2478 	int error;
2479 
2480 	if (uap->tp == NULL)
2481 		return (0);
2482 	error = kern_clock_getres(td, uap->clock_id, &ts);
2483 	if (error == 0) {
2484 		CP(ts, ts32, tv_sec);
2485 		CP(ts, ts32, tv_nsec);
2486 		error = copyout(&ts32, uap->tp, sizeof(ts32));
2487 	}
2488 	return (error);
2489 }
2490 
2491 int
2492 freebsd32_thr_new(struct thread *td,
2493 		  struct freebsd32_thr_new_args *uap)
2494 {
2495 	struct thr_param32 param32;
2496 	struct thr_param param;
2497 	int error;
2498 
2499 	if (uap->param_size < 0 ||
2500 	    uap->param_size > sizeof(struct thr_param32))
2501 		return (EINVAL);
2502 	bzero(&param, sizeof(struct thr_param));
2503 	bzero(&param32, sizeof(struct thr_param32));
2504 	error = copyin(uap->param, &param32, uap->param_size);
2505 	if (error != 0)
2506 		return (error);
2507 	param.start_func = PTRIN(param32.start_func);
2508 	param.arg = PTRIN(param32.arg);
2509 	param.stack_base = PTRIN(param32.stack_base);
2510 	param.stack_size = param32.stack_size;
2511 	param.tls_base = PTRIN(param32.tls_base);
2512 	param.tls_size = param32.tls_size;
2513 	param.child_tid = PTRIN(param32.child_tid);
2514 	param.parent_tid = PTRIN(param32.parent_tid);
2515 	param.flags = param32.flags;
2516 	param.rtp = PTRIN(param32.rtp);
2517 	param.spare[0] = PTRIN(param32.spare[0]);
2518 	param.spare[1] = PTRIN(param32.spare[1]);
2519 	param.spare[2] = PTRIN(param32.spare[2]);
2520 
2521 	return (kern_thr_new(td, &param));
2522 }
2523 
2524 int
2525 freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2526 {
2527 	struct timespec32 ts32;
2528 	struct timespec ts, *tsp;
2529 	int error;
2530 
2531 	error = 0;
2532 	tsp = NULL;
2533 	if (uap->timeout != NULL) {
2534 		error = copyin((const void *)uap->timeout, (void *)&ts32,
2535 		    sizeof(struct timespec32));
2536 		if (error != 0)
2537 			return (error);
2538 		ts.tv_sec = ts32.tv_sec;
2539 		ts.tv_nsec = ts32.tv_nsec;
2540 		tsp = &ts;
2541 	}
2542 	return (kern_thr_suspend(td, tsp));
2543 }
2544 
2545 void
2546 siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2547 {
2548 	bzero(dst, sizeof(*dst));
2549 	dst->si_signo = src->si_signo;
2550 	dst->si_errno = src->si_errno;
2551 	dst->si_code = src->si_code;
2552 	dst->si_pid = src->si_pid;
2553 	dst->si_uid = src->si_uid;
2554 	dst->si_status = src->si_status;
2555 	dst->si_addr = (uintptr_t)src->si_addr;
2556 	dst->si_value.sigval_int = src->si_value.sival_int;
2557 	dst->si_timerid = src->si_timerid;
2558 	dst->si_overrun = src->si_overrun;
2559 }
2560 
2561 int
2562 freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2563 {
2564 	struct timespec32 ts32;
2565 	struct timespec ts;
2566 	struct timespec *timeout;
2567 	sigset_t set;
2568 	ksiginfo_t ksi;
2569 	struct siginfo32 si32;
2570 	int error;
2571 
2572 	if (uap->timeout) {
2573 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
2574 		if (error)
2575 			return (error);
2576 		ts.tv_sec = ts32.tv_sec;
2577 		ts.tv_nsec = ts32.tv_nsec;
2578 		timeout = &ts;
2579 	} else
2580 		timeout = NULL;
2581 
2582 	error = copyin(uap->set, &set, sizeof(set));
2583 	if (error)
2584 		return (error);
2585 
2586 	error = kern_sigtimedwait(td, set, &ksi, timeout);
2587 	if (error)
2588 		return (error);
2589 
2590 	if (uap->info) {
2591 		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2592 		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2593 	}
2594 
2595 	if (error == 0)
2596 		td->td_retval[0] = ksi.ksi_signo;
2597 	return (error);
2598 }
2599 
2600 /*
2601  * MPSAFE
2602  */
2603 int
2604 freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2605 {
2606 	ksiginfo_t ksi;
2607 	struct siginfo32 si32;
2608 	sigset_t set;
2609 	int error;
2610 
2611 	error = copyin(uap->set, &set, sizeof(set));
2612 	if (error)
2613 		return (error);
2614 
2615 	error = kern_sigtimedwait(td, set, &ksi, NULL);
2616 	if (error)
2617 		return (error);
2618 
2619 	if (uap->info) {
2620 		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2621 		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2622 	}
2623 	if (error == 0)
2624 		td->td_retval[0] = ksi.ksi_signo;
2625 	return (error);
2626 }
2627 
2628 int
2629 freebsd32_cpuset_setid(struct thread *td,
2630     struct freebsd32_cpuset_setid_args *uap)
2631 {
2632 	struct cpuset_setid_args ap;
2633 
2634 	ap.which = uap->which;
2635 	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2636 	ap.setid = uap->setid;
2637 
2638 	return (cpuset_setid(td, &ap));
2639 }
2640 
2641 int
2642 freebsd32_cpuset_getid(struct thread *td,
2643     struct freebsd32_cpuset_getid_args *uap)
2644 {
2645 	struct cpuset_getid_args ap;
2646 
2647 	ap.level = uap->level;
2648 	ap.which = uap->which;
2649 	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2650 	ap.setid = uap->setid;
2651 
2652 	return (cpuset_getid(td, &ap));
2653 }
2654 
2655 int
2656 freebsd32_cpuset_getaffinity(struct thread *td,
2657     struct freebsd32_cpuset_getaffinity_args *uap)
2658 {
2659 	struct cpuset_getaffinity_args ap;
2660 
2661 	ap.level = uap->level;
2662 	ap.which = uap->which;
2663 	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2664 	ap.cpusetsize = uap->cpusetsize;
2665 	ap.mask = uap->mask;
2666 
2667 	return (cpuset_getaffinity(td, &ap));
2668 }
2669 
2670 int
2671 freebsd32_cpuset_setaffinity(struct thread *td,
2672     struct freebsd32_cpuset_setaffinity_args *uap)
2673 {
2674 	struct cpuset_setaffinity_args ap;
2675 
2676 	ap.level = uap->level;
2677 	ap.which = uap->which;
2678 	ap.id = (uap->idlo | ((id_t)uap->idhi << 32));
2679 	ap.cpusetsize = uap->cpusetsize;
2680 	ap.mask = uap->mask;
2681 
2682 	return (cpuset_setaffinity(td, &ap));
2683 }
2684 
2685 int
2686 freebsd32_nmount(struct thread *td,
2687     struct freebsd32_nmount_args /* {
2688     	struct iovec *iovp;
2689     	unsigned int iovcnt;
2690     	int flags;
2691     } */ *uap)
2692 {
2693 	struct uio *auio;
2694 	int error;
2695 
2696 	AUDIT_ARG(fflags, uap->flags);
2697 
2698 	/*
2699 	 * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
2700 	 * userspace to set this flag, but we must filter it out if we want
2701 	 * MNT_UPDATE on the root file system to work.
2702 	 * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try().
2703 	 */
2704 	uap->flags &= ~MNT_ROOTFS;
2705 
2706 	/*
2707 	 * check that we have an even number of iovec's
2708 	 * and that we have at least two options.
2709 	 */
2710 	if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
2711 		return (EINVAL);
2712 
2713 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2714 	if (error)
2715 		return (error);
2716 	error = vfs_donmount(td, uap->flags, auio);
2717 
2718 	free(auio, M_IOV);
2719 	return error;
2720 }
2721 
2722 #if 0
2723 int
2724 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2725 {
2726 	struct yyy32 *p32, s32;
2727 	struct yyy *p = NULL, s;
2728 	struct xxx_arg ap;
2729 	int error;
2730 
2731 	if (uap->zzz) {
2732 		error = copyin(uap->zzz, &s32, sizeof(s32));
2733 		if (error)
2734 			return (error);
2735 		/* translate in */
2736 		p = &s;
2737 	}
2738 	error = kern_xxx(td, p);
2739 	if (error)
2740 		return (error);
2741 	if (uap->zzz) {
2742 		/* translate out */
2743 		error = copyout(&s32, p32, sizeof(s32));
2744 	}
2745 	return (error);
2746 }
2747 #endif
2748 
2749 int
2750 syscall32_register(int *offset, struct sysent *new_sysent,
2751     struct sysent *old_sysent)
2752 {
2753 	if (*offset == NO_SYSCALL) {
2754 		int i;
2755 
2756 		for (i = 1; i < SYS_MAXSYSCALL; ++i)
2757 			if (freebsd32_sysent[i].sy_call ==
2758 			    (sy_call_t *)lkmnosys)
2759 				break;
2760 		if (i == SYS_MAXSYSCALL)
2761 			return (ENFILE);
2762 		*offset = i;
2763 	} else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
2764 		return (EINVAL);
2765 	else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
2766 	    freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
2767 		return (EEXIST);
2768 
2769 	*old_sysent = freebsd32_sysent[*offset];
2770 	freebsd32_sysent[*offset] = *new_sysent;
2771 	return 0;
2772 }
2773 
2774 int
2775 syscall32_deregister(int *offset, struct sysent *old_sysent)
2776 {
2777 
2778 	if (*offset)
2779 		freebsd32_sysent[*offset] = *old_sysent;
2780 	return 0;
2781 }
2782 
2783 int
2784 syscall32_module_handler(struct module *mod, int what, void *arg)
2785 {
2786 	struct syscall_module_data *data = (struct syscall_module_data*)arg;
2787 	modspecific_t ms;
2788 	int error;
2789 
2790 	switch (what) {
2791 	case MOD_LOAD:
2792 		error = syscall32_register(data->offset, data->new_sysent,
2793 		    &data->old_sysent);
2794 		if (error) {
2795 			/* Leave a mark so we know to safely unload below. */
2796 			data->offset = NULL;
2797 			return error;
2798 		}
2799 		ms.intval = *data->offset;
2800 		MOD_XLOCK;
2801 		module_setspecific(mod, &ms);
2802 		MOD_XUNLOCK;
2803 		if (data->chainevh)
2804 			error = data->chainevh(mod, what, data->chainarg);
2805 		return (error);
2806 	case MOD_UNLOAD:
2807 		/*
2808 		 * MOD_LOAD failed, so just return without calling the
2809 		 * chained handler since we didn't pass along the MOD_LOAD
2810 		 * event.
2811 		 */
2812 		if (data->offset == NULL)
2813 			return (0);
2814 		if (data->chainevh) {
2815 			error = data->chainevh(mod, what, data->chainarg);
2816 			if (error)
2817 				return (error);
2818 		}
2819 		error = syscall32_deregister(data->offset, &data->old_sysent);
2820 		return (error);
2821 	default:
2822 		error = EOPNOTSUPP;
2823 		if (data->chainevh)
2824 			error = data->chainevh(mod, what, data->chainarg);
2825 		return (error);
2826 	}
2827 }
2828