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