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.0/sys/compat/freebsd32/freebsd32_misc.c 148133 2005-07-18 19:49:48Z jhb $");
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/mman.h>
45 #include <sys/module.h>
46 #include <sys/mount.h>
47 #include <sys/mutex.h>
48 #include <sys/namei.h>
49 #include <sys/param.h>
50 #include <sys/proc.h>
51 #include <sys/reboot.h>
52 #include <sys/resource.h>
53 #include <sys/resourcevar.h>
54 #include <sys/selinfo.h>
55 #include <sys/eventvar.h> /* Must come after sys/selinfo.h */
56 #include <sys/pipe.h> /* Must come after sys/selinfo.h */
57 #include <sys/signal.h>
58 #include <sys/signalvar.h>
59 #include <sys/socket.h>
60 #include <sys/socketvar.h>
61 #include <sys/stat.h>
62 #include <sys/syscallsubr.h>
63 #include <sys/sysctl.h>
64 #include <sys/sysent.h>
65 #include <sys/sysproto.h>
66 #include <sys/systm.h>
67 #include <sys/unistd.h>
68 #include <sys/vnode.h>
69 #include <sys/wait.h>
70
71 #include <vm/vm.h>
72 #include <vm/vm_kern.h>
73 #include <vm/vm_param.h>
74 #include <vm/pmap.h>
75 #include <vm/vm_map.h>
76 #include <vm/vm_object.h>
77 #include <vm/vm_extern.h>
78
79 #include <compat/freebsd32/freebsd32_util.h>
80 #include <compat/freebsd32/freebsd32.h>
81 #include <compat/freebsd32/freebsd32_proto.h>
82
83 CTASSERT(sizeof(struct timeval32) == 8);
84 CTASSERT(sizeof(struct timespec32) == 8);
85 CTASSERT(sizeof(struct statfs32) == 256);
86 CTASSERT(sizeof(struct rusage32) == 72);
87
88 int
89 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
90 {
91 int error, status;
92 struct rusage32 ru32;
93 struct rusage ru, *rup;
94
95 if (uap->rusage != NULL)
96 rup = &ru;
97 else
98 rup = NULL;
99 error = kern_wait(td, uap->pid, &status, uap->options, rup);
100 if (error)
101 return (error);
102 if (uap->status != NULL)
103 error = copyout(&status, uap->status, sizeof(status));
104 if (uap->rusage != NULL && error == 0) {
105 TV_CP(ru, ru32, ru_utime);
106 TV_CP(ru, ru32, ru_stime);
107 CP(ru, ru32, ru_maxrss);
108 CP(ru, ru32, ru_ixrss);
109 CP(ru, ru32, ru_idrss);
110 CP(ru, ru32, ru_isrss);
111 CP(ru, ru32, ru_minflt);
112 CP(ru, ru32, ru_majflt);
113 CP(ru, ru32, ru_nswap);
114 CP(ru, ru32, ru_inblock);
115 CP(ru, ru32, ru_oublock);
116 CP(ru, ru32, ru_msgsnd);
117 CP(ru, ru32, ru_msgrcv);
118 CP(ru, ru32, ru_nsignals);
119 CP(ru, ru32, ru_nvcsw);
120 CP(ru, ru32, ru_nivcsw);
121 error = copyout(&ru32, uap->rusage, sizeof(ru32));
122 }
123 return (error);
124 }
125
126 #ifdef COMPAT_FREEBSD4
127 static void
128 copy_statfs(struct statfs *in, struct statfs32 *out)
129 {
130 CP(*in, *out, f_bsize);
131 CP(*in, *out, f_iosize);
132 CP(*in, *out, f_blocks);
133 CP(*in, *out, f_bfree);
134 CP(*in, *out, f_bavail);
135 CP(*in, *out, f_files);
136 CP(*in, *out, f_ffree);
137 CP(*in, *out, f_fsid);
138 CP(*in, *out, f_owner);
139 CP(*in, *out, f_type);
140 CP(*in, *out, f_flags);
141 CP(*in, *out, f_flags);
142 CP(*in, *out, f_syncwrites);
143 CP(*in, *out, f_asyncwrites);
144 bcopy(in->f_fstypename,
145 out->f_fstypename, MFSNAMELEN);
146 bcopy(in->f_mntonname,
147 out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
148 CP(*in, *out, f_syncreads);
149 CP(*in, *out, f_asyncreads);
150 bcopy(in->f_mntfromname,
151 out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
152 }
153 #endif
154
155 #ifdef COMPAT_FREEBSD4
156 int
157 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
158 {
159 struct statfs *buf, *sp;
160 struct statfs32 stat32;
161 size_t count, size;
162 int error;
163
164 count = uap->bufsize / sizeof(struct statfs32);
165 size = count * sizeof(struct statfs);
166 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
167 if (size > 0) {
168 count = td->td_retval[0];
169 sp = buf;
170 while (count > 0 && error == 0) {
171 copy_statfs(sp, &stat32);
172 error = copyout(&stat32, uap->buf, sizeof(stat32));
173 sp++;
174 uap->buf++;
175 count--;
176 }
177 free(buf, M_TEMP);
178 }
179 return (error);
180 }
181 #endif
182
183 struct sigaltstack32 {
184 u_int32_t ss_sp;
185 u_int32_t ss_size;
186 int ss_flags;
187 };
188
189 CTASSERT(sizeof(struct sigaltstack32) == 12);
190
191 int
192 freebsd32_sigaltstack(struct thread *td,
193 struct freebsd32_sigaltstack_args *uap)
194 {
195 struct sigaltstack32 s32;
196 struct sigaltstack ss, oss, *ssp;
197 int error;
198
199 if (uap->ss != NULL) {
200 error = copyin(uap->ss, &s32, sizeof(s32));
201 if (error)
202 return (error);
203 PTRIN_CP(s32, ss, ss_sp);
204 CP(s32, ss, ss_size);
205 CP(s32, ss, ss_flags);
206 ssp = &ss;
207 } else
208 ssp = NULL;
209 error = kern_sigaltstack(td, ssp, &oss);
210 if (error == 0 && uap->oss != NULL) {
211 PTROUT_CP(oss, s32, ss_sp);
212 CP(oss, s32, ss_size);
213 CP(oss, s32, ss_flags);
214 error = copyout(&s32, uap->oss, sizeof(s32));
215 }
216 return (error);
217 }
218
219 /*
220 * Custom version of exec_copyin_args() so that we can translate
221 * the pointers.
222 */
223 static int
224 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
225 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
226 {
227 char *argp, *envp;
228 u_int32_t *p32, arg;
229 size_t length;
230 int error;
231
232 bzero(args, sizeof(*args));
233 if (argv == NULL)
234 return (EFAULT);
235
236 /*
237 * Allocate temporary demand zeroed space for argument and
238 * environment strings
239 */
240 args->buf = (char *) kmem_alloc_wait(exec_map,
241 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
242 if (args->buf == NULL)
243 return (ENOMEM);
244 args->begin_argv = args->buf;
245 args->endp = args->begin_argv;
246 args->stringspace = ARG_MAX;
247
248 args->fname = args->buf + ARG_MAX;
249
250 /*
251 * Copy the file name.
252 */
253 error = (segflg == UIO_SYSSPACE) ?
254 copystr(fname, args->fname, PATH_MAX, &length) :
255 copyinstr(fname, args->fname, PATH_MAX, &length);
256 if (error != 0)
257 return (error);
258
259 /*
260 * extract arguments first
261 */
262 p32 = argv;
263 for (;;) {
264 error = copyin(p32++, &arg, sizeof(arg));
265 if (error)
266 return (error);
267 if (arg == 0)
268 break;
269 argp = PTRIN(arg);
270 error = copyinstr(argp, args->endp, args->stringspace, &length);
271 if (error) {
272 if (error == ENAMETOOLONG)
273 return (E2BIG);
274 else
275 return (error);
276 }
277 args->stringspace -= length;
278 args->endp += length;
279 args->argc++;
280 }
281
282 args->begin_envv = args->endp;
283
284 /*
285 * extract environment strings
286 */
287 if (envv) {
288 p32 = envv;
289 for (;;) {
290 error = copyin(p32++, &arg, sizeof(arg));
291 if (error)
292 return (error);
293 if (arg == 0)
294 break;
295 envp = PTRIN(arg);
296 error = copyinstr(envp, args->endp, args->stringspace,
297 &length);
298 if (error) {
299 if (error == ENAMETOOLONG)
300 return (E2BIG);
301 else
302 return (error);
303 }
304 args->stringspace -= length;
305 args->endp += length;
306 args->envc++;
307 }
308 }
309
310 return (0);
311 }
312
313 int
314 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
315 {
316 struct image_args eargs;
317 int error;
318
319 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
320 uap->argv, uap->envv);
321 if (error == 0)
322 error = kern_execve(td, &eargs, NULL);
323 exec_free_args(&eargs);
324 return (error);
325 }
326
327 #ifdef __ia64__
328 static int
329 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
330 int prot, int fd, off_t pos)
331 {
332 vm_map_t map;
333 vm_map_entry_t entry;
334 int rv;
335
336 map = &td->td_proc->p_vmspace->vm_map;
337 if (fd != -1)
338 prot |= VM_PROT_WRITE;
339
340 if (vm_map_lookup_entry(map, start, &entry)) {
341 if ((entry->protection & prot) != prot) {
342 rv = vm_map_protect(map,
343 trunc_page(start),
344 round_page(end),
345 entry->protection | prot,
346 FALSE);
347 if (rv != KERN_SUCCESS)
348 return (EINVAL);
349 }
350 } else {
351 vm_offset_t addr = trunc_page(start);
352 rv = vm_map_find(map, 0, 0,
353 &addr, PAGE_SIZE, FALSE, prot,
354 VM_PROT_ALL, 0);
355 if (rv != KERN_SUCCESS)
356 return (EINVAL);
357 }
358
359 if (fd != -1) {
360 struct pread_args r;
361 r.fd = fd;
362 r.buf = (void *) start;
363 r.nbyte = end - start;
364 r.offset = pos;
365 return (pread(td, &r));
366 } else {
367 while (start < end) {
368 subyte((void *) start, 0);
369 start++;
370 }
371 return (0);
372 }
373 }
374 #endif
375
376 int
377 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
378 {
379 struct mmap_args ap;
380 vm_offset_t addr = (vm_offset_t) uap->addr;
381 vm_size_t len = uap->len;
382 int prot = uap->prot;
383 int flags = uap->flags;
384 int fd = uap->fd;
385 off_t pos = (uap->poslo
386 | ((off_t)uap->poshi << 32));
387 #ifdef __ia64__
388 vm_size_t pageoff;
389 int error;
390
391 /*
392 * Attempt to handle page size hassles.
393 */
394 pageoff = (pos & PAGE_MASK);
395 if (flags & MAP_FIXED) {
396 vm_offset_t start, end;
397 start = addr;
398 end = addr + len;
399
400 mtx_lock(&Giant);
401 if (start != trunc_page(start)) {
402 error = freebsd32_mmap_partial(td, start,
403 round_page(start), prot,
404 fd, pos);
405 if (fd != -1)
406 pos += round_page(start) - start;
407 start = round_page(start);
408 }
409 if (end != round_page(end)) {
410 vm_offset_t t = trunc_page(end);
411 error = freebsd32_mmap_partial(td, t, end,
412 prot, fd,
413 pos + t - start);
414 end = trunc_page(end);
415 }
416 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
417 /*
418 * We can't map this region at all. The specified
419 * address doesn't have the same alignment as the file
420 * position. Fake the mapping by simply reading the
421 * entire region into memory. First we need to make
422 * sure the region exists.
423 */
424 vm_map_t map;
425 struct pread_args r;
426 int rv;
427
428 prot |= VM_PROT_WRITE;
429 map = &td->td_proc->p_vmspace->vm_map;
430 rv = vm_map_remove(map, start, end);
431 if (rv != KERN_SUCCESS) {
432 mtx_unlock(&Giant);
433 return (EINVAL);
434 }
435 rv = vm_map_find(map, 0, 0,
436 &start, end - start, FALSE,
437 prot, VM_PROT_ALL, 0);
438 mtx_unlock(&Giant);
439 if (rv != KERN_SUCCESS)
440 return (EINVAL);
441 r.fd = fd;
442 r.buf = (void *) start;
443 r.nbyte = end - start;
444 r.offset = pos;
445 error = pread(td, &r);
446 if (error)
447 return (error);
448
449 td->td_retval[0] = addr;
450 return (0);
451 }
452 mtx_unlock(&Giant);
453 if (end == start) {
454 /*
455 * After dealing with the ragged ends, there
456 * might be none left.
457 */
458 td->td_retval[0] = addr;
459 return (0);
460 }
461 addr = start;
462 len = end - start;
463 }
464 #endif
465
466 ap.addr = (void *) addr;
467 ap.len = len;
468 ap.prot = prot;
469 ap.flags = flags;
470 ap.fd = fd;
471 ap.pos = pos;
472
473 return (mmap(td, &ap));
474 }
475
476 struct itimerval32 {
477 struct timeval32 it_interval;
478 struct timeval32 it_value;
479 };
480
481 CTASSERT(sizeof(struct itimerval32) == 16);
482
483 int
484 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
485 {
486 struct itimerval itv, oitv, *itvp;
487 struct itimerval32 i32;
488 int error;
489
490 if (uap->itv != NULL) {
491 error = copyin(uap->itv, &i32, sizeof(i32));
492 if (error)
493 return (error);
494 TV_CP(i32, itv, it_interval);
495 TV_CP(i32, itv, it_value);
496 itvp = &itv;
497 } else
498 itvp = NULL;
499 error = kern_setitimer(td, uap->which, itvp, &oitv);
500 if (error || uap->oitv == NULL)
501 return (error);
502 TV_CP(oitv, i32, it_interval);
503 TV_CP(oitv, i32, it_value);
504 return (copyout(&i32, uap->oitv, sizeof(i32)));
505 }
506
507 int
508 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
509 {
510 struct itimerval itv;
511 struct itimerval32 i32;
512 int error;
513
514 error = kern_getitimer(td, uap->which, &itv);
515 if (error || uap->itv == NULL)
516 return (error);
517 TV_CP(itv, i32, it_interval);
518 TV_CP(itv, i32, it_value);
519 return (copyout(&i32, uap->itv, sizeof(i32)));
520 }
521
522 int
523 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
524 {
525 struct timeval32 tv32;
526 struct timeval tv, *tvp;
527 int error;
528
529 if (uap->tv != NULL) {
530 error = copyin(uap->tv, &tv32, sizeof(tv32));
531 if (error)
532 return (error);
533 CP(tv32, tv, tv_sec);
534 CP(tv32, tv, tv_usec);
535 tvp = &tv;
536 } else
537 tvp = NULL;
538 /*
539 * XXX big-endian needs to convert the fd_sets too.
540 * XXX Do pointers need PTRIN()?
541 */
542 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
543 }
544
545 struct kevent32 {
546 u_int32_t ident; /* identifier for this event */
547 short filter; /* filter for event */
548 u_short flags;
549 u_int fflags;
550 int32_t data;
551 u_int32_t udata; /* opaque user data identifier */
552 };
553
554 CTASSERT(sizeof(struct kevent32) == 20);
555 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
556 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
557
558 /*
559 * Copy 'count' items into the destination list pointed to by uap->eventlist.
560 */
561 static int
562 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
563 {
564 struct freebsd32_kevent_args *uap;
565 struct kevent32 ks32[KQ_NEVENTS];
566 int i, error = 0;
567
568 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
569 uap = (struct freebsd32_kevent_args *)arg;
570
571 for (i = 0; i < count; i++) {
572 CP(kevp[i], ks32[i], ident);
573 CP(kevp[i], ks32[i], filter);
574 CP(kevp[i], ks32[i], flags);
575 CP(kevp[i], ks32[i], fflags);
576 CP(kevp[i], ks32[i], data);
577 PTROUT_CP(kevp[i], ks32[i], udata);
578 }
579 error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
580 if (error == 0)
581 uap->eventlist += count;
582 return (error);
583 }
584
585 /*
586 * Copy 'count' items from the list pointed to by uap->changelist.
587 */
588 static int
589 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
590 {
591 struct freebsd32_kevent_args *uap;
592 struct kevent32 ks32[KQ_NEVENTS];
593 int i, error = 0;
594
595 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
596 uap = (struct freebsd32_kevent_args *)arg;
597
598 error = copyin(uap->changelist, ks32, count * sizeof *ks32);
599 if (error)
600 goto done;
601 uap->changelist += count;
602
603 for (i = 0; i < count; i++) {
604 CP(ks32[i], kevp[i], ident);
605 CP(ks32[i], kevp[i], filter);
606 CP(ks32[i], kevp[i], flags);
607 CP(ks32[i], kevp[i], fflags);
608 CP(ks32[i], kevp[i], data);
609 PTRIN_CP(ks32[i], kevp[i], udata);
610 }
611 done:
612 return (error);
613 }
614
615 int
616 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
617 {
618 struct timespec32 ts32;
619 struct timespec ts, *tsp;
620 struct kevent_copyops k_ops = { uap,
621 freebsd32_kevent_copyout,
622 freebsd32_kevent_copyin};
623 int error;
624
625
626 if (uap->timeout) {
627 error = copyin(uap->timeout, &ts32, sizeof(ts32));
628 if (error)
629 return (error);
630 CP(ts32, ts, tv_sec);
631 CP(ts32, ts, tv_nsec);
632 tsp = &ts;
633 } else
634 tsp = NULL;
635 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
636 &k_ops, tsp);
637 return (error);
638 }
639
640 int
641 freebsd32_gettimeofday(struct thread *td,
642 struct freebsd32_gettimeofday_args *uap)
643 {
644 struct timeval atv;
645 struct timeval32 atv32;
646 struct timezone rtz;
647 int error = 0;
648
649 if (uap->tp) {
650 microtime(&atv);
651 CP(atv, atv32, tv_sec);
652 CP(atv, atv32, tv_usec);
653 error = copyout(&atv32, uap->tp, sizeof (atv32));
654 }
655 if (error == 0 && uap->tzp != NULL) {
656 rtz.tz_minuteswest = tz_minuteswest;
657 rtz.tz_dsttime = tz_dsttime;
658 error = copyout(&rtz, uap->tzp, sizeof (rtz));
659 }
660 return (error);
661 }
662
663 int
664 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
665 {
666 struct rusage32 s32;
667 struct rusage s;
668 int error;
669
670 error = kern_getrusage(td, uap->who, &s);
671 if (error)
672 return (error);
673 if (uap->rusage != NULL) {
674 TV_CP(s, s32, ru_utime);
675 TV_CP(s, s32, ru_stime);
676 CP(s, s32, ru_maxrss);
677 CP(s, s32, ru_ixrss);
678 CP(s, s32, ru_idrss);
679 CP(s, s32, ru_isrss);
680 CP(s, s32, ru_minflt);
681 CP(s, s32, ru_majflt);
682 CP(s, s32, ru_nswap);
683 CP(s, s32, ru_inblock);
684 CP(s, s32, ru_oublock);
685 CP(s, s32, ru_msgsnd);
686 CP(s, s32, ru_msgrcv);
687 CP(s, s32, ru_nsignals);
688 CP(s, s32, ru_nvcsw);
689 CP(s, s32, ru_nivcsw);
690 error = copyout(&s32, uap->rusage, sizeof(s32));
691 }
692 return (error);
693 }
694
695 struct iovec32 {
696 u_int32_t iov_base;
697 int iov_len;
698 };
699
700 CTASSERT(sizeof(struct iovec32) == 8);
701
702 static int
703 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
704 {
705 struct iovec32 iov32;
706 struct iovec *iov;
707 struct uio *uio;
708 u_int iovlen;
709 int error, i;
710
711 *uiop = NULL;
712 if (iovcnt > UIO_MAXIOV)
713 return (EINVAL);
714 iovlen = iovcnt * sizeof(struct iovec);
715 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
716 iov = (struct iovec *)(uio + 1);
717 for (i = 0; i < iovcnt; i++) {
718 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
719 if (error) {
720 free(uio, M_IOV);
721 return (error);
722 }
723 iov[i].iov_base = PTRIN(iov32.iov_base);
724 iov[i].iov_len = iov32.iov_len;
725 }
726 uio->uio_iov = iov;
727 uio->uio_iovcnt = iovcnt;
728 uio->uio_segflg = UIO_USERSPACE;
729 uio->uio_offset = -1;
730 uio->uio_resid = 0;
731 for (i = 0; i < iovcnt; i++) {
732 if (iov->iov_len > INT_MAX - uio->uio_resid) {
733 free(uio, M_IOV);
734 return (EINVAL);
735 }
736 uio->uio_resid += iov->iov_len;
737 iov++;
738 }
739 *uiop = uio;
740 return (0);
741 }
742
743 int
744 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
745 {
746 struct uio *auio;
747 int error;
748
749 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
750 if (error)
751 return (error);
752 error = kern_readv(td, uap->fd, auio);
753 free(auio, M_IOV);
754 return (error);
755 }
756
757 int
758 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
759 {
760 struct uio *auio;
761 int error;
762
763 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
764 if (error)
765 return (error);
766 error = kern_writev(td, uap->fd, auio);
767 free(auio, M_IOV);
768 return (error);
769 }
770
771 int
772 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
773 {
774 struct uio *auio;
775 int error;
776
777 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
778 if (error)
779 return (error);
780 error = kern_preadv(td, uap->fd, auio, uap->offset);
781 free(auio, M_IOV);
782 return (error);
783 }
784
785 int
786 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
787 {
788 struct uio *auio;
789 int error;
790
791 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
792 if (error)
793 return (error);
794 error = kern_pwritev(td, uap->fd, auio, uap->offset);
795 free(auio, M_IOV);
796 return (error);
797 }
798
799 int
800 freebsd32_settimeofday(struct thread *td,
801 struct freebsd32_settimeofday_args *uap)
802 {
803 struct timeval32 tv32;
804 struct timeval tv, *tvp;
805 struct timezone tz, *tzp;
806 int error;
807
808 if (uap->tv) {
809 error = copyin(uap->tv, &tv32, sizeof(tv32));
810 if (error)
811 return (error);
812 CP(tv32, tv, tv_sec);
813 CP(tv32, tv, tv_usec);
814 tvp = &tv;
815 } else
816 tvp = NULL;
817 if (uap->tzp) {
818 error = copyin(uap->tzp, &tz, sizeof(tz));
819 if (error)
820 return (error);
821 tzp = &tz;
822 } else
823 tzp = NULL;
824 return (kern_settimeofday(td, tvp, tzp));
825 }
826
827 int
828 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
829 {
830 struct timeval32 s32[2];
831 struct timeval s[2], *sp;
832 int error;
833
834 if (uap->tptr != NULL) {
835 error = copyin(uap->tptr, s32, sizeof(s32));
836 if (error)
837 return (error);
838 CP(s32[0], s[0], tv_sec);
839 CP(s32[0], s[0], tv_usec);
840 CP(s32[1], s[1], tv_sec);
841 CP(s32[1], s[1], tv_usec);
842 sp = s;
843 } else
844 sp = NULL;
845 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
846 }
847
848 int
849 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
850 {
851 struct timeval32 tv32;
852 struct timeval delta, olddelta, *deltap;
853 int error;
854
855 if (uap->delta) {
856 error = copyin(uap->delta, &tv32, sizeof(tv32));
857 if (error)
858 return (error);
859 CP(tv32, delta, tv_sec);
860 CP(tv32, delta, tv_usec);
861 deltap = δ
862 } else
863 deltap = NULL;
864 error = kern_adjtime(td, deltap, &olddelta);
865 if (uap->olddelta && error == 0) {
866 CP(olddelta, tv32, tv_sec);
867 CP(olddelta, tv32, tv_usec);
868 error = copyout(&tv32, uap->olddelta, sizeof(tv32));
869 }
870 return (error);
871 }
872
873 #ifdef COMPAT_FREEBSD4
874 int
875 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
876 {
877 struct statfs32 s32;
878 struct statfs s;
879 int error;
880
881 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
882 if (error)
883 return (error);
884 copy_statfs(&s, &s32);
885 return (copyout(&s32, uap->buf, sizeof(s32)));
886 }
887 #endif
888
889 #ifdef COMPAT_FREEBSD4
890 int
891 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
892 {
893 struct statfs32 s32;
894 struct statfs s;
895 int error;
896
897 error = kern_fstatfs(td, uap->fd, &s);
898 if (error)
899 return (error);
900 copy_statfs(&s, &s32);
901 return (copyout(&s32, uap->buf, sizeof(s32)));
902 }
903 #endif
904
905 #ifdef COMPAT_FREEBSD4
906 int
907 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
908 {
909 struct statfs32 s32;
910 struct statfs s;
911 fhandle_t fh;
912 int error;
913
914 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
915 return (error);
916 error = kern_fhstatfs(td, fh, &s);
917 if (error)
918 return (error);
919 copy_statfs(&s, &s32);
920 return (copyout(&s32, uap->buf, sizeof(s32)));
921 }
922 #endif
923
924 int
925 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
926 {
927 /*
928 * Vector through to semsys if it is loaded.
929 */
930 return sysent[169].sy_call(td, uap);
931 }
932
933 int
934 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
935 {
936 /*
937 * Vector through to msgsys if it is loaded.
938 */
939 return sysent[170].sy_call(td, uap);
940 }
941
942 int
943 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
944 {
945 /*
946 * Vector through to shmsys if it is loaded.
947 */
948 return sysent[171].sy_call(td, uap);
949 }
950
951 int
952 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
953 {
954 struct pread_args ap;
955
956 ap.fd = uap->fd;
957 ap.buf = uap->buf;
958 ap.nbyte = uap->nbyte;
959 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
960 return (pread(td, &ap));
961 }
962
963 int
964 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
965 {
966 struct pwrite_args ap;
967
968 ap.fd = uap->fd;
969 ap.buf = uap->buf;
970 ap.nbyte = uap->nbyte;
971 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
972 return (pwrite(td, &ap));
973 }
974
975 int
976 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
977 {
978 int error;
979 struct lseek_args ap;
980 off_t pos;
981
982 ap.fd = uap->fd;
983 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
984 ap.whence = uap->whence;
985 error = lseek(td, &ap);
986 /* Expand the quad return into two parts for eax and edx */
987 pos = *(off_t *)(td->td_retval);
988 td->td_retval[0] = pos & 0xffffffff; /* %eax */
989 td->td_retval[1] = pos >> 32; /* %edx */
990 return error;
991 }
992
993 int
994 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
995 {
996 struct truncate_args ap;
997
998 ap.path = uap->path;
999 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1000 return (truncate(td, &ap));
1001 }
1002
1003 int
1004 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1005 {
1006 struct ftruncate_args ap;
1007
1008 ap.fd = uap->fd;
1009 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1010 return (ftruncate(td, &ap));
1011 }
1012
1013 #ifdef COMPAT_FREEBSD4
1014 int
1015 freebsd4_freebsd32_sendfile(struct thread *td,
1016 struct freebsd4_freebsd32_sendfile_args *uap)
1017 {
1018 struct freebsd4_sendfile_args ap;
1019
1020 ap.fd = uap->fd;
1021 ap.s = uap->s;
1022 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1023 ap.nbytes = uap->nbytes; /* XXX check */
1024 ap.hdtr = uap->hdtr; /* XXX check */
1025 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1026 ap.flags = uap->flags;
1027 return (freebsd4_sendfile(td, &ap));
1028 }
1029 #endif
1030
1031 int
1032 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1033 {
1034 struct sendfile_args ap;
1035
1036 ap.fd = uap->fd;
1037 ap.s = uap->s;
1038 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1039 ap.nbytes = uap->nbytes; /* XXX check */
1040 ap.hdtr = uap->hdtr; /* XXX check */
1041 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1042 ap.flags = uap->flags;
1043 return (sendfile(td, &ap));
1044 }
1045
1046 struct stat32 {
1047 dev_t st_dev;
1048 ino_t st_ino;
1049 mode_t st_mode;
1050 nlink_t st_nlink;
1051 uid_t st_uid;
1052 gid_t st_gid;
1053 dev_t st_rdev;
1054 struct timespec32 st_atimespec;
1055 struct timespec32 st_mtimespec;
1056 struct timespec32 st_ctimespec;
1057 off_t st_size;
1058 int64_t st_blocks;
1059 u_int32_t st_blksize;
1060 u_int32_t st_flags;
1061 u_int32_t st_gen;
1062 struct timespec32 st_birthtimespec;
1063 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1064 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1065 };
1066
1067
1068 CTASSERT(sizeof(struct stat32) == 96);
1069
1070 static void
1071 copy_stat( struct stat *in, struct stat32 *out)
1072 {
1073 CP(*in, *out, st_dev);
1074 CP(*in, *out, st_ino);
1075 CP(*in, *out, st_mode);
1076 CP(*in, *out, st_nlink);
1077 CP(*in, *out, st_uid);
1078 CP(*in, *out, st_gid);
1079 CP(*in, *out, st_rdev);
1080 TS_CP(*in, *out, st_atimespec);
1081 TS_CP(*in, *out, st_mtimespec);
1082 TS_CP(*in, *out, st_ctimespec);
1083 CP(*in, *out, st_size);
1084 CP(*in, *out, st_blocks);
1085 CP(*in, *out, st_blksize);
1086 CP(*in, *out, st_flags);
1087 CP(*in, *out, st_gen);
1088 }
1089
1090 int
1091 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1092 {
1093 struct stat sb;
1094 struct stat32 sb32;
1095 int error;
1096
1097 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1098 if (error)
1099 return (error);
1100 copy_stat(&sb, &sb32);
1101 error = copyout(&sb32, uap->ub, sizeof (sb32));
1102 return (error);
1103 }
1104
1105 int
1106 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1107 {
1108 struct stat ub;
1109 struct stat32 ub32;
1110 int error;
1111
1112 error = kern_fstat(td, uap->fd, &ub);
1113 if (error)
1114 return (error);
1115 copy_stat(&ub, &ub32);
1116 error = copyout(&ub32, uap->ub, sizeof(ub32));
1117 return (error);
1118 }
1119
1120 int
1121 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1122 {
1123 struct stat sb;
1124 struct stat32 sb32;
1125 int error;
1126
1127 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1128 if (error)
1129 return (error);
1130 copy_stat(&sb, &sb32);
1131 error = copyout(&sb32, uap->ub, sizeof (sb32));
1132 return (error);
1133 }
1134
1135 /*
1136 * MPSAFE
1137 */
1138 int
1139 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1140 {
1141 int error, name[CTL_MAXNAME];
1142 size_t j, oldlen;
1143
1144 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1145 return (EINVAL);
1146 error = copyin(uap->name, name, uap->namelen * sizeof(int));
1147 if (error)
1148 return (error);
1149 mtx_lock(&Giant);
1150 if (uap->oldlenp)
1151 oldlen = fuword32(uap->oldlenp);
1152 else
1153 oldlen = 0;
1154 error = userland_sysctl(td, name, uap->namelen,
1155 uap->old, &oldlen, 1,
1156 uap->new, uap->newlen, &j, SCTL_MASK32);
1157 if (error && error != ENOMEM)
1158 goto done2;
1159 if (uap->oldlenp)
1160 suword32(uap->oldlenp, j);
1161 done2:
1162 mtx_unlock(&Giant);
1163 return (error);
1164 }
1165
1166 struct sigaction32 {
1167 u_int32_t sa_u;
1168 int sa_flags;
1169 sigset_t sa_mask;
1170 };
1171
1172 CTASSERT(sizeof(struct sigaction32) == 24);
1173
1174 int
1175 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1176 {
1177 struct sigaction32 s32;
1178 struct sigaction sa, osa, *sap;
1179 int error;
1180
1181 if (uap->act) {
1182 error = copyin(uap->act, &s32, sizeof(s32));
1183 if (error)
1184 return (error);
1185 sa.sa_handler = PTRIN(s32.sa_u);
1186 CP(s32, sa, sa_flags);
1187 CP(s32, sa, sa_mask);
1188 sap = &sa;
1189 } else
1190 sap = NULL;
1191 error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1192 if (error == 0 && uap->oact != NULL) {
1193 s32.sa_u = PTROUT(osa.sa_handler);
1194 CP(osa, s32, sa_flags);
1195 CP(osa, s32, sa_mask);
1196 error = copyout(&s32, uap->oact, sizeof(s32));
1197 }
1198 return (error);
1199 }
1200
1201 #ifdef COMPAT_FREEBSD4
1202 int
1203 freebsd4_freebsd32_sigaction(struct thread *td,
1204 struct freebsd4_freebsd32_sigaction_args *uap)
1205 {
1206 struct sigaction32 s32;
1207 struct sigaction sa, osa, *sap;
1208 int error;
1209
1210 if (uap->act) {
1211 error = copyin(uap->act, &s32, sizeof(s32));
1212 if (error)
1213 return (error);
1214 sa.sa_handler = PTRIN(s32.sa_u);
1215 CP(s32, sa, sa_flags);
1216 CP(s32, sa, sa_mask);
1217 sap = &sa;
1218 } else
1219 sap = NULL;
1220 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1221 if (error == 0 && uap->oact != NULL) {
1222 s32.sa_u = PTROUT(osa.sa_handler);
1223 CP(osa, s32, sa_flags);
1224 CP(osa, s32, sa_mask);
1225 error = copyout(&s32, uap->oact, sizeof(s32));
1226 }
1227 return (error);
1228 }
1229 #endif
1230
1231 int
1232 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1233 {
1234 struct timespec32 rmt32, rqt32;
1235 struct timespec rmt, rqt;
1236 int error;
1237
1238 error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1239 if (error)
1240 return (error);
1241
1242 CP(rqt32, rqt, tv_sec);
1243 CP(rqt32, rqt, tv_nsec);
1244
1245 if (uap->rmtp &&
1246 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1247 return (EFAULT);
1248 error = kern_nanosleep(td, &rqt, &rmt);
1249 if (error && uap->rmtp) {
1250 int error2;
1251
1252 CP(rmt, rmt32, tv_sec);
1253 CP(rmt, rmt32, tv_nsec);
1254
1255 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1256 if (error2)
1257 error = error2;
1258 }
1259 return (error);
1260 }
1261
1262 #if 0
1263
1264 int
1265 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1266 {
1267 int error;
1268 struct yyy32 *p32, s32;
1269 struct yyy *p = NULL, s;
1270
1271 if (uap->zzz) {
1272 error = copyin(uap->zzz, &s32, sizeof(s32));
1273 if (error)
1274 return (error);
1275 /* translate in */
1276 p = &s;
1277 }
1278 error = kern_xxx(td, p);
1279 if (error)
1280 return (error);
1281 if (uap->zzz) {
1282 /* translate out */
1283 error = copyout(&s32, p32, sizeof(s32));
1284 }
1285 return (error);
1286 }
1287
1288 #endif
Cache object: c55b379e5aa430fe4e2cf630c614c9f3
|