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/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/file.h> /* Must come after sys/malloc.h */
44 #include <sys/mbuf.h>
45 #include <sys/mman.h>
46 #include <sys/module.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/namei.h>
50 #include <sys/param.h>
51 #include <sys/proc.h>
52 #include <sys/reboot.h>
53 #include <sys/resource.h>
54 #include <sys/resourcevar.h>
55 #include <sys/selinfo.h>
56 #include <sys/eventvar.h> /* Must come after sys/selinfo.h */
57 #include <sys/pipe.h> /* Must come after sys/selinfo.h */
58 #include <sys/signal.h>
59 #include <sys/signalvar.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
62 #include <sys/stat.h>
63 #include <sys/syscall.h>
64 #include <sys/syscallsubr.h>
65 #include <sys/sysctl.h>
66 #include <sys/sysent.h>
67 #include <sys/sysproto.h>
68 #include <sys/systm.h>
69 #include <sys/unistd.h>
70 #include <sys/vnode.h>
71 #include <sys/wait.h>
72 #include <sys/ipc.h>
73 #include <sys/msg.h>
74 #include <sys/sem.h>
75 #include <sys/shm.h>
76
77 #include <vm/vm.h>
78 #include <vm/vm_kern.h>
79 #include <vm/vm_param.h>
80 #include <vm/pmap.h>
81 #include <vm/vm_map.h>
82 #include <vm/vm_object.h>
83 #include <vm/vm_extern.h>
84
85 #include <machine/cpu.h>
86
87 #include <compat/freebsd32/freebsd32_util.h>
88 #include <compat/freebsd32/freebsd32.h>
89 #include <compat/freebsd32/freebsd32_ipc.h>
90 #include <compat/freebsd32/freebsd32_proto.h>
91
92 CTASSERT(sizeof(struct timeval32) == 8);
93 CTASSERT(sizeof(struct timespec32) == 8);
94 CTASSERT(sizeof(struct itimerval32) == 16);
95 CTASSERT(sizeof(struct statfs32) == 256);
96 CTASSERT(sizeof(struct rusage32) == 72);
97 CTASSERT(sizeof(struct sigaltstack32) == 12);
98 CTASSERT(sizeof(struct kevent32) == 20);
99 CTASSERT(sizeof(struct iovec32) == 8);
100 CTASSERT(sizeof(struct msghdr32) == 28);
101 CTASSERT(sizeof(struct stat32) == 96);
102 CTASSERT(sizeof(struct sigaction32) == 24);
103
104 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
105 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
106
107 int
108 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
109 {
110 int error, status;
111 struct rusage32 ru32;
112 struct rusage ru, *rup;
113
114 if (uap->rusage != NULL)
115 rup = &ru;
116 else
117 rup = NULL;
118 error = kern_wait(td, uap->pid, &status, uap->options, rup);
119 if (error)
120 return (error);
121 if (uap->status != NULL)
122 error = copyout(&status, uap->status, sizeof(status));
123 if (uap->rusage != NULL && error == 0) {
124 TV_CP(ru, ru32, ru_utime);
125 TV_CP(ru, ru32, ru_stime);
126 CP(ru, ru32, ru_maxrss);
127 CP(ru, ru32, ru_ixrss);
128 CP(ru, ru32, ru_idrss);
129 CP(ru, ru32, ru_isrss);
130 CP(ru, ru32, ru_minflt);
131 CP(ru, ru32, ru_majflt);
132 CP(ru, ru32, ru_nswap);
133 CP(ru, ru32, ru_inblock);
134 CP(ru, ru32, ru_oublock);
135 CP(ru, ru32, ru_msgsnd);
136 CP(ru, ru32, ru_msgrcv);
137 CP(ru, ru32, ru_nsignals);
138 CP(ru, ru32, ru_nvcsw);
139 CP(ru, ru32, ru_nivcsw);
140 error = copyout(&ru32, uap->rusage, sizeof(ru32));
141 }
142 return (error);
143 }
144
145 #ifdef COMPAT_FREEBSD4
146 static void
147 copy_statfs(struct statfs *in, struct statfs32 *out)
148 {
149
150 bzero(out, sizeof(*out));
151 CP(*in, *out, f_bsize);
152 CP(*in, *out, f_iosize);
153 CP(*in, *out, f_blocks);
154 CP(*in, *out, f_bfree);
155 CP(*in, *out, f_bavail);
156 CP(*in, *out, f_files);
157 CP(*in, *out, f_ffree);
158 CP(*in, *out, f_fsid);
159 CP(*in, *out, f_owner);
160 CP(*in, *out, f_type);
161 CP(*in, *out, f_flags);
162 CP(*in, *out, f_flags);
163 CP(*in, *out, f_syncwrites);
164 CP(*in, *out, f_asyncwrites);
165 strlcpy(out->f_fstypename,
166 in->f_fstypename, MFSNAMELEN);
167 strlcpy(out->f_mntonname,
168 in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
169 CP(*in, *out, f_syncreads);
170 CP(*in, *out, f_asyncreads);
171 strlcpy(out->f_mntfromname,
172 in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
173 }
174 #endif
175
176 #ifdef COMPAT_FREEBSD4
177 int
178 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
179 {
180 struct statfs *buf, *sp;
181 struct statfs32 stat32;
182 size_t count, size;
183 int error;
184
185 count = uap->bufsize / sizeof(struct statfs32);
186 size = count * sizeof(struct statfs);
187 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
188 if (size > 0) {
189 count = td->td_retval[0];
190 sp = buf;
191 while (count > 0 && error == 0) {
192 copy_statfs(sp, &stat32);
193 error = copyout(&stat32, uap->buf, sizeof(stat32));
194 sp++;
195 uap->buf++;
196 count--;
197 }
198 free(buf, M_TEMP);
199 }
200 return (error);
201 }
202 #endif
203
204 int
205 freebsd32_sigaltstack(struct thread *td,
206 struct freebsd32_sigaltstack_args *uap)
207 {
208 struct sigaltstack32 s32;
209 struct sigaltstack ss, oss, *ssp;
210 int error;
211
212 if (uap->ss != NULL) {
213 error = copyin(uap->ss, &s32, sizeof(s32));
214 if (error)
215 return (error);
216 PTRIN_CP(s32, ss, ss_sp);
217 CP(s32, ss, ss_size);
218 CP(s32, ss, ss_flags);
219 ssp = &ss;
220 } else
221 ssp = NULL;
222 error = kern_sigaltstack(td, ssp, &oss);
223 if (error == 0 && uap->oss != NULL) {
224 PTROUT_CP(oss, s32, ss_sp);
225 CP(oss, s32, ss_size);
226 CP(oss, s32, ss_flags);
227 error = copyout(&s32, uap->oss, sizeof(s32));
228 }
229 return (error);
230 }
231
232 /*
233 * Custom version of exec_copyin_args() so that we can translate
234 * the pointers.
235 */
236 static int
237 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
238 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
239 {
240 char *argp, *envp;
241 u_int32_t *p32, arg;
242 size_t length;
243 int error;
244
245 bzero(args, sizeof(*args));
246 if (argv == NULL)
247 return (EFAULT);
248
249 /*
250 * Allocate temporary demand zeroed space for argument and
251 * environment strings
252 */
253 args->buf = (char *) kmem_alloc_wait(exec_map,
254 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
255 if (args->buf == NULL)
256 return (ENOMEM);
257 args->begin_argv = args->buf;
258 args->endp = args->begin_argv;
259 args->stringspace = ARG_MAX;
260
261 args->fname = args->buf + ARG_MAX;
262
263 /*
264 * Copy the file name.
265 */
266 error = (segflg == UIO_SYSSPACE) ?
267 copystr(fname, args->fname, PATH_MAX, &length) :
268 copyinstr(fname, args->fname, PATH_MAX, &length);
269 if (error != 0)
270 return (error);
271
272 /*
273 * extract arguments first
274 */
275 p32 = argv;
276 for (;;) {
277 error = copyin(p32++, &arg, sizeof(arg));
278 if (error)
279 return (error);
280 if (arg == 0)
281 break;
282 argp = PTRIN(arg);
283 error = copyinstr(argp, args->endp, args->stringspace, &length);
284 if (error) {
285 if (error == ENAMETOOLONG)
286 return (E2BIG);
287 else
288 return (error);
289 }
290 args->stringspace -= length;
291 args->endp += length;
292 args->argc++;
293 }
294
295 args->begin_envv = args->endp;
296
297 /*
298 * extract environment strings
299 */
300 if (envv) {
301 p32 = envv;
302 for (;;) {
303 error = copyin(p32++, &arg, sizeof(arg));
304 if (error)
305 return (error);
306 if (arg == 0)
307 break;
308 envp = PTRIN(arg);
309 error = copyinstr(envp, args->endp, args->stringspace,
310 &length);
311 if (error) {
312 if (error == ENAMETOOLONG)
313 return (E2BIG);
314 else
315 return (error);
316 }
317 args->stringspace -= length;
318 args->endp += length;
319 args->envc++;
320 }
321 }
322
323 return (0);
324 }
325
326 int
327 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
328 {
329 struct image_args eargs;
330 int error;
331
332 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
333 uap->argv, uap->envv);
334 if (error == 0)
335 error = kern_execve(td, &eargs, NULL);
336 exec_free_args(&eargs);
337 return (error);
338 }
339
340 #ifdef __ia64__
341 static int
342 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
343 int prot, int fd, off_t pos)
344 {
345 vm_map_t map;
346 vm_map_entry_t entry;
347 int rv;
348
349 map = &td->td_proc->p_vmspace->vm_map;
350 if (fd != -1)
351 prot |= VM_PROT_WRITE;
352
353 if (vm_map_lookup_entry(map, start, &entry)) {
354 if ((entry->protection & prot) != prot) {
355 rv = vm_map_protect(map,
356 trunc_page(start),
357 round_page(end),
358 entry->protection | prot,
359 FALSE);
360 if (rv != KERN_SUCCESS)
361 return (EINVAL);
362 }
363 } else {
364 vm_offset_t addr = trunc_page(start);
365 rv = vm_map_find(map, 0, 0,
366 &addr, PAGE_SIZE, FALSE, prot,
367 VM_PROT_ALL, 0);
368 if (rv != KERN_SUCCESS)
369 return (EINVAL);
370 }
371
372 if (fd != -1) {
373 struct pread_args r;
374 r.fd = fd;
375 r.buf = (void *) start;
376 r.nbyte = end - start;
377 r.offset = pos;
378 return (pread(td, &r));
379 } else {
380 while (start < end) {
381 subyte((void *) start, 0);
382 start++;
383 }
384 return (0);
385 }
386 }
387 #endif
388
389 int
390 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
391 {
392 struct mmap_args ap;
393 vm_offset_t addr = (vm_offset_t) uap->addr;
394 vm_size_t len = uap->len;
395 int prot = uap->prot;
396 int flags = uap->flags;
397 int fd = uap->fd;
398 off_t pos = (uap->poslo
399 | ((off_t)uap->poshi << 32));
400 #ifdef __ia64__
401 vm_size_t pageoff;
402 int error;
403
404 /*
405 * Attempt to handle page size hassles.
406 */
407 pageoff = (pos & PAGE_MASK);
408 if (flags & MAP_FIXED) {
409 vm_offset_t start, end;
410 start = addr;
411 end = addr + len;
412
413 mtx_lock(&Giant);
414 if (start != trunc_page(start)) {
415 error = freebsd32_mmap_partial(td, start,
416 round_page(start), prot,
417 fd, pos);
418 if (fd != -1)
419 pos += round_page(start) - start;
420 start = round_page(start);
421 }
422 if (end != round_page(end)) {
423 vm_offset_t t = trunc_page(end);
424 error = freebsd32_mmap_partial(td, t, end,
425 prot, fd,
426 pos + t - start);
427 end = trunc_page(end);
428 }
429 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
430 /*
431 * We can't map this region at all. The specified
432 * address doesn't have the same alignment as the file
433 * position. Fake the mapping by simply reading the
434 * entire region into memory. First we need to make
435 * sure the region exists.
436 */
437 vm_map_t map;
438 struct pread_args r;
439 int rv;
440
441 prot |= VM_PROT_WRITE;
442 map = &td->td_proc->p_vmspace->vm_map;
443 rv = vm_map_remove(map, start, end);
444 if (rv != KERN_SUCCESS) {
445 mtx_unlock(&Giant);
446 return (EINVAL);
447 }
448 rv = vm_map_find(map, 0, 0,
449 &start, end - start, FALSE,
450 prot, VM_PROT_ALL, 0);
451 mtx_unlock(&Giant);
452 if (rv != KERN_SUCCESS)
453 return (EINVAL);
454 r.fd = fd;
455 r.buf = (void *) start;
456 r.nbyte = end - start;
457 r.offset = pos;
458 error = pread(td, &r);
459 if (error)
460 return (error);
461
462 td->td_retval[0] = addr;
463 return (0);
464 }
465 mtx_unlock(&Giant);
466 if (end == start) {
467 /*
468 * After dealing with the ragged ends, there
469 * might be none left.
470 */
471 td->td_retval[0] = addr;
472 return (0);
473 }
474 addr = start;
475 len = end - start;
476 }
477 #endif
478
479 ap.addr = (void *) addr;
480 ap.len = len;
481 ap.prot = prot;
482 ap.flags = flags;
483 ap.fd = fd;
484 ap.pos = pos;
485
486 return (mmap(td, &ap));
487 }
488
489 int
490 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
491 {
492 struct itimerval itv, oitv, *itvp;
493 struct itimerval32 i32;
494 int error;
495
496 if (uap->itv != NULL) {
497 error = copyin(uap->itv, &i32, sizeof(i32));
498 if (error)
499 return (error);
500 TV_CP(i32, itv, it_interval);
501 TV_CP(i32, itv, it_value);
502 itvp = &itv;
503 } else
504 itvp = NULL;
505 error = kern_setitimer(td, uap->which, itvp, &oitv);
506 if (error || uap->oitv == NULL)
507 return (error);
508 TV_CP(oitv, i32, it_interval);
509 TV_CP(oitv, i32, it_value);
510 return (copyout(&i32, uap->oitv, sizeof(i32)));
511 }
512
513 int
514 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
515 {
516 struct itimerval itv;
517 struct itimerval32 i32;
518 int error;
519
520 error = kern_getitimer(td, uap->which, &itv);
521 if (error || uap->itv == NULL)
522 return (error);
523 TV_CP(itv, i32, it_interval);
524 TV_CP(itv, i32, it_value);
525 return (copyout(&i32, uap->itv, sizeof(i32)));
526 }
527
528 int
529 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
530 {
531 struct timeval32 tv32;
532 struct timeval tv, *tvp;
533 int error;
534
535 if (uap->tv != NULL) {
536 error = copyin(uap->tv, &tv32, sizeof(tv32));
537 if (error)
538 return (error);
539 CP(tv32, tv, tv_sec);
540 CP(tv32, tv, tv_usec);
541 tvp = &tv;
542 } else
543 tvp = NULL;
544 /*
545 * XXX big-endian needs to convert the fd_sets too.
546 * XXX Do pointers need PTRIN()?
547 */
548 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
549 }
550
551 /*
552 * Copy 'count' items into the destination list pointed to by uap->eventlist.
553 */
554 static int
555 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
556 {
557 struct freebsd32_kevent_args *uap;
558 struct kevent32 ks32[KQ_NEVENTS];
559 int i, error = 0;
560
561 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
562 uap = (struct freebsd32_kevent_args *)arg;
563
564 for (i = 0; i < count; i++) {
565 CP(kevp[i], ks32[i], ident);
566 CP(kevp[i], ks32[i], filter);
567 CP(kevp[i], ks32[i], flags);
568 CP(kevp[i], ks32[i], fflags);
569 CP(kevp[i], ks32[i], data);
570 PTROUT_CP(kevp[i], ks32[i], udata);
571 }
572 error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
573 if (error == 0)
574 uap->eventlist += count;
575 return (error);
576 }
577
578 /*
579 * Copy 'count' items from the list pointed to by uap->changelist.
580 */
581 static int
582 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
583 {
584 struct freebsd32_kevent_args *uap;
585 struct kevent32 ks32[KQ_NEVENTS];
586 int i, error = 0;
587
588 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
589 uap = (struct freebsd32_kevent_args *)arg;
590
591 error = copyin(uap->changelist, ks32, count * sizeof *ks32);
592 if (error)
593 goto done;
594 uap->changelist += count;
595
596 for (i = 0; i < count; i++) {
597 CP(ks32[i], kevp[i], ident);
598 CP(ks32[i], kevp[i], filter);
599 CP(ks32[i], kevp[i], flags);
600 CP(ks32[i], kevp[i], fflags);
601 CP(ks32[i], kevp[i], data);
602 PTRIN_CP(ks32[i], kevp[i], udata);
603 }
604 done:
605 return (error);
606 }
607
608 int
609 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
610 {
611 struct timespec32 ts32;
612 struct timespec ts, *tsp;
613 struct kevent_copyops k_ops = { uap,
614 freebsd32_kevent_copyout,
615 freebsd32_kevent_copyin};
616 int error;
617
618
619 if (uap->timeout) {
620 error = copyin(uap->timeout, &ts32, sizeof(ts32));
621 if (error)
622 return (error);
623 CP(ts32, ts, tv_sec);
624 CP(ts32, ts, tv_nsec);
625 tsp = &ts;
626 } else
627 tsp = NULL;
628 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
629 &k_ops, tsp);
630 return (error);
631 }
632
633 int
634 freebsd32_gettimeofday(struct thread *td,
635 struct freebsd32_gettimeofday_args *uap)
636 {
637 struct timeval atv;
638 struct timeval32 atv32;
639 struct timezone rtz;
640 int error = 0;
641
642 if (uap->tp) {
643 microtime(&atv);
644 CP(atv, atv32, tv_sec);
645 CP(atv, atv32, tv_usec);
646 error = copyout(&atv32, uap->tp, sizeof (atv32));
647 }
648 if (error == 0 && uap->tzp != NULL) {
649 rtz.tz_minuteswest = tz_minuteswest;
650 rtz.tz_dsttime = tz_dsttime;
651 error = copyout(&rtz, uap->tzp, sizeof (rtz));
652 }
653 return (error);
654 }
655
656 int
657 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
658 {
659 struct rusage32 s32;
660 struct rusage s;
661 int error;
662
663 error = kern_getrusage(td, uap->who, &s);
664 if (error)
665 return (error);
666 if (uap->rusage != NULL) {
667 TV_CP(s, s32, ru_utime);
668 TV_CP(s, s32, ru_stime);
669 CP(s, s32, ru_maxrss);
670 CP(s, s32, ru_ixrss);
671 CP(s, s32, ru_idrss);
672 CP(s, s32, ru_isrss);
673 CP(s, s32, ru_minflt);
674 CP(s, s32, ru_majflt);
675 CP(s, s32, ru_nswap);
676 CP(s, s32, ru_inblock);
677 CP(s, s32, ru_oublock);
678 CP(s, s32, ru_msgsnd);
679 CP(s, s32, ru_msgrcv);
680 CP(s, s32, ru_nsignals);
681 CP(s, s32, ru_nvcsw);
682 CP(s, s32, ru_nivcsw);
683 error = copyout(&s32, uap->rusage, sizeof(s32));
684 }
685 return (error);
686 }
687
688 static int
689 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
690 {
691 struct iovec32 iov32;
692 struct iovec *iov;
693 struct uio *uio;
694 u_int iovlen;
695 int error, i;
696
697 *uiop = NULL;
698 if (iovcnt > UIO_MAXIOV)
699 return (EINVAL);
700 iovlen = iovcnt * sizeof(struct iovec);
701 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
702 iov = (struct iovec *)(uio + 1);
703 for (i = 0; i < iovcnt; i++) {
704 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
705 if (error) {
706 free(uio, M_IOV);
707 return (error);
708 }
709 iov[i].iov_base = PTRIN(iov32.iov_base);
710 iov[i].iov_len = iov32.iov_len;
711 }
712 uio->uio_iov = iov;
713 uio->uio_iovcnt = iovcnt;
714 uio->uio_segflg = UIO_USERSPACE;
715 uio->uio_offset = -1;
716 uio->uio_resid = 0;
717 for (i = 0; i < iovcnt; i++) {
718 if (iov->iov_len > INT_MAX - uio->uio_resid) {
719 free(uio, M_IOV);
720 return (EINVAL);
721 }
722 uio->uio_resid += iov->iov_len;
723 iov++;
724 }
725 *uiop = uio;
726 return (0);
727 }
728
729 int
730 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
731 {
732 struct uio *auio;
733 int error;
734
735 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
736 if (error)
737 return (error);
738 error = kern_readv(td, uap->fd, auio);
739 free(auio, M_IOV);
740 return (error);
741 }
742
743 int
744 freebsd32_writev(struct thread *td, struct freebsd32_writev_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_writev(td, uap->fd, auio);
753 free(auio, M_IOV);
754 return (error);
755 }
756
757 int
758 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_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_preadv(td, uap->fd, auio, uap->offset);
767 free(auio, M_IOV);
768 return (error);
769 }
770
771 int
772 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_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_pwritev(td, uap->fd, auio, uap->offset);
781 free(auio, M_IOV);
782 return (error);
783 }
784
785 static int
786 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
787 int error)
788 {
789 struct iovec32 iov32;
790 struct iovec *iov;
791 u_int iovlen;
792 int i;
793
794 *iovp = NULL;
795 if (iovcnt > UIO_MAXIOV)
796 return (error);
797 iovlen = iovcnt * sizeof(struct iovec);
798 iov = malloc(iovlen, M_IOV, M_WAITOK);
799 for (i = 0; i < iovcnt; i++) {
800 error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
801 if (error) {
802 free(iov, M_IOV);
803 return (error);
804 }
805 iov[i].iov_base = PTRIN(iov32.iov_base);
806 iov[i].iov_len = iov32.iov_len;
807 }
808 *iovp = iov;
809 return (0);
810 }
811
812 static int
813 freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
814 {
815 struct msghdr32 m32;
816 int error;
817
818 error = copyin(msg32, &m32, sizeof(m32));
819 if (error)
820 return (error);
821 msg->msg_name = PTRIN(m32.msg_name);
822 msg->msg_namelen = m32.msg_namelen;
823 msg->msg_iov = PTRIN(m32.msg_iov);
824 msg->msg_iovlen = m32.msg_iovlen;
825 msg->msg_control = PTRIN(m32.msg_control);
826 msg->msg_controllen = m32.msg_controllen;
827 msg->msg_flags = m32.msg_flags;
828 return (0);
829 }
830
831 static int
832 freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
833 {
834 struct msghdr32 m32;
835 int error;
836
837 m32.msg_name = PTROUT(msg->msg_name);
838 m32.msg_namelen = msg->msg_namelen;
839 m32.msg_iov = PTROUT(msg->msg_iov);
840 m32.msg_iovlen = msg->msg_iovlen;
841 m32.msg_control = PTROUT(msg->msg_control);
842 m32.msg_controllen = msg->msg_controllen;
843 m32.msg_flags = msg->msg_flags;
844 error = copyout(&m32, msg32, sizeof(m32));
845 return (error);
846 }
847
848 #define FREEBSD32_ALIGNBYTES (sizeof(int) - 1)
849 #define FREEBSD32_ALIGN(p) \
850 (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
851 #define FREEBSD32_CMSG_SPACE(l) \
852 (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
853
854 #define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \
855 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
856 static int
857 freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
858 {
859 struct cmsghdr *cm;
860 void *data;
861 socklen_t clen, datalen;
862 int error;
863 caddr_t ctlbuf;
864 int len, maxlen, copylen;
865 struct mbuf *m;
866 error = 0;
867
868 len = msg->msg_controllen;
869 maxlen = msg->msg_controllen;
870 msg->msg_controllen = 0;
871
872 m = control;
873 ctlbuf = msg->msg_control;
874
875 while (m && len > 0) {
876 cm = mtod(m, struct cmsghdr *);
877 clen = m->m_len;
878
879 while (cm != NULL) {
880
881 if (sizeof(struct cmsghdr) > clen ||
882 cm->cmsg_len > clen) {
883 error = EINVAL;
884 break;
885 }
886
887 data = CMSG_DATA(cm);
888 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
889
890 /* Adjust message length */
891 cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
892 datalen;
893
894
895 /* Copy cmsghdr */
896 copylen = sizeof(struct cmsghdr);
897 if (len < copylen) {
898 msg->msg_flags |= MSG_CTRUNC;
899 copylen = len;
900 }
901
902 error = copyout(cm,ctlbuf,copylen);
903 if (error)
904 goto exit;
905
906 ctlbuf += FREEBSD32_ALIGN(copylen);
907 len -= FREEBSD32_ALIGN(copylen);
908
909 if (len <= 0)
910 break;
911
912 /* Copy data */
913 copylen = datalen;
914 if (len < copylen) {
915 msg->msg_flags |= MSG_CTRUNC;
916 copylen = len;
917 }
918
919 error = copyout(data,ctlbuf,copylen);
920 if (error)
921 goto exit;
922
923 ctlbuf += FREEBSD32_ALIGN(copylen);
924 len -= FREEBSD32_ALIGN(copylen);
925
926 if (CMSG_SPACE(datalen) < clen) {
927 clen -= CMSG_SPACE(datalen);
928 cm = (struct cmsghdr *)
929 ((caddr_t)cm + CMSG_SPACE(datalen));
930 } else {
931 clen = 0;
932 cm = NULL;
933 }
934 }
935 m = m->m_next;
936 }
937
938 msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control;
939
940 exit:
941 return (error);
942
943 }
944
945 int
946 freebsd32_recvmsg(td, uap)
947 struct thread *td;
948 struct freebsd32_recvmsg_args /* {
949 int s;
950 struct msghdr32 *msg;
951 int flags;
952 } */ *uap;
953 {
954 struct msghdr msg;
955 struct msghdr32 m32;
956 struct iovec *uiov, *iov;
957 struct mbuf *control = NULL;
958 struct mbuf **controlp;
959
960 int error;
961 error = copyin(uap->msg, &m32, sizeof(m32));
962 if (error)
963 return (error);
964 error = freebsd32_copyinmsghdr(uap->msg, &msg);
965 if (error)
966 return (error);
967 error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
968 EMSGSIZE);
969 if (error)
970 return (error);
971 msg.msg_flags = uap->flags;
972 uiov = msg.msg_iov;
973 msg.msg_iov = iov;
974
975 controlp = (msg.msg_control != NULL) ? &control : NULL;
976 error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp);
977 if (error == 0) {
978 msg.msg_iov = uiov;
979
980 if (control != NULL)
981 error = freebsd32_copy_msg_out(&msg, control);
982
983 if (error == 0)
984 error = freebsd32_copyoutmsghdr(&msg, uap->msg);
985 }
986 free(iov, M_IOV);
987
988 if (control != NULL)
989 m_freem(control);
990
991 return (error);
992 }
993
994
995 static int
996 freebsd32_convert_msg_in(struct mbuf **controlp)
997 {
998 struct mbuf *control = *controlp;
999 struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1000 void *data;
1001 socklen_t clen = control->m_len, datalen;
1002 int error;
1003
1004 error = 0;
1005 *controlp = NULL;
1006
1007 while (cm != NULL) {
1008 if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1009 error = EINVAL;
1010 break;
1011 }
1012
1013 data = FREEBSD32_CMSG_DATA(cm);
1014 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1015
1016 *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1017 cm->cmsg_level);
1018 controlp = &(*controlp)->m_next;
1019
1020 if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1021 clen -= FREEBSD32_CMSG_SPACE(datalen);
1022 cm = (struct cmsghdr *)
1023 ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1024 } else {
1025 clen = 0;
1026 cm = NULL;
1027 }
1028 }
1029
1030 m_freem(control);
1031 return (error);
1032 }
1033
1034
1035 int
1036 freebsd32_sendmsg(struct thread *td,
1037 struct freebsd32_sendmsg_args *uap)
1038 {
1039 struct msghdr msg;
1040 struct msghdr32 m32;
1041 struct iovec *iov;
1042 struct mbuf *control = NULL;
1043 struct sockaddr *to = NULL;
1044 int error;
1045
1046 error = copyin(uap->msg, &m32, sizeof(m32));
1047 if (error)
1048 return (error);
1049 error = freebsd32_copyinmsghdr(uap->msg, &msg);
1050 if (error)
1051 return (error);
1052 error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1053 EMSGSIZE);
1054 if (error)
1055 return (error);
1056 msg.msg_iov = iov;
1057 if (msg.msg_name != NULL) {
1058 error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1059 if (error) {
1060 to = NULL;
1061 goto out;
1062 }
1063 msg.msg_name = to;
1064 }
1065
1066 if (msg.msg_control) {
1067 if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1068 error = EINVAL;
1069 goto out;
1070 }
1071
1072 error = sockargs(&control, msg.msg_control,
1073 msg.msg_controllen, MT_CONTROL);
1074 if (error)
1075 goto out;
1076
1077 error = freebsd32_convert_msg_in(&control);
1078 if (error)
1079 goto out;
1080 }
1081
1082 error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1083 UIO_USERSPACE);
1084
1085 out:
1086 free(iov, M_IOV);
1087 if (to)
1088 free(to, M_SONAME);
1089 return (error);
1090 }
1091
1092 int
1093 freebsd32_recvfrom(struct thread *td,
1094 struct freebsd32_recvfrom_args *uap)
1095 {
1096 struct msghdr msg;
1097 struct iovec aiov;
1098 int error;
1099
1100 if (uap->fromlenaddr) {
1101 error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1102 sizeof(msg.msg_namelen));
1103 if (error)
1104 return (error);
1105 } else {
1106 msg.msg_namelen = 0;
1107 }
1108
1109 msg.msg_name = PTRIN(uap->from);
1110 msg.msg_iov = &aiov;
1111 msg.msg_iovlen = 1;
1112 aiov.iov_base = PTRIN(uap->buf);
1113 aiov.iov_len = uap->len;
1114 msg.msg_control = NULL;
1115 msg.msg_flags = uap->flags;
1116 error = kern_recvit(td, uap->s, &msg, PTRIN(uap->fromlenaddr),
1117 UIO_USERSPACE, NULL);
1118 return (error);
1119 }
1120
1121 int
1122 freebsd32_settimeofday(struct thread *td,
1123 struct freebsd32_settimeofday_args *uap)
1124 {
1125 struct timeval32 tv32;
1126 struct timeval tv, *tvp;
1127 struct timezone tz, *tzp;
1128 int error;
1129
1130 if (uap->tv) {
1131 error = copyin(uap->tv, &tv32, sizeof(tv32));
1132 if (error)
1133 return (error);
1134 CP(tv32, tv, tv_sec);
1135 CP(tv32, tv, tv_usec);
1136 tvp = &tv;
1137 } else
1138 tvp = NULL;
1139 if (uap->tzp) {
1140 error = copyin(uap->tzp, &tz, sizeof(tz));
1141 if (error)
1142 return (error);
1143 tzp = &tz;
1144 } else
1145 tzp = NULL;
1146 return (kern_settimeofday(td, tvp, tzp));
1147 }
1148
1149 int
1150 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1151 {
1152 struct timeval32 s32[2];
1153 struct timeval s[2], *sp;
1154 int error;
1155
1156 if (uap->tptr != NULL) {
1157 error = copyin(uap->tptr, s32, sizeof(s32));
1158 if (error)
1159 return (error);
1160 CP(s32[0], s[0], tv_sec);
1161 CP(s32[0], s[0], tv_usec);
1162 CP(s32[1], s[1], tv_sec);
1163 CP(s32[1], s[1], tv_usec);
1164 sp = s;
1165 } else
1166 sp = NULL;
1167 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1168 }
1169
1170 int
1171 freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1172 {
1173 struct timeval32 s32[2];
1174 struct timeval s[2], *sp;
1175 int error;
1176
1177 if (uap->tptr != NULL) {
1178 error = copyin(uap->tptr, s32, sizeof(s32));
1179 if (error)
1180 return (error);
1181 CP(s32[0], s[0], tv_sec);
1182 CP(s32[0], s[0], tv_usec);
1183 CP(s32[1], s[1], tv_sec);
1184 CP(s32[1], s[1], tv_usec);
1185 sp = s;
1186 } else
1187 sp = NULL;
1188 return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1189 }
1190
1191 int
1192 freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1193 {
1194 struct timeval32 s32[2];
1195 struct timeval s[2], *sp;
1196 int error;
1197
1198 if (uap->tptr != NULL) {
1199 error = copyin(uap->tptr, s32, sizeof(s32));
1200 if (error)
1201 return (error);
1202 CP(s32[0], s[0], tv_sec);
1203 CP(s32[0], s[0], tv_usec);
1204 CP(s32[1], s[1], tv_sec);
1205 CP(s32[1], s[1], tv_usec);
1206 sp = s;
1207 } else
1208 sp = NULL;
1209 return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1210 }
1211
1212
1213 int
1214 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1215 {
1216 struct timeval32 tv32;
1217 struct timeval delta, olddelta, *deltap;
1218 int error;
1219
1220 if (uap->delta) {
1221 error = copyin(uap->delta, &tv32, sizeof(tv32));
1222 if (error)
1223 return (error);
1224 CP(tv32, delta, tv_sec);
1225 CP(tv32, delta, tv_usec);
1226 deltap = δ
1227 } else
1228 deltap = NULL;
1229 error = kern_adjtime(td, deltap, &olddelta);
1230 if (uap->olddelta && error == 0) {
1231 CP(olddelta, tv32, tv_sec);
1232 CP(olddelta, tv32, tv_usec);
1233 error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1234 }
1235 return (error);
1236 }
1237
1238 #ifdef COMPAT_FREEBSD4
1239 int
1240 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1241 {
1242 struct statfs32 s32;
1243 struct statfs s;
1244 int error;
1245
1246 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1247 if (error)
1248 return (error);
1249 copy_statfs(&s, &s32);
1250 return (copyout(&s32, uap->buf, sizeof(s32)));
1251 }
1252 #endif
1253
1254 #ifdef COMPAT_FREEBSD4
1255 int
1256 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1257 {
1258 struct statfs32 s32;
1259 struct statfs s;
1260 int error;
1261
1262 error = kern_fstatfs(td, uap->fd, &s);
1263 if (error)
1264 return (error);
1265 copy_statfs(&s, &s32);
1266 return (copyout(&s32, uap->buf, sizeof(s32)));
1267 }
1268 #endif
1269
1270 #ifdef COMPAT_FREEBSD4
1271 int
1272 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1273 {
1274 struct statfs32 s32;
1275 struct statfs s;
1276 fhandle_t fh;
1277 int error;
1278
1279 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1280 return (error);
1281 error = kern_fhstatfs(td, fh, &s);
1282 if (error)
1283 return (error);
1284 copy_statfs(&s, &s32);
1285 return (copyout(&s32, uap->buf, sizeof(s32)));
1286 }
1287 #endif
1288
1289 static void
1290 freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
1291 {
1292
1293 CP(*ip32, *ip, cuid);
1294 CP(*ip32, *ip, cgid);
1295 CP(*ip32, *ip, uid);
1296 CP(*ip32, *ip, gid);
1297 CP(*ip32, *ip, mode);
1298 CP(*ip32, *ip, seq);
1299 CP(*ip32, *ip, key);
1300 }
1301
1302 static void
1303 freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32)
1304 {
1305
1306 CP(*ip, *ip32, cuid);
1307 CP(*ip, *ip32, cgid);
1308 CP(*ip, *ip32, uid);
1309 CP(*ip, *ip32, gid);
1310 CP(*ip, *ip32, mode);
1311 CP(*ip, *ip32, seq);
1312 CP(*ip, *ip32, key);
1313 }
1314
1315 int
1316 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1317 {
1318
1319 switch (uap->which) {
1320 case 0:
1321 return (freebsd32_semctl(td,
1322 (struct freebsd32_semctl_args *)&uap->a2));
1323 default:
1324 return (semsys(td, (struct semsys_args *)uap));
1325 }
1326 }
1327
1328 int
1329 freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
1330 {
1331 struct semid_ds32 dsbuf32;
1332 struct semid_ds dsbuf;
1333 union semun semun;
1334 union semun32 arg;
1335 register_t rval;
1336 int error;
1337
1338 switch (uap->cmd) {
1339 case SEM_STAT:
1340 case IPC_SET:
1341 case IPC_STAT:
1342 case GETALL:
1343 case SETVAL:
1344 case SETALL:
1345 error = copyin(uap->arg, &arg, sizeof(arg));
1346 if (error)
1347 return (error);
1348 break;
1349 }
1350
1351 switch (uap->cmd) {
1352 case SEM_STAT:
1353 case IPC_STAT:
1354 semun.buf = &dsbuf;
1355 break;
1356 case IPC_SET:
1357 error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1358 if (error)
1359 return (error);
1360 freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1361 PTRIN_CP(dsbuf32, dsbuf, sem_base);
1362 CP(dsbuf32, dsbuf, sem_nsems);
1363 CP(dsbuf32, dsbuf, sem_otime);
1364 CP(dsbuf32, dsbuf, sem_pad1);
1365 CP(dsbuf32, dsbuf, sem_ctime);
1366 CP(dsbuf32, dsbuf, sem_pad2);
1367 CP(dsbuf32, dsbuf, sem_pad3[0]);
1368 CP(dsbuf32, dsbuf, sem_pad3[1]);
1369 CP(dsbuf32, dsbuf, sem_pad3[2]);
1370 CP(dsbuf32, dsbuf, sem_pad3[3]);
1371 semun.buf = &dsbuf;
1372 break;
1373 case GETALL:
1374 case SETALL:
1375 semun.array = PTRIN(arg.array);
1376 break;
1377 case SETVAL:
1378 semun.val = arg.val;
1379 break;
1380 }
1381
1382 error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1383 &rval);
1384 if (error)
1385 return (error);
1386
1387 switch (uap->cmd) {
1388 case SEM_STAT:
1389 case IPC_STAT:
1390 freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1391 PTROUT_CP(dsbuf, dsbuf32, sem_base);
1392 CP(dsbuf, dsbuf32, sem_nsems);
1393 CP(dsbuf, dsbuf32, sem_otime);
1394 CP(dsbuf, dsbuf32, sem_pad1);
1395 CP(dsbuf, dsbuf32, sem_ctime);
1396 CP(dsbuf, dsbuf32, sem_pad2);
1397 CP(dsbuf, dsbuf32, sem_pad3[0]);
1398 CP(dsbuf, dsbuf32, sem_pad3[1]);
1399 CP(dsbuf, dsbuf32, sem_pad3[2]);
1400 CP(dsbuf, dsbuf32, sem_pad3[3]);
1401 error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1402 break;
1403 }
1404
1405 if (error == 0)
1406 td->td_retval[0] = rval;
1407 return (error);
1408 }
1409
1410 int
1411 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1412 {
1413
1414 switch (uap->which) {
1415 case 0:
1416 return (freebsd32_msgctl(td,
1417 (struct freebsd32_msgctl_args *)&uap->a2));
1418 case 2:
1419 return (freebsd32_msgsnd(td,
1420 (struct freebsd32_msgsnd_args *)&uap->a2));
1421 case 3:
1422 return (freebsd32_msgrcv(td,
1423 (struct freebsd32_msgrcv_args *)&uap->a2));
1424 default:
1425 return (msgsys(td, (struct msgsys_args *)uap));
1426 }
1427 }
1428
1429 int
1430 freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
1431 {
1432 struct msqid_ds msqbuf;
1433 struct msqid_ds32 msqbuf32;
1434 int error;
1435
1436 if (uap->cmd == IPC_SET) {
1437 error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1438 if (error)
1439 return (error);
1440 freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1441 PTRIN_CP(msqbuf32, msqbuf, msg_first);
1442 PTRIN_CP(msqbuf32, msqbuf, msg_last);
1443 CP(msqbuf32, msqbuf, msg_cbytes);
1444 CP(msqbuf32, msqbuf, msg_qnum);
1445 CP(msqbuf32, msqbuf, msg_qbytes);
1446 CP(msqbuf32, msqbuf, msg_lspid);
1447 CP(msqbuf32, msqbuf, msg_lrpid);
1448 CP(msqbuf32, msqbuf, msg_stime);
1449 CP(msqbuf32, msqbuf, msg_pad1);
1450 CP(msqbuf32, msqbuf, msg_rtime);
1451 CP(msqbuf32, msqbuf, msg_pad2);
1452 CP(msqbuf32, msqbuf, msg_ctime);
1453 CP(msqbuf32, msqbuf, msg_pad3);
1454 CP(msqbuf32, msqbuf, msg_pad4[0]);
1455 CP(msqbuf32, msqbuf, msg_pad4[1]);
1456 CP(msqbuf32, msqbuf, msg_pad4[2]);
1457 CP(msqbuf32, msqbuf, msg_pad4[3]);
1458 }
1459 error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1460 if (error)
1461 return (error);
1462 if (uap->cmd == IPC_STAT) {
1463 freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1464 PTROUT_CP(msqbuf, msqbuf32, msg_first);
1465 PTROUT_CP(msqbuf, msqbuf32, msg_last);
1466 CP(msqbuf, msqbuf32, msg_cbytes);
1467 CP(msqbuf, msqbuf32, msg_qnum);
1468 CP(msqbuf, msqbuf32, msg_qbytes);
1469 CP(msqbuf, msqbuf32, msg_lspid);
1470 CP(msqbuf, msqbuf32, msg_lrpid);
1471 CP(msqbuf, msqbuf32, msg_stime);
1472 CP(msqbuf, msqbuf32, msg_pad1);
1473 CP(msqbuf, msqbuf32, msg_rtime);
1474 CP(msqbuf, msqbuf32, msg_pad2);
1475 CP(msqbuf, msqbuf32, msg_ctime);
1476 CP(msqbuf, msqbuf32, msg_pad3);
1477 CP(msqbuf, msqbuf32, msg_pad4[0]);
1478 CP(msqbuf, msqbuf32, msg_pad4[1]);
1479 CP(msqbuf, msqbuf32, msg_pad4[2]);
1480 CP(msqbuf, msqbuf32, msg_pad4[3]);
1481 error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1482 }
1483 return (error);
1484 }
1485
1486 int
1487 freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1488 {
1489 const void *msgp;
1490 long mtype;
1491 int32_t mtype32;
1492 int error;
1493
1494 msgp = PTRIN(uap->msgp);
1495 if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1496 return (error);
1497 mtype = mtype32;
1498 return (kern_msgsnd(td, uap->msqid,
1499 (const char *)msgp + sizeof(mtype32),
1500 uap->msgsz, uap->msgflg, mtype));
1501 }
1502
1503 int
1504 freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1505 {
1506 void *msgp;
1507 long mtype;
1508 int32_t mtype32;
1509 int error;
1510
1511 msgp = PTRIN(uap->msgp);
1512 if ((error = kern_msgrcv(td, uap->msqid,
1513 (char *)msgp + sizeof(mtype32), uap->msgsz,
1514 uap->msgtyp, uap->msgflg, &mtype)) != 0)
1515 return (error);
1516 mtype32 = (int32_t)mtype;
1517 return (copyout(&mtype32, msgp, sizeof(mtype32)));
1518 }
1519
1520 int
1521 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1522 {
1523
1524 switch (uap->which) {
1525 case 0: { /* shmat */
1526 struct shmat_args ap;
1527
1528 ap.shmid = uap->a2;
1529 ap.shmaddr = PTRIN(uap->a3);
1530 ap.shmflg = uap->a4;
1531 return (sysent[SYS_shmat].sy_call(td, &ap));
1532 }
1533 case 2: { /* shmdt */
1534 struct shmdt_args ap;
1535
1536 ap.shmaddr = PTRIN(uap->a2);
1537 return (sysent[SYS_shmdt].sy_call(td, &ap));
1538 }
1539 case 3: { /* shmget */
1540 struct shmget_args ap;
1541
1542 ap.key = uap->a2;
1543 ap.size = uap->a3;
1544 ap.shmflg = uap->a4;
1545 return (sysent[SYS_shmget].sy_call(td, &ap));
1546 }
1547 case 4: { /* shmctl */
1548 struct freebsd32_shmctl_args ap;
1549
1550 ap.shmid = uap->a2;
1551 ap.cmd = uap->a3;
1552 ap.buf = PTRIN(uap->a4);
1553 return (freebsd32_shmctl(td, &ap));
1554 }
1555 case 1: /* oshmctl */
1556 default:
1557 return (EINVAL);
1558 }
1559 }
1560
1561 int
1562 freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1563 {
1564 int error = 0;
1565 union {
1566 struct shmid_ds shmid_ds;
1567 struct shm_info shm_info;
1568 struct shminfo shminfo;
1569 } u;
1570 union {
1571 struct shmid_ds32 shmid_ds32;
1572 struct shm_info32 shm_info32;
1573 struct shminfo32 shminfo32;
1574 } u32;
1575 size_t sz;
1576
1577 if (uap->cmd == IPC_SET) {
1578 if ((error = copyin(uap->buf, &u32.shmid_ds32,
1579 sizeof(u32.shmid_ds32))))
1580 goto done;
1581 freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
1582 &u.shmid_ds.shm_perm);
1583 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1584 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1585 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1586 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1587 CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1588 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1589 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1590 PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
1591 }
1592
1593 error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1594 if (error)
1595 goto done;
1596
1597 /* Cases in which we need to copyout */
1598 switch (uap->cmd) {
1599 case IPC_INFO:
1600 CP(u.shminfo, u32.shminfo32, shmmax);
1601 CP(u.shminfo, u32.shminfo32, shmmin);
1602 CP(u.shminfo, u32.shminfo32, shmmni);
1603 CP(u.shminfo, u32.shminfo32, shmseg);
1604 CP(u.shminfo, u32.shminfo32, shmall);
1605 error = copyout(&u32.shminfo32, uap->buf,
1606 sizeof(u32.shminfo32));
1607 break;
1608 case SHM_INFO:
1609 CP(u.shm_info, u32.shm_info32, used_ids);
1610 CP(u.shm_info, u32.shm_info32, shm_rss);
1611 CP(u.shm_info, u32.shm_info32, shm_tot);
1612 CP(u.shm_info, u32.shm_info32, shm_swp);
1613 CP(u.shm_info, u32.shm_info32, swap_attempts);
1614 CP(u.shm_info, u32.shm_info32, swap_successes);
1615 error = copyout(&u32.shm_info32, uap->buf,
1616 sizeof(u32.shm_info32));
1617 break;
1618 case SHM_STAT:
1619 case IPC_STAT:
1620 freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
1621 &u32.shmid_ds32.shm_perm);
1622 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1623 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1624 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1625 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1626 CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1627 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1628 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1629 PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
1630 error = copyout(&u32.shmid_ds32, uap->buf,
1631 sizeof(u32.shmid_ds32));
1632 break;
1633 }
1634
1635 done:
1636 if (error) {
1637 /* Invalidate the return value */
1638 td->td_retval[0] = -1;
1639 }
1640 return (error);
1641 }
1642
1643 int
1644 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1645 {
1646 struct pread_args ap;
1647
1648 ap.fd = uap->fd;
1649 ap.buf = uap->buf;
1650 ap.nbyte = uap->nbyte;
1651 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1652 return (pread(td, &ap));
1653 }
1654
1655 int
1656 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1657 {
1658 struct pwrite_args ap;
1659
1660 ap.fd = uap->fd;
1661 ap.buf = uap->buf;
1662 ap.nbyte = uap->nbyte;
1663 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1664 return (pwrite(td, &ap));
1665 }
1666
1667 int
1668 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1669 {
1670 int error;
1671 struct lseek_args ap;
1672 off_t pos;
1673
1674 ap.fd = uap->fd;
1675 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1676 ap.whence = uap->whence;
1677 error = lseek(td, &ap);
1678 /* Expand the quad return into two parts for eax and edx */
1679 pos = *(off_t *)(td->td_retval);
1680 td->td_retval[0] = pos & 0xffffffff; /* %eax */
1681 td->td_retval[1] = pos >> 32; /* %edx */
1682 return error;
1683 }
1684
1685 int
1686 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1687 {
1688 struct truncate_args ap;
1689
1690 ap.path = uap->path;
1691 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1692 return (truncate(td, &ap));
1693 }
1694
1695 int
1696 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1697 {
1698 struct ftruncate_args ap;
1699
1700 ap.fd = uap->fd;
1701 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1702 return (ftruncate(td, &ap));
1703 }
1704
1705 int
1706 freebsd32_getdirentries(struct thread *td,
1707 struct freebsd32_getdirentries_args *uap)
1708 {
1709 long base;
1710 int32_t base32;
1711 int error;
1712
1713 error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
1714 if (error)
1715 return (error);
1716 if (uap->basep != NULL) {
1717 base32 = base;
1718 error = copyout(&base32, uap->basep, sizeof(int32_t));
1719 }
1720 return (error);
1721 }
1722
1723 struct sf_hdtr32 {
1724 uint32_t headers;
1725 int hdr_cnt;
1726 uint32_t trailers;
1727 int trl_cnt;
1728 };
1729
1730 static int
1731 freebsd32_do_sendfile(struct thread *td,
1732 struct freebsd32_sendfile_args *uap, int compat)
1733 {
1734 struct sendfile_args ap;
1735 struct sf_hdtr32 hdtr32;
1736 struct sf_hdtr hdtr;
1737 struct uio *hdr_uio, *trl_uio;
1738 struct iovec32 *iov32;
1739 int error;
1740
1741 hdr_uio = trl_uio = NULL;
1742
1743 ap.fd = uap->fd;
1744 ap.s = uap->s;
1745 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1746 ap.nbytes = uap->nbytes;
1747 ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */
1748 ap.sbytes = uap->sbytes;
1749 ap.flags = uap->flags;
1750
1751 if (uap->hdtr != NULL) {
1752 error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1753 if (error)
1754 goto out;
1755 PTRIN_CP(hdtr32, hdtr, headers);
1756 CP(hdtr32, hdtr, hdr_cnt);
1757 PTRIN_CP(hdtr32, hdtr, trailers);
1758 CP(hdtr32, hdtr, trl_cnt);
1759
1760 if (hdtr.headers != NULL) {
1761 iov32 = PTRIN(hdtr32.headers);
1762 error = freebsd32_copyinuio(iov32,
1763 hdtr32.hdr_cnt, &hdr_uio);
1764 if (error)
1765 goto out;
1766 }
1767 if (hdtr.trailers != NULL) {
1768 iov32 = PTRIN(hdtr32.trailers);
1769 error = freebsd32_copyinuio(iov32,
1770 hdtr32.trl_cnt, &trl_uio);
1771 if (error)
1772 goto out;
1773 }
1774 }
1775
1776 error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1777 out:
1778 if (hdr_uio)
1779 free(hdr_uio, M_IOV);
1780 if (trl_uio)
1781 free(trl_uio, M_IOV);
1782 return (error);
1783 }
1784
1785 #ifdef COMPAT_FREEBSD4
1786 int
1787 freebsd4_freebsd32_sendfile(struct thread *td,
1788 struct freebsd4_freebsd32_sendfile_args *uap)
1789 {
1790 return (freebsd32_do_sendfile(td,
1791 (struct freebsd32_sendfile_args *)uap, 1));
1792 }
1793 #endif
1794
1795 int
1796 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1797 {
1798
1799 return (freebsd32_do_sendfile(td, uap, 0));
1800 }
1801
1802 static void
1803 copy_stat( struct stat *in, struct stat32 *out)
1804 {
1805 CP(*in, *out, st_dev);
1806 CP(*in, *out, st_ino);
1807 CP(*in, *out, st_mode);
1808 CP(*in, *out, st_nlink);
1809 CP(*in, *out, st_uid);
1810 CP(*in, *out, st_gid);
1811 CP(*in, *out, st_rdev);
1812 TS_CP(*in, *out, st_atimespec);
1813 TS_CP(*in, *out, st_mtimespec);
1814 TS_CP(*in, *out, st_ctimespec);
1815 CP(*in, *out, st_size);
1816 CP(*in, *out, st_blocks);
1817 CP(*in, *out, st_blksize);
1818 CP(*in, *out, st_flags);
1819 CP(*in, *out, st_gen);
1820 }
1821
1822 int
1823 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1824 {
1825 struct stat sb;
1826 struct stat32 sb32;
1827 int error;
1828
1829 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1830 if (error)
1831 return (error);
1832 copy_stat(&sb, &sb32);
1833 error = copyout(&sb32, uap->ub, sizeof (sb32));
1834 return (error);
1835 }
1836
1837 int
1838 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1839 {
1840 struct stat ub;
1841 struct stat32 ub32;
1842 int error;
1843
1844 error = kern_fstat(td, uap->fd, &ub);
1845 if (error)
1846 return (error);
1847 copy_stat(&ub, &ub32);
1848 error = copyout(&ub32, uap->ub, sizeof(ub32));
1849 return (error);
1850 }
1851
1852 int
1853 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1854 {
1855 struct stat sb;
1856 struct stat32 sb32;
1857 int error;
1858
1859 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1860 if (error)
1861 return (error);
1862 copy_stat(&sb, &sb32);
1863 error = copyout(&sb32, uap->ub, sizeof (sb32));
1864 return (error);
1865 }
1866
1867 /*
1868 * MPSAFE
1869 */
1870 int
1871 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1872 {
1873 int error, name[CTL_MAXNAME];
1874 size_t j, oldlen;
1875
1876 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1877 return (EINVAL);
1878 error = copyin(uap->name, name, uap->namelen * sizeof(int));
1879 if (error)
1880 return (error);
1881 mtx_lock(&Giant);
1882 if (uap->oldlenp)
1883 oldlen = fuword32(uap->oldlenp);
1884 else
1885 oldlen = 0;
1886 error = userland_sysctl(td, name, uap->namelen,
1887 uap->old, &oldlen, 1,
1888 uap->new, uap->newlen, &j, SCTL_MASK32);
1889 if (error && error != ENOMEM)
1890 goto done2;
1891 if (uap->oldlenp)
1892 suword32(uap->oldlenp, j);
1893 done2:
1894 mtx_unlock(&Giant);
1895 return (error);
1896 }
1897
1898 int
1899 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1900 {
1901 struct sigaction32 s32;
1902 struct sigaction sa, osa, *sap;
1903 int error;
1904
1905 if (uap->act) {
1906 error = copyin(uap->act, &s32, sizeof(s32));
1907 if (error)
1908 return (error);
1909 sa.sa_handler = PTRIN(s32.sa_u);
1910 CP(s32, sa, sa_flags);
1911 CP(s32, sa, sa_mask);
1912 sap = &sa;
1913 } else
1914 sap = NULL;
1915 error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1916 if (error == 0 && uap->oact != NULL) {
1917 s32.sa_u = PTROUT(osa.sa_handler);
1918 CP(osa, s32, sa_flags);
1919 CP(osa, s32, sa_mask);
1920 error = copyout(&s32, uap->oact, sizeof(s32));
1921 }
1922 return (error);
1923 }
1924
1925 #ifdef COMPAT_FREEBSD4
1926 int
1927 freebsd4_freebsd32_sigaction(struct thread *td,
1928 struct freebsd4_freebsd32_sigaction_args *uap)
1929 {
1930 struct sigaction32 s32;
1931 struct sigaction sa, osa, *sap;
1932 int error;
1933
1934 if (uap->act) {
1935 error = copyin(uap->act, &s32, sizeof(s32));
1936 if (error)
1937 return (error);
1938 sa.sa_handler = PTRIN(s32.sa_u);
1939 CP(s32, sa, sa_flags);
1940 CP(s32, sa, sa_mask);
1941 sap = &sa;
1942 } else
1943 sap = NULL;
1944 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1945 if (error == 0 && uap->oact != NULL) {
1946 s32.sa_u = PTROUT(osa.sa_handler);
1947 CP(osa, s32, sa_flags);
1948 CP(osa, s32, sa_mask);
1949 error = copyout(&s32, uap->oact, sizeof(s32));
1950 }
1951 return (error);
1952 }
1953 #endif
1954
1955 #ifdef COMPAT_43
1956 struct osigaction32 {
1957 u_int32_t sa_u;
1958 osigset_t sa_mask;
1959 int sa_flags;
1960 };
1961
1962 #define ONSIG 32
1963
1964 int
1965 ofreebsd32_sigaction(struct thread *td,
1966 struct ofreebsd32_sigaction_args *uap)
1967 {
1968 struct osigaction32 s32;
1969 struct sigaction sa, osa, *sap;
1970 int error;
1971
1972 if (uap->signum <= 0 || uap->signum >= ONSIG)
1973 return (EINVAL);
1974
1975 if (uap->nsa) {
1976 error = copyin(uap->nsa, &s32, sizeof(s32));
1977 if (error)
1978 return (error);
1979 sa.sa_handler = PTRIN(s32.sa_u);
1980 CP(s32, sa, sa_flags);
1981 OSIG2SIG(s32.sa_mask, sa.sa_mask);
1982 sap = &sa;
1983 } else
1984 sap = NULL;
1985 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1986 if (error == 0 && uap->osa != NULL) {
1987 s32.sa_u = PTROUT(osa.sa_handler);
1988 CP(osa, s32, sa_flags);
1989 SIG2OSIG(osa.sa_mask, s32.sa_mask);
1990 error = copyout(&s32, uap->osa, sizeof(s32));
1991 }
1992 return (error);
1993 }
1994
1995 int
1996 ofreebsd32_sigprocmask(struct thread *td,
1997 struct ofreebsd32_sigprocmask_args *uap)
1998 {
1999 sigset_t set, oset;
2000 int error;
2001
2002 OSIG2SIG(uap->mask, set);
2003 error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
2004 SIG2OSIG(oset, td->td_retval[0]);
2005 return (error);
2006 }
2007
2008 int
2009 ofreebsd32_sigpending(struct thread *td,
2010 struct ofreebsd32_sigpending_args *uap)
2011 {
2012 struct proc *p = td->td_proc;
2013 sigset_t siglist;
2014
2015 PROC_LOCK(p);
2016 siglist = p->p_siglist;
2017 SIGSETOR(siglist, td->td_siglist);
2018 PROC_UNLOCK(p);
2019 SIG2OSIG(siglist, td->td_retval[0]);
2020 return (0);
2021 }
2022
2023 struct sigvec32 {
2024 u_int32_t sv_handler;
2025 int sv_mask;
2026 int sv_flags;
2027 };
2028
2029 int
2030 ofreebsd32_sigvec(struct thread *td,
2031 struct ofreebsd32_sigvec_args *uap)
2032 {
2033 struct sigvec32 vec;
2034 struct sigaction sa, osa, *sap;
2035 int error;
2036
2037 if (uap->signum <= 0 || uap->signum >= ONSIG)
2038 return (EINVAL);
2039
2040 if (uap->nsv) {
2041 error = copyin(uap->nsv, &vec, sizeof(vec));
2042 if (error)
2043 return (error);
2044 sa.sa_handler = PTRIN(vec.sv_handler);
2045 OSIG2SIG(vec.sv_mask, sa.sa_mask);
2046 sa.sa_flags = vec.sv_flags;
2047 sa.sa_flags ^= SA_RESTART;
2048 sap = &sa;
2049 } else
2050 sap = NULL;
2051 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2052 if (error == 0 && uap->osv != NULL) {
2053 vec.sv_handler = PTROUT(osa.sa_handler);
2054 SIG2OSIG(osa.sa_mask, vec.sv_mask);
2055 vec.sv_flags = osa.sa_flags;
2056 vec.sv_flags &= ~SA_NOCLDWAIT;
2057 vec.sv_flags ^= SA_RESTART;
2058 error = copyout(&vec, uap->osv, sizeof(vec));
2059 }
2060 return (error);
2061 }
2062
2063 int
2064 ofreebsd32_sigblock(struct thread *td,
2065 struct ofreebsd32_sigblock_args *uap)
2066 {
2067 struct proc *p = td->td_proc;
2068 sigset_t set;
2069
2070 OSIG2SIG(uap->mask, set);
2071 SIG_CANTMASK(set);
2072 PROC_LOCK(p);
2073 SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2074 SIGSETOR(td->td_sigmask, set);
2075 PROC_UNLOCK(p);
2076 return (0);
2077 }
2078
2079 int
2080 ofreebsd32_sigsetmask(struct thread *td,
2081 struct ofreebsd32_sigsetmask_args *uap)
2082 {
2083 struct proc *p = td->td_proc;
2084 sigset_t set;
2085
2086 OSIG2SIG(uap->mask, set);
2087 SIG_CANTMASK(set);
2088 PROC_LOCK(p);
2089 SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2090 SIGSETLO(td->td_sigmask, set);
2091 signotify(td);
2092 PROC_UNLOCK(p);
2093 return (0);
2094 }
2095
2096 int
2097 ofreebsd32_sigsuspend(struct thread *td,
2098 struct ofreebsd32_sigsuspend_args *uap)
2099 {
2100 struct proc *p = td->td_proc;
2101 sigset_t mask;
2102
2103 PROC_LOCK(p);
2104 td->td_oldsigmask = td->td_sigmask;
2105 td->td_pflags |= TDP_OLDMASK;
2106 OSIG2SIG(uap->mask, mask);
2107 SIG_CANTMASK(mask);
2108 SIGSETLO(td->td_sigmask, mask);
2109 signotify(td);
2110 while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
2111 /* void */;
2112 PROC_UNLOCK(p);
2113 /* always return EINTR rather than ERESTART... */
2114 return (EINTR);
2115 }
2116
2117 struct sigstack32 {
2118 u_int32_t ss_sp;
2119 int ss_onstack;
2120 };
2121
2122 int
2123 ofreebsd32_sigstack(struct thread *td,
2124 struct ofreebsd32_sigstack_args *uap)
2125 {
2126 struct sigstack32 s32;
2127 struct sigstack nss, oss;
2128 int error = 0;
2129
2130 if (uap->nss != NULL) {
2131 error = copyin(uap->nss, &s32, sizeof(s32));
2132 if (error)
2133 return (error);
2134 nss.ss_sp = PTRIN(s32.ss_sp);
2135 CP(s32, nss, ss_onstack);
2136 }
2137 oss.ss_sp = td->td_sigstk.ss_sp;
2138 oss.ss_onstack = sigonstack(cpu_getstack(td));
2139 if (uap->nss != NULL) {
2140 td->td_sigstk.ss_sp = nss.ss_sp;
2141 td->td_sigstk.ss_size = 0;
2142 td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
2143 td->td_pflags |= TDP_ALTSTACK;
2144 }
2145 if (uap->oss != NULL) {
2146 s32.ss_sp = PTROUT(oss.ss_sp);
2147 CP(oss, s32, ss_onstack);
2148 error = copyout(&s32, uap->oss, sizeof(s32));
2149 }
2150 return (error);
2151 }
2152 #endif
2153
2154 int
2155 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2156 {
2157 struct timespec32 rmt32, rqt32;
2158 struct timespec rmt, rqt;
2159 int error;
2160
2161 error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2162 if (error)
2163 return (error);
2164
2165 CP(rqt32, rqt, tv_sec);
2166 CP(rqt32, rqt, tv_nsec);
2167
2168 if (uap->rmtp &&
2169 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2170 return (EFAULT);
2171 error = kern_nanosleep(td, &rqt, &rmt);
2172 if (error && uap->rmtp) {
2173 int error2;
2174
2175 CP(rmt, rmt32, tv_sec);
2176 CP(rmt, rmt32, tv_nsec);
2177
2178 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2179 if (error2)
2180 error = error2;
2181 }
2182 return (error);
2183 }
2184
2185 int
2186 freebsd32_clock_gettime(struct thread *td,
2187 struct freebsd32_clock_gettime_args *uap)
2188 {
2189 struct timespec ats;
2190 struct timespec32 ats32;
2191 int error;
2192
2193 error = kern_clock_gettime(td, uap->clock_id, &ats);
2194 if (error == 0) {
2195 CP(ats, ats32, tv_sec);
2196 CP(ats, ats32, tv_nsec);
2197 error = copyout(&ats32, uap->tp, sizeof(ats32));
2198 }
2199 return (error);
2200 }
2201
2202 int
2203 freebsd32_clock_settime(struct thread *td,
2204 struct freebsd32_clock_settime_args *uap)
2205 {
2206 struct timespec ats;
2207 struct timespec32 ats32;
2208 int error;
2209
2210 error = copyin(uap->tp, &ats32, sizeof(ats32));
2211 if (error)
2212 return (error);
2213 CP(ats32, ats, tv_sec);
2214 CP(ats32, ats, tv_nsec);
2215
2216 return (kern_clock_settime(td, uap->clock_id, &ats));
2217 }
2218
2219 int
2220 freebsd32_clock_getres(struct thread *td,
2221 struct freebsd32_clock_getres_args *uap)
2222 {
2223 struct timespec ts;
2224 struct timespec32 ts32;
2225 int error;
2226
2227 if (uap->tp == NULL)
2228 return (0);
2229 error = kern_clock_getres(td, uap->clock_id, &ts);
2230 if (error == 0) {
2231 CP(ts, ts32, tv_sec);
2232 CP(ts, ts32, tv_nsec);
2233 error = copyout(&ts32, uap->tp, sizeof(ts32));
2234 }
2235 return (error);
2236 }
2237
2238 int
2239 freebsd32_thr_new(struct thread *td,
2240 struct freebsd32_thr_new_args *uap)
2241 {
2242 struct thr_param32 param32;
2243 struct thr_param param;
2244 int error;
2245
2246 if (uap->param_size < 0 ||
2247 uap->param_size > sizeof(struct thr_param32))
2248 return (EINVAL);
2249 bzero(¶m, sizeof(struct thr_param));
2250 bzero(¶m32, sizeof(struct thr_param32));
2251 error = copyin(uap->param, ¶m32, uap->param_size);
2252 if (error != 0)
2253 return (error);
2254 param.start_func = PTRIN(param32.start_func);
2255 param.arg = PTRIN(param32.arg);
2256 param.stack_base = PTRIN(param32.stack_base);
2257 param.stack_size = param32.stack_size;
2258 param.tls_base = PTRIN(param32.tls_base);
2259 param.tls_size = param32.tls_size;
2260 param.child_tid = PTRIN(param32.child_tid);
2261 param.parent_tid = PTRIN(param32.parent_tid);
2262 param.flags = param32.flags;
2263 param.spare[0] = PTRIN(param32.spare[0]);
2264 param.spare[1] = PTRIN(param32.spare[1]);
2265 param.spare[2] = PTRIN(param32.spare[2]);
2266 param.spare[3] = PTRIN(param32.spare[3]);
2267
2268 return (kern_thr_new(td, ¶m));
2269 }
2270
2271 int
2272 freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2273 {
2274 struct timespec32 ts32;
2275 struct timespec ts, *tsp;
2276 int error;
2277
2278 error = 0;
2279 tsp = NULL;
2280 if (uap->timeout != NULL) {
2281 error = copyin((const void *)uap->timeout, (void *)&ts32,
2282 sizeof(struct timespec32));
2283 if (error != 0)
2284 return (error);
2285 ts.tv_sec = ts32.tv_sec;
2286 ts.tv_nsec = ts32.tv_nsec;
2287 tsp = &ts;
2288 }
2289 return (kern_thr_suspend(td, tsp));
2290 }
2291
2292 #if 0
2293
2294 int
2295 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2296 {
2297 int error;
2298 struct yyy32 *p32, s32;
2299 struct yyy *p = NULL, s;
2300
2301 if (uap->zzz) {
2302 error = copyin(uap->zzz, &s32, sizeof(s32));
2303 if (error)
2304 return (error);
2305 /* translate in */
2306 p = &s;
2307 }
2308 error = kern_xxx(td, p);
2309 if (error)
2310 return (error);
2311 if (uap->zzz) {
2312 /* translate out */
2313 error = copyout(&s32, p32, sizeof(s32));
2314 }
2315 return (error);
2316 }
2317
2318 #endif
2319
2320 int
2321 syscall32_register(int *offset, struct sysent *new_sysent,
2322 struct sysent *old_sysent)
2323 {
2324 if (*offset == NO_SYSCALL) {
2325 int i;
2326
2327 for (i = 1; i < SYS_MAXSYSCALL; ++i)
2328 if (freebsd32_sysent[i].sy_call ==
2329 (sy_call_t *)lkmnosys)
2330 break;
2331 if (i == SYS_MAXSYSCALL)
2332 return (ENFILE);
2333 *offset = i;
2334 } else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
2335 return (EINVAL);
2336 else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
2337 freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
2338 return (EEXIST);
2339
2340 *old_sysent = freebsd32_sysent[*offset];
2341 freebsd32_sysent[*offset] = *new_sysent;
2342 return 0;
2343 }
2344
2345 int
2346 syscall32_deregister(int *offset, struct sysent *old_sysent)
2347 {
2348
2349 if (*offset)
2350 freebsd32_sysent[*offset] = *old_sysent;
2351 return 0;
2352 }
2353
2354 int
2355 syscall32_module_handler(struct module *mod, int what, void *arg)
2356 {
2357 struct syscall_module_data *data = (struct syscall_module_data*)arg;
2358 modspecific_t ms;
2359 int error;
2360
2361 switch (what) {
2362 case MOD_LOAD:
2363 error = syscall32_register(data->offset, data->new_sysent,
2364 &data->old_sysent);
2365 if (error) {
2366 /* Leave a mark so we know to safely unload below. */
2367 data->offset = NULL;
2368 return error;
2369 }
2370 ms.intval = *data->offset;
2371 MOD_XLOCK;
2372 module_setspecific(mod, &ms);
2373 MOD_XUNLOCK;
2374 if (data->chainevh)
2375 error = data->chainevh(mod, what, data->chainarg);
2376 return (error);
2377 case MOD_UNLOAD:
2378 /*
2379 * MOD_LOAD failed, so just return without calling the
2380 * chained handler since we didn't pass along the MOD_LOAD
2381 * event.
2382 */
2383 if (data->offset == NULL)
2384 return (0);
2385 if (data->chainevh) {
2386 error = data->chainevh(mod, what, data->chainarg);
2387 if (error)
2388 return (error);
2389 }
2390 error = syscall32_deregister(data->offset, &data->old_sysent);
2391 return (error);
2392 default:
2393 error = EOPNOTSUPP;
2394 if (data->chainevh)
2395 error = data->chainevh(mod, what, data->chainarg);
2396 return (error);
2397 }
2398 }
Cache object: 4a96a6ed0f955bcefd1d461317275fb3
|