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