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