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