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: src/sys/compat/freebsd32/freebsd32_misc.c,v 1.86 2008/12/29 12:58:45 ed Exp $");
29
30 #include "opt_compat.h"
31
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/clock.h>
35 #include <sys/exec.h>
36 #include <sys/fcntl.h>
37 #include <sys/filedesc.h>
38 #include <sys/imgact.h>
39 #include <sys/jail.h>
40 #include <sys/kernel.h>
41 #include <sys/limits.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/file.h> /* Must come after sys/malloc.h */
45 #include <sys/mbuf.h>
46 #include <sys/mman.h>
47 #include <sys/module.h>
48 #include <sys/mount.h>
49 #include <sys/mutex.h>
50 #include <sys/namei.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/thr.h>
70 #include <sys/unistd.h>
71 #include <sys/ucontext.h>
72 #include <sys/vnode.h>
73 #include <sys/wait.h>
74 #include <sys/ipc.h>
75 #include <sys/msg.h>
76 #include <sys/sem.h>
77 #include <sys/shm.h>
78
79 #include <vm/vm.h>
80 #include <vm/vm_kern.h>
81 #include <vm/vm_param.h>
82 #include <vm/pmap.h>
83 #include <vm/vm_map.h>
84 #include <vm/vm_object.h>
85 #include <vm/vm_extern.h>
86
87 #include <machine/cpu.h>
88
89 #include <security/audit/audit.h>
90
91 #include <compat/freebsd32/freebsd32_util.h>
92 #include <compat/freebsd32/freebsd32.h>
93 #include <compat/freebsd32/freebsd32_ipc.h>
94 #include <compat/freebsd32/freebsd32_signal.h>
95 #include <compat/freebsd32/freebsd32_proto.h>
96
97 CTASSERT(sizeof(struct timeval32) == 8);
98 CTASSERT(sizeof(struct timespec32) == 8);
99 CTASSERT(sizeof(struct itimerval32) == 16);
100 CTASSERT(sizeof(struct statfs32) == 256);
101 CTASSERT(sizeof(struct rusage32) == 72);
102 CTASSERT(sizeof(struct sigaltstack32) == 12);
103 CTASSERT(sizeof(struct kevent32) == 20);
104 CTASSERT(sizeof(struct iovec32) == 8);
105 CTASSERT(sizeof(struct msghdr32) == 28);
106 CTASSERT(sizeof(struct stat32) == 96);
107 CTASSERT(sizeof(struct sigaction32) == 24);
108
109 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
110 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
111
112 int
113 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
114 {
115 int error, status;
116 struct rusage32 ru32;
117 struct rusage ru, *rup;
118
119 if (uap->rusage != NULL)
120 rup = &ru;
121 else
122 rup = NULL;
123 error = kern_wait(td, uap->pid, &status, uap->options, rup);
124 if (error)
125 return (error);
126 if (uap->status != NULL)
127 error = copyout(&status, uap->status, sizeof(status));
128 if (uap->rusage != NULL && error == 0) {
129 TV_CP(ru, ru32, ru_utime);
130 TV_CP(ru, ru32, ru_stime);
131 CP(ru, ru32, ru_maxrss);
132 CP(ru, ru32, ru_ixrss);
133 CP(ru, ru32, ru_idrss);
134 CP(ru, ru32, ru_isrss);
135 CP(ru, ru32, ru_minflt);
136 CP(ru, ru32, ru_majflt);
137 CP(ru, ru32, ru_nswap);
138 CP(ru, ru32, ru_inblock);
139 CP(ru, ru32, ru_oublock);
140 CP(ru, ru32, ru_msgsnd);
141 CP(ru, ru32, ru_msgrcv);
142 CP(ru, ru32, ru_nsignals);
143 CP(ru, ru32, ru_nvcsw);
144 CP(ru, ru32, ru_nivcsw);
145 error = copyout(&ru32, uap->rusage, sizeof(ru32));
146 }
147 return (error);
148 }
149
150 #ifdef COMPAT_FREEBSD4
151 static void
152 copy_statfs(struct statfs *in, struct statfs32 *out)
153 {
154
155 statfs_scale_blocks(in, INT32_MAX);
156 bzero(out, sizeof(*out));
157 CP(*in, *out, f_bsize);
158 out->f_iosize = MIN(in->f_iosize, INT32_MAX);
159 CP(*in, *out, f_blocks);
160 CP(*in, *out, f_bfree);
161 CP(*in, *out, f_bavail);
162 out->f_files = MIN(in->f_files, INT32_MAX);
163 out->f_ffree = MIN(in->f_ffree, INT32_MAX);
164 CP(*in, *out, f_fsid);
165 CP(*in, *out, f_owner);
166 CP(*in, *out, f_type);
167 CP(*in, *out, f_flags);
168 out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
169 out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
170 strlcpy(out->f_fstypename,
171 in->f_fstypename, MFSNAMELEN);
172 strlcpy(out->f_mntonname,
173 in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
174 out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
175 out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
176 strlcpy(out->f_mntfromname,
177 in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
178 }
179 #endif
180
181 #ifdef COMPAT_FREEBSD4
182 int
183 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
184 {
185 struct statfs *buf, *sp;
186 struct statfs32 stat32;
187 size_t count, size;
188 int error;
189
190 count = uap->bufsize / sizeof(struct statfs32);
191 size = count * sizeof(struct statfs);
192 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
193 if (size > 0) {
194 count = td->td_retval[0];
195 sp = buf;
196 while (count > 0 && error == 0) {
197 copy_statfs(sp, &stat32);
198 error = copyout(&stat32, uap->buf, sizeof(stat32));
199 sp++;
200 uap->buf++;
201 count--;
202 }
203 free(buf, M_TEMP);
204 }
205 return (error);
206 }
207 #endif
208
209 int
210 freebsd32_sigaltstack(struct thread *td,
211 struct freebsd32_sigaltstack_args *uap)
212 {
213 struct sigaltstack32 s32;
214 struct sigaltstack ss, oss, *ssp;
215 int error;
216
217 if (uap->ss != NULL) {
218 error = copyin(uap->ss, &s32, sizeof(s32));
219 if (error)
220 return (error);
221 PTRIN_CP(s32, ss, ss_sp);
222 CP(s32, ss, ss_size);
223 CP(s32, ss, ss_flags);
224 ssp = &ss;
225 } else
226 ssp = NULL;
227 error = kern_sigaltstack(td, ssp, &oss);
228 if (error == 0 && uap->oss != NULL) {
229 PTROUT_CP(oss, s32, ss_sp);
230 CP(oss, s32, ss_size);
231 CP(oss, s32, ss_flags);
232 error = copyout(&s32, uap->oss, sizeof(s32));
233 }
234 return (error);
235 }
236
237 /*
238 * Custom version of exec_copyin_args() so that we can translate
239 * the pointers.
240 */
241 static int
242 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
243 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
244 {
245 char *argp, *envp;
246 u_int32_t *p32, arg;
247 size_t length;
248 int error;
249
250 bzero(args, sizeof(*args));
251 if (argv == NULL)
252 return (EFAULT);
253
254 /*
255 * Allocate temporary demand zeroed space for argument and
256 * environment strings
257 */
258 args->buf = (char *) kmem_alloc_wait(exec_map,
259 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
260 if (args->buf == NULL)
261 return (ENOMEM);
262 args->begin_argv = args->buf;
263 args->endp = args->begin_argv;
264 args->stringspace = ARG_MAX;
265
266 /*
267 * Copy the file name.
268 */
269 if (fname != NULL) {
270 args->fname = args->buf + ARG_MAX;
271 error = (segflg == UIO_SYSSPACE) ?
272 copystr(fname, args->fname, PATH_MAX, &length) :
273 copyinstr(fname, args->fname, PATH_MAX, &length);
274 if (error != 0)
275 goto err_exit;
276 } else
277 args->fname = NULL;
278
279 /*
280 * extract arguments first
281 */
282 p32 = argv;
283 for (;;) {
284 error = copyin(p32++, &arg, sizeof(arg));
285 if (error)
286 goto err_exit;
287 if (arg == 0)
288 break;
289 argp = PTRIN(arg);
290 error = copyinstr(argp, args->endp, args->stringspace, &length);
291 if (error) {
292 if (error == ENAMETOOLONG)
293 error = E2BIG;
294 goto err_exit;
295 }
296 args->stringspace -= length;
297 args->endp += length;
298 args->argc++;
299 }
300
301 args->begin_envv = args->endp;
302
303 /*
304 * extract environment strings
305 */
306 if (envv) {
307 p32 = envv;
308 for (;;) {
309 error = copyin(p32++, &arg, sizeof(arg));
310 if (error)
311 goto err_exit;
312 if (arg == 0)
313 break;
314 envp = PTRIN(arg);
315 error = copyinstr(envp, args->endp, args->stringspace,
316 &length);
317 if (error) {
318 if (error == ENAMETOOLONG)
319 error = E2BIG;
320 goto err_exit;
321 }
322 args->stringspace -= length;
323 args->endp += length;
324 args->envc++;
325 }
326 }
327
328 return (0);
329
330 err_exit:
331 kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
332 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
333 args->buf = NULL;
334 return (error);
335 }
336
337 int
338 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
339 {
340 struct image_args eargs;
341 int error;
342
343 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
344 uap->argv, uap->envv);
345 if (error == 0)
346 error = kern_execve(td, &eargs, NULL);
347 return (error);
348 }
349
350 int
351 freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
352 {
353 struct image_args eargs;
354 int error;
355
356 error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
357 uap->argv, uap->envv);
358 if (error == 0) {
359 eargs.fd = uap->fd;
360 error = kern_execve(td, &eargs, NULL);
361 }
362 return (error);
363 }
364
365 #ifdef __ia64__
366 static int
367 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
368 int prot, int fd, off_t pos)
369 {
370 vm_map_t map;
371 vm_map_entry_t entry;
372 int rv;
373
374 map = &td->td_proc->p_vmspace->vm_map;
375 if (fd != -1)
376 prot |= VM_PROT_WRITE;
377
378 if (vm_map_lookup_entry(map, start, &entry)) {
379 if ((entry->protection & prot) != prot) {
380 rv = vm_map_protect(map,
381 trunc_page(start),
382 round_page(end),
383 entry->protection | prot,
384 FALSE);
385 if (rv != KERN_SUCCESS)
386 return (EINVAL);
387 }
388 } else {
389 vm_offset_t addr = trunc_page(start);
390 rv = vm_map_find(map, 0, 0,
391 &addr, PAGE_SIZE, FALSE, prot,
392 VM_PROT_ALL, 0);
393 if (rv != KERN_SUCCESS)
394 return (EINVAL);
395 }
396
397 if (fd != -1) {
398 struct pread_args r;
399 r.fd = fd;
400 r.buf = (void *) start;
401 r.nbyte = end - start;
402 r.offset = pos;
403 return (pread(td, &r));
404 } else {
405 while (start < end) {
406 subyte((void *) start, 0);
407 start++;
408 }
409 return (0);
410 }
411 }
412 #endif
413
414 int
415 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
416 {
417 struct mmap_args ap;
418 vm_offset_t addr = (vm_offset_t) uap->addr;
419 vm_size_t len = uap->len;
420 int prot = uap->prot;
421 int flags = uap->flags;
422 int fd = uap->fd;
423 off_t pos = (uap->poslo
424 | ((off_t)uap->poshi << 32));
425 #ifdef __ia64__
426 vm_size_t pageoff;
427 int error;
428
429 /*
430 * Attempt to handle page size hassles.
431 */
432 pageoff = (pos & PAGE_MASK);
433 if (flags & MAP_FIXED) {
434 vm_offset_t start, end;
435 start = addr;
436 end = addr + len;
437
438 if (start != trunc_page(start)) {
439 error = freebsd32_mmap_partial(td, start,
440 round_page(start), prot,
441 fd, pos);
442 if (fd != -1)
443 pos += round_page(start) - start;
444 start = round_page(start);
445 }
446 if (end != round_page(end)) {
447 vm_offset_t t = trunc_page(end);
448 error = freebsd32_mmap_partial(td, t, end,
449 prot, fd,
450 pos + t - start);
451 end = trunc_page(end);
452 }
453 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
454 /*
455 * We can't map this region at all. The specified
456 * address doesn't have the same alignment as the file
457 * position. Fake the mapping by simply reading the
458 * entire region into memory. First we need to make
459 * sure the region exists.
460 */
461 vm_map_t map;
462 struct pread_args r;
463 int rv;
464
465 prot |= VM_PROT_WRITE;
466 map = &td->td_proc->p_vmspace->vm_map;
467 rv = vm_map_remove(map, start, end);
468 if (rv != KERN_SUCCESS)
469 return (EINVAL);
470 rv = vm_map_find(map, 0, 0,
471 &start, end - start, FALSE,
472 prot, VM_PROT_ALL, 0);
473 if (rv != KERN_SUCCESS)
474 return (EINVAL);
475 r.fd = fd;
476 r.buf = (void *) start;
477 r.nbyte = end - start;
478 r.offset = pos;
479 error = pread(td, &r);
480 if (error)
481 return (error);
482
483 td->td_retval[0] = addr;
484 return (0);
485 }
486 if (end == start) {
487 /*
488 * After dealing with the ragged ends, there
489 * might be none left.
490 */
491 td->td_retval[0] = addr;
492 return (0);
493 }
494 addr = start;
495 len = end - start;
496 }
497 #endif
498
499 ap.addr = (void *) addr;
500 ap.len = len;
501 ap.prot = prot;
502 ap.flags = flags;
503 ap.fd = fd;
504 ap.pos = pos;
505
506 return (mmap(td, &ap));
507 }
508
509 #ifdef COMPAT_FREEBSD6
510 int
511 freebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
512 {
513 struct freebsd32_mmap_args ap;
514
515 ap.addr = uap->addr;
516 ap.len = uap->len;
517 ap.prot = uap->prot;
518 ap.flags = uap->flags;
519 ap.fd = uap->fd;
520 ap.poslo = uap->poslo;
521 ap.poshi = uap->poshi;
522
523 return (freebsd32_mmap(td, &ap));
524 }
525 #endif
526
527 int
528 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
529 {
530 struct itimerval itv, oitv, *itvp;
531 struct itimerval32 i32;
532 int error;
533
534 if (uap->itv != NULL) {
535 error = copyin(uap->itv, &i32, sizeof(i32));
536 if (error)
537 return (error);
538 TV_CP(i32, itv, it_interval);
539 TV_CP(i32, itv, it_value);
540 itvp = &itv;
541 } else
542 itvp = NULL;
543 error = kern_setitimer(td, uap->which, itvp, &oitv);
544 if (error || uap->oitv == NULL)
545 return (error);
546 TV_CP(oitv, i32, it_interval);
547 TV_CP(oitv, i32, it_value);
548 return (copyout(&i32, uap->oitv, sizeof(i32)));
549 }
550
551 int
552 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
553 {
554 struct itimerval itv;
555 struct itimerval32 i32;
556 int error;
557
558 error = kern_getitimer(td, uap->which, &itv);
559 if (error || uap->itv == NULL)
560 return (error);
561 TV_CP(itv, i32, it_interval);
562 TV_CP(itv, i32, it_value);
563 return (copyout(&i32, uap->itv, sizeof(i32)));
564 }
565
566 int
567 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
568 {
569 struct timeval32 tv32;
570 struct timeval tv, *tvp;
571 int error;
572
573 if (uap->tv != NULL) {
574 error = copyin(uap->tv, &tv32, sizeof(tv32));
575 if (error)
576 return (error);
577 CP(tv32, tv, tv_sec);
578 CP(tv32, tv, tv_usec);
579 tvp = &tv;
580 } else
581 tvp = NULL;
582 /*
583 * XXX big-endian needs to convert the fd_sets too.
584 * XXX Do pointers need PTRIN()?
585 */
586 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
587 }
588
589 /*
590 * Copy 'count' items into the destination list pointed to by uap->eventlist.
591 */
592 static int
593 freebsd32_kevent_copyout(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 for (i = 0; i < count; i++) {
603 CP(kevp[i], ks32[i], ident);
604 CP(kevp[i], ks32[i], filter);
605 CP(kevp[i], ks32[i], flags);
606 CP(kevp[i], ks32[i], fflags);
607 CP(kevp[i], ks32[i], data);
608 PTROUT_CP(kevp[i], ks32[i], udata);
609 }
610 error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
611 if (error == 0)
612 uap->eventlist += count;
613 return (error);
614 }
615
616 /*
617 * Copy 'count' items from the list pointed to by uap->changelist.
618 */
619 static int
620 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
621 {
622 struct freebsd32_kevent_args *uap;
623 struct kevent32 ks32[KQ_NEVENTS];
624 int i, error = 0;
625
626 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
627 uap = (struct freebsd32_kevent_args *)arg;
628
629 error = copyin(uap->changelist, ks32, count * sizeof *ks32);
630 if (error)
631 goto done;
632 uap->changelist += count;
633
634 for (i = 0; i < count; i++) {
635 CP(ks32[i], kevp[i], ident);
636 CP(ks32[i], kevp[i], filter);
637 CP(ks32[i], kevp[i], flags);
638 CP(ks32[i], kevp[i], fflags);
639 CP(ks32[i], kevp[i], data);
640 PTRIN_CP(ks32[i], kevp[i], udata);
641 }
642 done:
643 return (error);
644 }
645
646 int
647 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
648 {
649 struct timespec32 ts32;
650 struct timespec ts, *tsp;
651 struct kevent_copyops k_ops = { uap,
652 freebsd32_kevent_copyout,
653 freebsd32_kevent_copyin};
654 int error;
655
656
657 if (uap->timeout) {
658 error = copyin(uap->timeout, &ts32, sizeof(ts32));
659 if (error)
660 return (error);
661 CP(ts32, ts, tv_sec);
662 CP(ts32, ts, tv_nsec);
663 tsp = &ts;
664 } else
665 tsp = NULL;
666 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
667 &k_ops, tsp);
668 return (error);
669 }
670
671 int
672 freebsd32_gettimeofday(struct thread *td,
673 struct freebsd32_gettimeofday_args *uap)
674 {
675 struct timeval atv;
676 struct timeval32 atv32;
677 struct timezone rtz;
678 int error = 0;
679
680 if (uap->tp) {
681 microtime(&atv);
682 CP(atv, atv32, tv_sec);
683 CP(atv, atv32, tv_usec);
684 error = copyout(&atv32, uap->tp, sizeof (atv32));
685 }
686 if (error == 0 && uap->tzp != NULL) {
687 rtz.tz_minuteswest = tz_minuteswest;
688 rtz.tz_dsttime = tz_dsttime;
689 error = copyout(&rtz, uap->tzp, sizeof (rtz));
690 }
691 return (error);
692 }
693
694 int
695 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
696 {
697 struct rusage32 s32;
698 struct rusage s;
699 int error;
700
701 error = kern_getrusage(td, uap->who, &s);
702 if (error)
703 return (error);
704 if (uap->rusage != NULL) {
705 TV_CP(s, s32, ru_utime);
706 TV_CP(s, s32, ru_stime);
707 CP(s, s32, ru_maxrss);
708 CP(s, s32, ru_ixrss);
709 CP(s, s32, ru_idrss);
710 CP(s, s32, ru_isrss);
711 CP(s, s32, ru_minflt);
712 CP(s, s32, ru_majflt);
713 CP(s, s32, ru_nswap);
714 CP(s, s32, ru_inblock);
715 CP(s, s32, ru_oublock);
716 CP(s, s32, ru_msgsnd);
717 CP(s, s32, ru_msgrcv);
718 CP(s, s32, ru_nsignals);
719 CP(s, s32, ru_nvcsw);
720 CP(s, s32, ru_nivcsw);
721 error = copyout(&s32, uap->rusage, sizeof(s32));
722 }
723 return (error);
724 }
725
726 static int
727 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
728 {
729 struct iovec32 iov32;
730 struct iovec *iov;
731 struct uio *uio;
732 u_int iovlen;
733 int error, i;
734
735 *uiop = NULL;
736 if (iovcnt > UIO_MAXIOV)
737 return (EINVAL);
738 iovlen = iovcnt * sizeof(struct iovec);
739 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
740 iov = (struct iovec *)(uio + 1);
741 for (i = 0; i < iovcnt; i++) {
742 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
743 if (error) {
744 free(uio, M_IOV);
745 return (error);
746 }
747 iov[i].iov_base = PTRIN(iov32.iov_base);
748 iov[i].iov_len = iov32.iov_len;
749 }
750 uio->uio_iov = iov;
751 uio->uio_iovcnt = iovcnt;
752 uio->uio_segflg = UIO_USERSPACE;
753 uio->uio_offset = -1;
754 uio->uio_resid = 0;
755 for (i = 0; i < iovcnt; i++) {
756 if (iov->iov_len > INT_MAX - uio->uio_resid) {
757 free(uio, M_IOV);
758 return (EINVAL);
759 }
760 uio->uio_resid += iov->iov_len;
761 iov++;
762 }
763 *uiop = uio;
764 return (0);
765 }
766
767 int
768 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
769 {
770 struct uio *auio;
771 int error;
772
773 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
774 if (error)
775 return (error);
776 error = kern_readv(td, uap->fd, auio);
777 free(auio, M_IOV);
778 return (error);
779 }
780
781 int
782 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
783 {
784 struct uio *auio;
785 int error;
786
787 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
788 if (error)
789 return (error);
790 error = kern_writev(td, uap->fd, auio);
791 free(auio, M_IOV);
792 return (error);
793 }
794
795 int
796 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
797 {
798 struct uio *auio;
799 int error;
800
801 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
802 if (error)
803 return (error);
804 error = kern_preadv(td, uap->fd, auio, uap->offset);
805 free(auio, M_IOV);
806 return (error);
807 }
808
809 int
810 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
811 {
812 struct uio *auio;
813 int error;
814
815 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
816 if (error)
817 return (error);
818 error = kern_pwritev(td, uap->fd, auio, uap->offset);
819 free(auio, M_IOV);
820 return (error);
821 }
822
823 static int
824 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
825 int error)
826 {
827 struct iovec32 iov32;
828 struct iovec *iov;
|