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