freebsd32_misc.c revision 146950
16562Sphk/*- 237421Scharnier * Copyright (c) 2002 Doug Rabson 36562Sphk * All rights reserved. 46562Sphk * 53995Spst * Redistribution and use in source and binary forms, with or without 63995Spst * modification, are permitted provided that the following conditions 76562Sphk * are met: 86562Sphk * 1. Redistributions of source code must retain the above copyright 96562Sphk * notice, this list of conditions and the following disclaimer. 106562Sphk * 2. Redistributions in binary form must reproduce the above copyright 116562Sphk * notice, this list of conditions and the following disclaimer in the 126562Sphk * documentation and/or other materials provided with the distribution. 136562Sphk * 146562Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 156562Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 166562Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 176562Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 183995Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 193995Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2037421Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2137421Scharnier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2250476Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2337421Scharnier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2437421Scharnier * SUCH DAMAGE. 2519168Sbde */ 2637421Scharnier 2719168Sbde#include <sys/cdefs.h> 283995Spst__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 146950 2005-06-03 23:15:01Z ps $"); 293995Spst 3032074Ssteve#include "opt_compat.h" 3148953Sbillf 3219168Sbde#include <sys/param.h> 333995Spst#include <sys/systm.h> 343995Spst#include <sys/bus.h> 356562Sphk#include <sys/exec.h> 366562Sphk#include <sys/fcntl.h> 373995Spst#include <sys/filedesc.h> 3846226Skris#include <sys/namei.h> 3946226Skris#include <sys/imgact.h> 403995Spst#include <sys/kernel.h> 4152949Sobrien#include <sys/lock.h> 4252949Sobrien#include <sys/malloc.h> 436562Sphk#include <sys/file.h> /* Must come after sys/malloc.h */ 446562Sphk#include <sys/mman.h> 456562Sphk#include <sys/module.h> 466725Sphk#include <sys/mount.h> 4732074Ssteve#include <sys/mutex.h> 483995Spst#include <sys/namei.h> 493995Spst#include <sys/param.h> 503995Spst#include <sys/proc.h> 513995Spst#include <sys/reboot.h> 523995Spst#include <sys/resource.h> 533995Spst#include <sys/resourcevar.h> 543995Spst#include <sys/selinfo.h> 553995Spst#include <sys/eventvar.h> /* Must come after sys/selinfo.h */ 563995Spst#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 573995Spst#include <sys/signal.h> 586562Sphk#include <sys/signalvar.h> 596562Sphk#include <sys/socket.h> 606562Sphk#include <sys/socketvar.h> 616562Sphk#include <sys/stat.h> 623995Spst#include <sys/syscallsubr.h> 6332086Ssteve#include <sys/sysctl.h> 646562Sphk#include <sys/sysent.h> 659489Sphk#include <sys/sysproto.h> 663995Spst#include <sys/systm.h> 6732074Ssteve#include <sys/unistd.h> 6852949Sobrien#include <sys/vnode.h> 6932086Ssteve#include <sys/wait.h> 7032074Ssteve 7132074Ssteve#include <vm/vm.h> 7232074Ssteve#include <vm/vm_kern.h> 7352949Sobrien#include <vm/vm_param.h> 7452949Sobrien#include <vm/pmap.h> 7552949Sobrien#include <vm/vm_map.h> 7632074Ssteve#include <vm/vm_object.h> 7732074Ssteve#include <vm/vm_extern.h> 7832074Ssteve 7932074Ssteve#include <compat/freebsd32/freebsd32_util.h> 806562Sphk#include <compat/freebsd32/freebsd32.h> 8132074Ssteve#include <compat/freebsd32/freebsd32_proto.h> 8232074Ssteve 836562SphkCTASSERT(sizeof(struct timeval32) == 8); 8432074SsteveCTASSERT(sizeof(struct timespec32) == 8); 8532074SsteveCTASSERT(sizeof(struct statfs32) == 256); 8632074SsteveCTASSERT(sizeof(struct rusage32) == 72); 876562Sphk 8832074Ssteveint 8932074Sstevefreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 9032074Ssteve{ 9132074Ssteve int error, status; 9237421Scharnier struct rusage32 ru32; 9332074Ssteve struct rusage ru, *rup; 9452949Sobrien 9552949Sobrien if (uap->rusage != NULL) 9652949Sobrien rup = &ru; 9752949Sobrien else 9852949Sobrien rup = NULL; 9932074Ssteve error = kern_wait(td, uap->pid, &status, uap->options, rup); 10032074Ssteve if (error) 10132074Ssteve return (error); 1026725Sphk if (uap->status != NULL) 1033995Spst error = copyout(&status, uap->status, sizeof(status)); 1046562Sphk if (uap->rusage != NULL && error == 0) { 1053995Spst TV_CP(ru, ru32, ru_utime); 1066562Sphk TV_CP(ru, ru32, ru_stime); 1076562Sphk CP(ru, ru32, ru_maxrss); 1083995Spst CP(ru, ru32, ru_ixrss); 1096562Sphk CP(ru, ru32, ru_idrss); 1106562Sphk CP(ru, ru32, ru_isrss); 1116562Sphk CP(ru, ru32, ru_minflt); 1123995Spst CP(ru, ru32, ru_majflt); 11348953Sbillf CP(ru, ru32, ru_nswap); 1149489Sphk CP(ru, ru32, ru_inblock); 1153995Spst CP(ru, ru32, ru_oublock); 11652949Sobrien CP(ru, ru32, ru_msgsnd); 11752949Sobrien CP(ru, ru32, ru_msgrcv); 11852949Sobrien CP(ru, ru32, ru_nsignals); 11952949Sobrien CP(ru, ru32, ru_nvcsw); 1203995Spst CP(ru, ru32, ru_nivcsw); 1216562Sphk error = copyout(&ru32, uap->rusage, sizeof(ru32)); 1226562Sphk } 1233995Spst return (error); 1246562Sphk} 1256562Sphk 1263995Spst#ifdef COMPAT_FREEBSD4 1276562Sphkstatic void 1286562Sphkcopy_statfs(struct statfs *in, struct statfs32 *out) 1296725Sphk{ 1306562Sphk CP(*in, *out, f_bsize); 1319489Sphk CP(*in, *out, f_iosize); 1323995Spst CP(*in, *out, f_blocks); 1336562Sphk CP(*in, *out, f_bfree); 1346562Sphk CP(*in, *out, f_bavail); 13521763Sphk CP(*in, *out, f_files); 13646226Skris CP(*in, *out, f_ffree); 1373995Spst CP(*in, *out, f_fsid); 1386562Sphk CP(*in, *out, f_owner); 1396562Sphk CP(*in, *out, f_type); 1406562Sphk CP(*in, *out, f_flags); 1413995Spst CP(*in, *out, f_flags); 1426562Sphk CP(*in, *out, f_syncwrites); 1436562Sphk CP(*in, *out, f_asyncwrites); 1443995Spst bcopy(in->f_fstypename, 1456562Sphk out->f_fstypename, MFSNAMELEN); 1466562Sphk bcopy(in->f_mntonname, 1476562Sphk out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 1486562Sphk CP(*in, *out, f_syncreads); 1499489Sphk CP(*in, *out, f_asyncreads); 1503995Spst bcopy(in->f_mntfromname, 1516562Sphk out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 1526562Sphk} 1533995Spst#endif 1546562Sphk 1556562Sphk#ifdef COMPAT_FREEBSD4 1566562Sphkint 1576562Sphkfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 1586562Sphk{ 1596562Sphk int error; 1606562Sphk caddr_t sg; 1616562Sphk struct statfs32 *sp32, stat32; 1623995Spst struct statfs *sp = NULL, stat; 1636562Sphk int maxcount, count, i; 1646562Sphk 1653995Spst sp32 = uap->buf; 1666562Sphk maxcount = uap->bufsize / sizeof(struct statfs32); 1676562Sphk 1683995Spst if (sp32) { 16932086Ssteve sg = stackgap_init(); 1706562Sphk sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); 1713995Spst uap->buf = (struct statfs32 *)sp; 1726562Sphk } 1736562Sphk error = getfsstat(td, (struct getfsstat_args *) uap); 1746562Sphk if (sp32 && !error) { 1756562Sphk count = td->td_retval[0]; 1766562Sphk for (i = 0; i < count; i++) { 1776562Sphk error = copyin(&sp[i], &stat, sizeof(stat)); 1786562Sphk if (error) 1796562Sphk return (error); 1806562Sphk copy_statfs(&stat, &stat32); 1813995Spst error = copyout(&stat32, &sp32[i], sizeof(stat32)); 1823995Spst if (error) 1833995Spst return (error); 1846562Sphk } 1856562Sphk } 1863995Spst return (error); 1876562Sphk} 18832086Ssteve#endif 18932086Ssteve 1903995Spststruct sigaltstack32 { 1916562Sphk u_int32_t ss_sp; 1926562Sphk u_int32_t ss_size; 19332074Ssteve int ss_flags; 1949489Sphk}; 1953995Spst 1966562SphkCTASSERT(sizeof(struct sigaltstack32) == 12); 19732074Ssteve 19837421Scharnierint 19937421Scharnierfreebsd32_sigaltstack(struct thread *td, 2006562Sphk struct freebsd32_sigaltstack_args *uap) 2016725Sphk{ 2029489Sphk struct sigaltstack32 s32; 2033995Spst struct sigaltstack ss, oss, *ssp; 20432074Ssteve int error; 20532074Ssteve 20632086Ssteve if (uap->ss != NULL) { 20732074Ssteve error = copyin(uap->ss, &s32, sizeof(s32)); 20832086Ssteve if (error) 20932086Ssteve return (error); 21032074Ssteve PTRIN_CP(s32, ss, ss_sp); 21132074Ssteve CP(s32, ss, ss_size); 212 CP(s32, ss, ss_flags); 213 ssp = &ss; 214 } else 215 ssp = NULL; 216 error = kern_sigaltstack(td, ssp, &oss); 217 if (error == 0 && uap->oss != NULL) { 218 PTROUT_CP(oss, s32, ss_sp); 219 CP(oss, s32, ss_size); 220 CP(oss, s32, ss_flags); 221 error = copyout(&s32, uap->oss, sizeof(s32)); 222 } 223 return (error); 224} 225 226/* 227 * Custom version of exec_copyin_args() so that we can translate 228 * the pointers. 229 */ 230static int 231freebsd32_exec_copyin_args(struct image_args *args, char *fname, 232 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 233{ 234 char *argp, *envp; 235 u_int32_t *p32, arg; 236 size_t length; 237 int error; 238 239 bzero(args, sizeof(*args)); 240 if (argv == NULL) 241 return (EFAULT); 242 243 /* 244 * Allocate temporary demand zeroed space for argument and 245 * environment strings 246 */ 247 args->buf = (char *) kmem_alloc_wait(exec_map, PATH_MAX + ARG_MAX); 248 if (args->buf == NULL) 249 return (ENOMEM); 250 args->begin_argv = args->buf; 251 args->endp = args->begin_argv; 252 args->stringspace = ARG_MAX; 253 254 args->fname = args->buf + ARG_MAX; 255 256 /* 257 * Copy the file name. 258 */ 259 error = (segflg == UIO_SYSSPACE) ? 260 copystr(fname, args->fname, PATH_MAX, &length) : 261 copyinstr(fname, args->fname, PATH_MAX, &length); 262 if (error != 0) 263 return (error); 264 265 /* 266 * extract arguments first 267 */ 268 p32 = argv; 269 for (;;) { 270 error = copyin(p32++, &arg, sizeof(arg)); 271 if (error) 272 return (error); 273 if (arg == 0) 274 break; 275 argp = PTRIN(arg); 276 error = copyinstr(argp, args->endp, args->stringspace, &length); 277 if (error) { 278 if (error == ENAMETOOLONG) 279 return (E2BIG); 280 else 281 return (error); 282 } 283 args->stringspace -= length; 284 args->endp += length; 285 args->argc++; 286 } 287 288 args->begin_envv = args->endp; 289 290 /* 291 * extract environment strings 292 */ 293 if (envv) { 294 p32 = envv; 295 for (;;) { 296 error = copyin(p32++, &arg, sizeof(arg)); 297 if (error) 298 return (error); 299 if (arg == 0) 300 break; 301 envp = PTRIN(arg); 302 error = copyinstr(envp, args->endp, args->stringspace, 303 &length); 304 if (error) { 305 if (error == ENAMETOOLONG) 306 return (E2BIG); 307 else 308 return (error); 309 } 310 args->stringspace -= length; 311 args->endp += length; 312 args->envc++; 313 } 314 } 315 316 return (0); 317} 318 319int 320freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 321{ 322 struct image_args eargs; 323 int error; 324 325 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 326 uap->argv, uap->envv); 327 if (error == 0) 328 error = kern_execve(td, &eargs, NULL); 329 exec_free_args(&eargs); 330 return (error); 331} 332 333#ifdef __ia64__ 334static int 335freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 336 int prot, int fd, off_t pos) 337{ 338 vm_map_t map; 339 vm_map_entry_t entry; 340 int rv; 341 342 map = &td->td_proc->p_vmspace->vm_map; 343 if (fd != -1) 344 prot |= VM_PROT_WRITE; 345 346 if (vm_map_lookup_entry(map, start, &entry)) { 347 if ((entry->protection & prot) != prot) { 348 rv = vm_map_protect(map, 349 trunc_page(start), 350 round_page(end), 351 entry->protection | prot, 352 FALSE); 353 if (rv != KERN_SUCCESS) 354 return (EINVAL); 355 } 356 } else { 357 vm_offset_t addr = trunc_page(start); 358 rv = vm_map_find(map, 0, 0, 359 &addr, PAGE_SIZE, FALSE, prot, 360 VM_PROT_ALL, 0); 361 if (rv != KERN_SUCCESS) 362 return (EINVAL); 363 } 364 365 if (fd != -1) { 366 struct pread_args r; 367 r.fd = fd; 368 r.buf = (void *) start; 369 r.nbyte = end - start; 370 r.offset = pos; 371 return (pread(td, &r)); 372 } else { 373 while (start < end) { 374 subyte((void *) start, 0); 375 start++; 376 } 377 return (0); 378 } 379} 380#endif 381 382int 383freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 384{ 385 struct mmap_args ap; 386 vm_offset_t addr = (vm_offset_t) uap->addr; 387 vm_size_t len = uap->len; 388 int prot = uap->prot; 389 int flags = uap->flags; 390 int fd = uap->fd; 391 off_t pos = (uap->poslo 392 | ((off_t)uap->poshi << 32)); 393#ifdef __ia64__ 394 vm_size_t pageoff; 395 int error; 396 397 /* 398 * Attempt to handle page size hassles. 399 */ 400 pageoff = (pos & PAGE_MASK); 401 if (flags & MAP_FIXED) { 402 vm_offset_t start, end; 403 start = addr; 404 end = addr + len; 405 406 if (start != trunc_page(start)) { 407 error = freebsd32_mmap_partial(td, start, 408 round_page(start), prot, 409 fd, pos); 410 if (fd != -1) 411 pos += round_page(start) - start; 412 start = round_page(start); 413 } 414 if (end != round_page(end)) { 415 vm_offset_t t = trunc_page(end); 416 error = freebsd32_mmap_partial(td, t, end, 417 prot, fd, 418 pos + t - start); 419 end = trunc_page(end); 420 } 421 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 422 /* 423 * We can't map this region at all. The specified 424 * address doesn't have the same alignment as the file 425 * position. Fake the mapping by simply reading the 426 * entire region into memory. First we need to make 427 * sure the region exists. 428 */ 429 vm_map_t map; 430 struct pread_args r; 431 int rv; 432 433 prot |= VM_PROT_WRITE; 434 map = &td->td_proc->p_vmspace->vm_map; 435 rv = vm_map_remove(map, start, end); 436 if (rv != KERN_SUCCESS) 437 return (EINVAL); 438 rv = vm_map_find(map, 0, 0, 439 &start, end - start, FALSE, 440 prot, VM_PROT_ALL, 0); 441 if (rv != KERN_SUCCESS) 442 return (EINVAL); 443 r.fd = fd; 444 r.buf = (void *) start; 445 r.nbyte = end - start; 446 r.offset = pos; 447 error = pread(td, &r); 448 if (error) 449 return (error); 450 451 td->td_retval[0] = addr; 452 return (0); 453 } 454 if (end == start) { 455 /* 456 * After dealing with the ragged ends, there 457 * might be none left. 458 */ 459 td->td_retval[0] = addr; 460 return (0); 461 } 462 addr = start; 463 len = end - start; 464 } 465#endif 466 467 ap.addr = (void *) addr; 468 ap.len = len; 469 ap.prot = prot; 470 ap.flags = flags; 471 ap.fd = fd; 472 ap.pos = pos; 473 474 return (mmap(td, &ap)); 475} 476 477struct itimerval32 { 478 struct timeval32 it_interval; 479 struct timeval32 it_value; 480}; 481 482CTASSERT(sizeof(struct itimerval32) == 16); 483 484int 485freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 486{ 487 struct itimerval itv, oitv, *itvp; 488 struct itimerval32 i32; 489 int error; 490 491 if (uap->itv != NULL) { 492 error = copyin(uap->itv, &i32, sizeof(i32)); 493 if (error) 494 return (error); 495 TV_CP(i32, itv, it_interval); 496 TV_CP(i32, itv, it_value); 497 itvp = &itv; 498 } else 499 itvp = NULL; 500 error = kern_setitimer(td, uap->which, itvp, &oitv); 501 if (error || uap->oitv == NULL) 502 return (error); 503 TV_CP(oitv, i32, it_interval); 504 TV_CP(oitv, i32, it_value); 505 return (copyout(&i32, uap->oitv, sizeof(i32))); 506} 507 508int 509freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 510{ 511 struct itimerval itv; 512 struct itimerval32 i32; 513 int error; 514 515 error = kern_getitimer(td, uap->which, &itv); 516 if (error || uap->itv == NULL) 517 return (error); 518 TV_CP(itv, i32, it_interval); 519 TV_CP(itv, i32, it_value); 520 return (copyout(&i32, uap->itv, sizeof(i32))); 521} 522 523int 524freebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 525{ 526 struct timeval32 tv32; 527 struct timeval tv, *tvp; 528 int error; 529 530 if (uap->tv != NULL) { 531 error = copyin(uap->tv, &tv32, sizeof(tv32)); 532 if (error) 533 return (error); 534 CP(tv32, tv, tv_sec); 535 CP(tv32, tv, tv_usec); 536 tvp = &tv; 537 } else 538 tvp = NULL; 539 /* 540 * XXX big-endian needs to convert the fd_sets too. 541 * XXX Do pointers need PTRIN()? 542 */ 543 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); 544} 545 546struct kevent32 { 547 u_int32_t ident; /* identifier for this event */ 548 short filter; /* filter for event */ 549 u_short flags; 550 u_int fflags; 551 int32_t data; 552 u_int32_t udata; /* opaque user data identifier */ 553}; 554 555CTASSERT(sizeof(struct kevent32) == 20); 556static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 557static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 558 559/* 560 * Copy 'count' items into the destination list pointed to by uap->eventlist. 561 */ 562static int 563freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 564{ 565 struct freebsd32_kevent_args *uap; 566 struct kevent32 ks32[KQ_NEVENTS]; 567 int i, error = 0; 568 569 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 570 uap = (struct freebsd32_kevent_args *)arg; 571 572 for (i = 0; i < count; i++) { 573 CP(kevp[i], ks32[i], ident); 574 CP(kevp[i], ks32[i], filter); 575 CP(kevp[i], ks32[i], flags); 576 CP(kevp[i], ks32[i], fflags); 577 CP(kevp[i], ks32[i], data); 578 PTROUT_CP(kevp[i], ks32[i], udata); 579 } 580 error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 581 if (error == 0) 582 uap->eventlist += count; 583 return (error); 584} 585 586/* 587 * Copy 'count' items from the list pointed to by uap->changelist. 588 */ 589static int 590freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 591{ 592 struct freebsd32_kevent_args *uap; 593 struct kevent32 ks32[KQ_NEVENTS]; 594 int i, error = 0; 595 596 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 597 uap = (struct freebsd32_kevent_args *)arg; 598 599 error = copyin(uap->changelist, ks32, count * sizeof *ks32); 600 if (error) 601 goto done; 602 uap->changelist += count; 603 604 for (i = 0; i < count; i++) { 605 CP(ks32[i], kevp[i], ident); 606 CP(ks32[i], kevp[i], filter); 607 CP(ks32[i], kevp[i], flags); 608 CP(ks32[i], kevp[i], fflags); 609 CP(ks32[i], kevp[i], data); 610 PTRIN_CP(ks32[i], kevp[i], udata); 611 } 612done: 613 return (error); 614} 615 616int 617freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 618{ 619 struct timespec32 ts32; 620 struct timespec ts, *tsp; 621 struct kevent_copyops k_ops = { uap, 622 freebsd32_kevent_copyout, 623 freebsd32_kevent_copyin}; 624 int error; 625 626 627 if (uap->timeout) { 628 error = copyin(uap->timeout, &ts32, sizeof(ts32)); 629 if (error) 630 return (error); 631 CP(ts32, ts, tv_sec); 632 CP(ts32, ts, tv_nsec); 633 tsp = &ts; 634 } else 635 tsp = NULL; 636 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 637 &k_ops, tsp); 638 return (error); 639} 640 641int 642freebsd32_gettimeofday(struct thread *td, 643 struct freebsd32_gettimeofday_args *uap) 644{ 645 struct timeval atv; 646 struct timeval32 atv32; 647 struct timezone rtz; 648 int error = 0; 649 650 if (uap->tp) { 651 microtime(&atv); 652 CP(atv, atv32, tv_sec); 653 CP(atv, atv32, tv_usec); 654 error = copyout(&atv32, uap->tp, sizeof (atv32)); 655 } 656 if (error == 0 && uap->tzp != NULL) { 657 rtz.tz_minuteswest = tz_minuteswest; 658 rtz.tz_dsttime = tz_dsttime; 659 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 660 } 661 return (error); 662} 663 664int 665freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 666{ 667 struct rusage32 s32; 668 struct rusage s; 669 int error; 670 671 error = kern_getrusage(td, uap->who, &s); 672 if (error) 673 return (error); 674 if (uap->rusage != NULL) { 675 TV_CP(s, s32, ru_utime); 676 TV_CP(s, s32, ru_stime); 677 CP(s, s32, ru_maxrss); 678 CP(s, s32, ru_ixrss); 679 CP(s, s32, ru_idrss); 680 CP(s, s32, ru_isrss); 681 CP(s, s32, ru_minflt); 682 CP(s, s32, ru_majflt); 683 CP(s, s32, ru_nswap); 684 CP(s, s32, ru_inblock); 685 CP(s, s32, ru_oublock); 686 CP(s, s32, ru_msgsnd); 687 CP(s, s32, ru_msgrcv); 688 CP(s, s32, ru_nsignals); 689 CP(s, s32, ru_nvcsw); 690 CP(s, s32, ru_nivcsw); 691 error = copyout(&s32, uap->rusage, sizeof(s32)); 692 } 693 return (error); 694} 695 696struct iovec32 { 697 u_int32_t iov_base; 698 int iov_len; 699}; 700 701CTASSERT(sizeof(struct iovec32) == 8); 702 703static int 704freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 705{ 706 struct iovec32 iov32; 707 struct iovec *iov; 708 struct uio *uio; 709 u_int iovlen; 710 int error, i; 711 712 *uiop = NULL; 713 if (iovcnt > UIO_MAXIOV) 714 return (EINVAL); 715 iovlen = iovcnt * sizeof(struct iovec); 716 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 717 iov = (struct iovec *)(uio + 1); 718 for (i = 0; i < iovcnt; i++) { 719 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 720 if (error) { 721 free(uio, M_IOV); 722 return (error); 723 } 724 iov[i].iov_base = PTRIN(iov32.iov_base); 725 iov[i].iov_len = iov32.iov_len; 726 } 727 uio->uio_iov = iov; 728 uio->uio_iovcnt = iovcnt; 729 uio->uio_segflg = UIO_USERSPACE; 730 uio->uio_offset = -1; 731 uio->uio_resid = 0; 732 for (i = 0; i < iovcnt; i++) { 733 if (iov->iov_len > INT_MAX - uio->uio_resid) { 734 free(uio, M_IOV); 735 return (EINVAL); 736 } 737 uio->uio_resid += iov->iov_len; 738 iov++; 739 } 740 *uiop = uio; 741 return (0); 742} 743 744int 745freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 746{ 747 struct uio *auio; 748 int error; 749 750 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 751 if (error) 752 return (error); 753 error = kern_readv(td, uap->fd, auio); 754 free(auio, M_IOV); 755 return (error); 756} 757 758int 759freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 760{ 761 struct uio *auio; 762 int error; 763 764 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 765 if (error) 766 return (error); 767 error = kern_writev(td, uap->fd, auio); 768 free(auio, M_IOV); 769 return (error); 770} 771 772int 773freebsd32_settimeofday(struct thread *td, 774 struct freebsd32_settimeofday_args *uap) 775{ 776 struct timeval32 tv32; 777 struct timeval tv, *tvp; 778 struct timezone tz, *tzp; 779 int error; 780 781 if (uap->tv) { 782 error = copyin(uap->tv, &tv32, sizeof(tv32)); 783 if (error) 784 return (error); 785 CP(tv32, tv, tv_sec); 786 CP(tv32, tv, tv_usec); 787 tvp = &tv; 788 } else 789 tvp = NULL; 790 if (uap->tzp) { 791 error = copyin(uap->tzp, &tz, sizeof(tz)); 792 if (error) 793 return (error); 794 tzp = &tz; 795 } else 796 tzp = NULL; 797 return (kern_settimeofday(td, tvp, tzp)); 798} 799 800int 801freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 802{ 803 struct timeval32 s32[2]; 804 struct timeval s[2], *sp; 805 int error; 806 807 if (uap->tptr != NULL) { 808 error = copyin(uap->tptr, s32, sizeof(s32)); 809 if (error) 810 return (error); 811 CP(s32[0], s[0], tv_sec); 812 CP(s32[0], s[0], tv_usec); 813 CP(s32[1], s[1], tv_sec); 814 CP(s32[1], s[1], tv_usec); 815 sp = s; 816 } else 817 sp = NULL; 818 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 819} 820 821int 822freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 823{ 824 struct timeval32 tv32; 825 struct timeval delta, olddelta, *deltap; 826 int error; 827 828 if (uap->delta) { 829 error = copyin(uap->delta, &tv32, sizeof(tv32)); 830 if (error) 831 return (error); 832 CP(tv32, delta, tv_sec); 833 CP(tv32, delta, tv_usec); 834 deltap = δ 835 } else 836 deltap = NULL; 837 error = kern_adjtime(td, deltap, &olddelta); 838 if (uap->olddelta && error == 0) { 839 CP(olddelta, tv32, tv_sec); 840 CP(olddelta, tv32, tv_usec); 841 error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 842 } 843 return (error); 844} 845 846#ifdef COMPAT_FREEBSD4 847int 848freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 849{ 850 struct statfs32 s32; 851 struct statfs s; 852 int error; 853 854 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 855 if (error) 856 return (error); 857 copy_statfs(&s, &s32); 858 return (copyout(&s32, uap->buf, sizeof(s32))); 859} 860#endif 861 862#ifdef COMPAT_FREEBSD4 863int 864freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 865{ 866 struct statfs32 s32; 867 struct statfs s; 868 int error; 869 870 error = kern_fstatfs(td, uap->fd, &s); 871 if (error) 872 return (error); 873 copy_statfs(&s, &s32); 874 return (copyout(&s32, uap->buf, sizeof(s32))); 875} 876#endif 877 878#ifdef COMPAT_FREEBSD4 879int 880freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 881{ 882 struct statfs32 s32; 883 struct statfs s; 884 fhandle_t fh; 885 int error; 886 887 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 888 return (error); 889 error = kern_fhstatfs(td, fh, &s); 890 if (error) 891 return (error); 892 copy_statfs(&s, &s32); 893 return (copyout(&s32, uap->buf, sizeof(s32))); 894} 895#endif 896 897int 898freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 899{ 900 /* 901 * Vector through to semsys if it is loaded. 902 */ 903 return sysent[169].sy_call(td, uap); 904} 905 906int 907freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 908{ 909 /* 910 * Vector through to msgsys if it is loaded. 911 */ 912 return sysent[170].sy_call(td, uap); 913} 914 915int 916freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 917{ 918 /* 919 * Vector through to shmsys if it is loaded. 920 */ 921 return sysent[171].sy_call(td, uap); 922} 923 924int 925freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 926{ 927 struct pread_args ap; 928 929 ap.fd = uap->fd; 930 ap.buf = uap->buf; 931 ap.nbyte = uap->nbyte; 932 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 933 return (pread(td, &ap)); 934} 935 936int 937freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 938{ 939 struct pwrite_args ap; 940 941 ap.fd = uap->fd; 942 ap.buf = uap->buf; 943 ap.nbyte = uap->nbyte; 944 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 945 return (pwrite(td, &ap)); 946} 947 948int 949freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 950{ 951 int error; 952 struct lseek_args ap; 953 off_t pos; 954 955 ap.fd = uap->fd; 956 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 957 ap.whence = uap->whence; 958 error = lseek(td, &ap); 959 /* Expand the quad return into two parts for eax and edx */ 960 pos = *(off_t *)(td->td_retval); 961 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 962 td->td_retval[1] = pos >> 32; /* %edx */ 963 return error; 964} 965 966int 967freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 968{ 969 struct truncate_args ap; 970 971 ap.path = uap->path; 972 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 973 return (truncate(td, &ap)); 974} 975 976int 977freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 978{ 979 struct ftruncate_args ap; 980 981 ap.fd = uap->fd; 982 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 983 return (ftruncate(td, &ap)); 984} 985 986#ifdef COMPAT_FREEBSD4 987int 988freebsd4_freebsd32_sendfile(struct thread *td, 989 struct freebsd4_freebsd32_sendfile_args *uap) 990{ 991 struct freebsd4_sendfile_args ap; 992 993 ap.fd = uap->fd; 994 ap.s = uap->s; 995 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 996 ap.nbytes = uap->nbytes; /* XXX check */ 997 ap.hdtr = uap->hdtr; /* XXX check */ 998 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 999 ap.flags = uap->flags; 1000 return (freebsd4_sendfile(td, &ap)); 1001} 1002#endif 1003 1004int 1005freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1006{ 1007 struct sendfile_args ap; 1008 1009 ap.fd = uap->fd; 1010 ap.s = uap->s; 1011 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1012 ap.nbytes = uap->nbytes; /* XXX check */ 1013 ap.hdtr = uap->hdtr; /* XXX check */ 1014 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1015 ap.flags = uap->flags; 1016 return (sendfile(td, &ap)); 1017} 1018 1019struct stat32 { 1020 dev_t st_dev; 1021 ino_t st_ino; 1022 mode_t st_mode; 1023 nlink_t st_nlink; 1024 uid_t st_uid; 1025 gid_t st_gid; 1026 dev_t st_rdev; 1027 struct timespec32 st_atimespec; 1028 struct timespec32 st_mtimespec; 1029 struct timespec32 st_ctimespec; 1030 off_t st_size; 1031 int64_t st_blocks; 1032 u_int32_t st_blksize; 1033 u_int32_t st_flags; 1034 u_int32_t st_gen; 1035 struct timespec32 st_birthtimespec; 1036 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1037 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1038}; 1039 1040 1041CTASSERT(sizeof(struct stat32) == 96); 1042 1043static void 1044copy_stat( struct stat *in, struct stat32 *out) 1045{ 1046 CP(*in, *out, st_dev); 1047 CP(*in, *out, st_ino); 1048 CP(*in, *out, st_mode); 1049 CP(*in, *out, st_nlink); 1050 CP(*in, *out, st_uid); 1051 CP(*in, *out, st_gid); 1052 CP(*in, *out, st_rdev); 1053 TS_CP(*in, *out, st_atimespec); 1054 TS_CP(*in, *out, st_mtimespec); 1055 TS_CP(*in, *out, st_ctimespec); 1056 CP(*in, *out, st_size); 1057 CP(*in, *out, st_blocks); 1058 CP(*in, *out, st_blksize); 1059 CP(*in, *out, st_flags); 1060 CP(*in, *out, st_gen); 1061} 1062 1063int 1064freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1065{ 1066 struct stat sb; 1067 struct stat32 sb32; 1068 int error; 1069 1070 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1071 if (error) 1072 return (error); 1073 copy_stat(&sb, &sb32); 1074 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1075 return (error); 1076} 1077 1078int 1079freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1080{ 1081 struct stat ub; 1082 struct stat32 ub32; 1083 int error; 1084 1085 error = kern_fstat(td, uap->fd, &ub); 1086 if (error) 1087 return (error); 1088 copy_stat(&ub, &ub32); 1089 error = copyout(&ub32, uap->ub, sizeof(ub32)); 1090 return (error); 1091} 1092 1093int 1094freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1095{ 1096 struct stat sb; 1097 struct stat32 sb32; 1098 int error; 1099 1100 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1101 if (error) 1102 return (error); 1103 copy_stat(&sb, &sb32); 1104 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1105 return (error); 1106} 1107 1108/* 1109 * MPSAFE 1110 */ 1111int 1112freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1113{ 1114 int error, name[CTL_MAXNAME]; 1115 size_t j, oldlen; 1116 1117 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1118 return (EINVAL); 1119 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 1120 if (error) 1121 return (error); 1122 mtx_lock(&Giant); 1123 if (uap->oldlenp) 1124 oldlen = fuword32(uap->oldlenp); 1125 else 1126 oldlen = 0; 1127 error = userland_sysctl(td, name, uap->namelen, 1128 uap->old, &oldlen, 1, 1129 uap->new, uap->newlen, &j, SCTL_MASK32); 1130 if (error && error != ENOMEM) 1131 goto done2; 1132 if (uap->oldlenp) 1133 suword32(uap->oldlenp, j); 1134done2: 1135 mtx_unlock(&Giant); 1136 return (error); 1137} 1138 1139struct sigaction32 { 1140 u_int32_t sa_u; 1141 int sa_flags; 1142 sigset_t sa_mask; 1143}; 1144 1145CTASSERT(sizeof(struct sigaction32) == 24); 1146 1147int 1148freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1149{ 1150 struct sigaction32 s32; 1151 struct sigaction sa, osa, *sap; 1152 int error; 1153 1154 if (uap->act) { 1155 error = copyin(uap->act, &s32, sizeof(s32)); 1156 if (error) 1157 return (error); 1158 sa.sa_handler = PTRIN(s32.sa_u); 1159 CP(s32, sa, sa_flags); 1160 CP(s32, sa, sa_mask); 1161 sap = &sa; 1162 } else 1163 sap = NULL; 1164 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1165 if (error == 0 && uap->oact != NULL) { 1166 s32.sa_u = PTROUT(osa.sa_handler); 1167 CP(osa, s32, sa_flags); 1168 CP(osa, s32, sa_mask); 1169 error = copyout(&s32, uap->oact, sizeof(s32)); 1170 } 1171 return (error); 1172} 1173 1174#ifdef COMPAT_FREEBSD4 1175int 1176freebsd4_freebsd32_sigaction(struct thread *td, 1177 struct freebsd4_freebsd32_sigaction_args *uap) 1178{ 1179 struct sigaction32 s32; 1180 struct sigaction sa, osa, *sap; 1181 int error; 1182 1183 if (uap->act) { 1184 error = copyin(uap->act, &s32, sizeof(s32)); 1185 if (error) 1186 return (error); 1187 sa.sa_handler = PTRIN(s32.sa_u); 1188 CP(s32, sa, sa_flags); 1189 CP(s32, sa, sa_mask); 1190 sap = &sa; 1191 } else 1192 sap = NULL; 1193 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1194 if (error == 0 && uap->oact != NULL) { 1195 s32.sa_u = PTROUT(osa.sa_handler); 1196 CP(osa, s32, sa_flags); 1197 CP(osa, s32, sa_mask); 1198 error = copyout(&s32, uap->oact, sizeof(s32)); 1199 } 1200 return (error); 1201} 1202#endif 1203 1204int 1205freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 1206{ 1207 struct timespec32 rmt32, rqt32; 1208 struct timespec rmt, rqt; 1209 int error; 1210 1211 error = copyin(uap->rqtp, &rqt32, sizeof(rqt)); 1212 if (error) 1213 return (error); 1214 1215 CP(rqt32, rqt, tv_sec); 1216 CP(rqt32, rqt, tv_nsec); 1217 1218 if (uap->rmtp && 1219 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 1220 return (EFAULT); 1221 error = kern_nanosleep(td, &rqt, &rmt); 1222 if (error && uap->rmtp) { 1223 int error2; 1224 1225 CP(rmt, rmt32, tv_sec); 1226 CP(rmt, rmt32, tv_nsec); 1227 1228 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt)); 1229 if (error2) 1230 error = error2; 1231 } 1232 return (error); 1233} 1234 1235#if 0 1236 1237int 1238freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 1239{ 1240 int error; 1241 caddr_t sg; 1242 struct yyy32 *p32, s32; 1243 struct yyy *p = NULL, s; 1244 1245 p32 = uap->zzz; 1246 if (p32) { 1247 sg = stackgap_init(); 1248 p = stackgap_alloc(&sg, sizeof(struct yyy)); 1249 uap->zzz = (struct yyy32 *)p; 1250 error = copyin(p32, &s32, sizeof(s32)); 1251 if (error) 1252 return (error); 1253 /* translate in */ 1254 error = copyout(&s, p, sizeof(s)); 1255 if (error) 1256 return (error); 1257 } 1258 error = xxx(td, (struct xxx_args *) uap); 1259 if (error) 1260 return (error); 1261 if (p32) { 1262 error = copyin(p, &s, sizeof(s)); 1263 if (error) 1264 return (error); 1265 /* translate out */ 1266 error = copyout(&s32, p32, sizeof(s32)); 1267 } 1268 return (error); 1269} 1270 1271#endif 1272