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