freebsd32_misc.c revision 157285
1184251Smarcel/*- 2184251Smarcel * Copyright (c) 2002 Doug Rabson 3255207Sbrooks * All rights reserved. 4184251Smarcel * 5184251Smarcel * Redistribution and use in source and binary forms, with or without 6255207Sbrooks * modification, are permitted provided that the following conditions 7255207Sbrooks * are met: 8255207Sbrooks * 1. Redistributions of source code must retain the above copyright 9255207Sbrooks * notice, this list of conditions and the following disclaimer. 10255207Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 11184251Smarcel * notice, this list of conditions and the following disclaimer in the 12184251Smarcel * documentation and/or other materials provided with the distribution. 13184251Smarcel * 14184251Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15184251Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16184251Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184251Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18184251Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184251Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184251Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184251Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184251Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184251Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184251Smarcel * SUCH DAMAGE. 25184251Smarcel */ 26184251Smarcel 27184251Smarcel#include <sys/cdefs.h> 28184251Smarcel__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 157285 2006-03-30 07:42:32Z ps $"); 29184251Smarcel 30184251Smarcel#include "opt_compat.h" 31184251Smarcel 32184251Smarcel#include <sys/param.h> 33184251Smarcel#include <sys/systm.h> 34184251Smarcel#include <sys/bus.h> 35184251Smarcel#include <sys/exec.h> 36184251Smarcel#include <sys/fcntl.h> 37184251Smarcel#include <sys/filedesc.h> 38184251Smarcel#include <sys/namei.h> 39188156Ssam#include <sys/imgact.h> 40188156Ssam#include <sys/kernel.h> 41184251Smarcel#include <sys/lock.h> 42184251Smarcel#include <sys/malloc.h> 43184251Smarcel#include <sys/file.h> /* Must come after sys/malloc.h */ 44184251Smarcel#include <sys/mbuf.h> 45233553Sjchandra#include <sys/mman.h> 46250115Sbrooks#include <sys/module.h> 47184251Smarcel#include <sys/mount.h> 48184251Smarcel#include <sys/mutex.h> 49184251Smarcel#include <sys/namei.h> 50184251Smarcel#include <sys/param.h> 51184251Smarcel#include <sys/proc.h> 52184251Smarcel#include <sys/reboot.h> 53184251Smarcel#include <sys/resource.h> 54184251Smarcel#include <sys/resourcevar.h> 55184251Smarcel#include <sys/selinfo.h> 56184251Smarcel#include <sys/eventvar.h> /* Must come after sys/selinfo.h */ 57184251Smarcel#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 58255207Sbrooks#include <sys/signal.h> 59255207Sbrooks#include <sys/signalvar.h> 60184251Smarcel#include <sys/socket.h> 61184251Smarcel#include <sys/socketvar.h> 62184251Smarcel#include <sys/stat.h> 63184251Smarcel#include <sys/syscall.h> 64189606Ssam#include <sys/syscallsubr.h> 65184251Smarcel#include <sys/sysctl.h> 66184251Smarcel#include <sys/sysent.h> 67233553Sjchandra#include <sys/sysproto.h> 68184251Smarcel#include <sys/systm.h> 69184251Smarcel#include <sys/unistd.h> 70184251Smarcel#include <sys/vnode.h> 71184251Smarcel#include <sys/wait.h> 72184251Smarcel#include <sys/ipc.h> 73184251Smarcel#include <sys/shm.h> 74184251Smarcel 75184251Smarcel#include <vm/vm.h> 76184251Smarcel#include <vm/vm_kern.h> 77184251Smarcel#include <vm/vm_param.h> 78184251Smarcel#include <vm/pmap.h> 79184251Smarcel#include <vm/vm_map.h> 80184251Smarcel#include <vm/vm_object.h> 81184251Smarcel#include <vm/vm_extern.h> 82184251Smarcel 83184251Smarcel#include <machine/cpu.h> 84184251Smarcel 85184251Smarcel#include <compat/freebsd32/freebsd32_util.h> 86184251Smarcel#include <compat/freebsd32/freebsd32.h> 87184251Smarcel#include <compat/freebsd32/freebsd32_proto.h> 88184251Smarcel 89233553SjchandraCTASSERT(sizeof(struct timeval32) == 8); 90233553SjchandraCTASSERT(sizeof(struct timespec32) == 8); 91233553SjchandraCTASSERT(sizeof(struct statfs32) == 256); 92233553SjchandraCTASSERT(sizeof(struct rusage32) == 72); 93233553Sjchandra 94233553Sjchandraint 95233553Sjchandrafreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap) 96233553Sjchandra{ 97233553Sjchandra int error, status; 98233553Sjchandra struct rusage32 ru32; 99233553Sjchandra struct rusage ru, *rup; 100233553Sjchandra 101233553Sjchandra if (uap->rusage != NULL) 102233553Sjchandra rup = &ru; 103233553Sjchandra else 104233553Sjchandra rup = NULL; 105233553Sjchandra error = kern_wait(td, uap->pid, &status, uap->options, rup); 106233553Sjchandra if (error) 107233553Sjchandra return (error); 108233553Sjchandra if (uap->status != NULL) 109233553Sjchandra error = copyout(&status, uap->status, sizeof(status)); 110233553Sjchandra if (uap->rusage != NULL && error == 0) { 111233553Sjchandra TV_CP(ru, ru32, ru_utime); 112233553Sjchandra TV_CP(ru, ru32, ru_stime); 113233553Sjchandra CP(ru, ru32, ru_maxrss); 114233553Sjchandra CP(ru, ru32, ru_ixrss); 115184251Smarcel CP(ru, ru32, ru_idrss); 116184251Smarcel CP(ru, ru32, ru_isrss); 117184251Smarcel CP(ru, ru32, ru_minflt); 118184251Smarcel CP(ru, ru32, ru_majflt); 119184251Smarcel CP(ru, ru32, ru_nswap); 120184251Smarcel CP(ru, ru32, ru_inblock); 121184251Smarcel CP(ru, ru32, ru_oublock); 122184251Smarcel CP(ru, ru32, ru_msgsnd); 123184251Smarcel CP(ru, ru32, ru_msgrcv); 124184251Smarcel CP(ru, ru32, ru_nsignals); 125233553Sjchandra CP(ru, ru32, ru_nvcsw); 126184251Smarcel CP(ru, ru32, ru_nivcsw); 127184251Smarcel error = copyout(&ru32, uap->rusage, sizeof(ru32)); 128233553Sjchandra } 129184251Smarcel return (error); 130184251Smarcel} 131184251Smarcel 132184251Smarcel#ifdef COMPAT_FREEBSD4 133184251Smarcelstatic void 134184251Smarcelcopy_statfs(struct statfs *in, struct statfs32 *out) 135184251Smarcel{ 136184251Smarcel 137184251Smarcel bzero(out, sizeof(*out)); 138184251Smarcel CP(*in, *out, f_bsize); 139184251Smarcel CP(*in, *out, f_iosize); 140184251Smarcel CP(*in, *out, f_blocks); 141184251Smarcel CP(*in, *out, f_bfree); 142184251Smarcel CP(*in, *out, f_bavail); 143184251Smarcel CP(*in, *out, f_files); 144184251Smarcel CP(*in, *out, f_ffree); 145184251Smarcel CP(*in, *out, f_fsid); 146184251Smarcel CP(*in, *out, f_owner); 147184251Smarcel CP(*in, *out, f_type); 148184251Smarcel CP(*in, *out, f_flags); 149184251Smarcel CP(*in, *out, f_flags); 150184251Smarcel CP(*in, *out, f_syncwrites); 151184251Smarcel CP(*in, *out, f_asyncwrites); 152184251Smarcel strlcpy(out->f_fstypename, 153184251Smarcel in->f_fstypename, MFSNAMELEN); 154184251Smarcel strlcpy(out->f_mntonname, 155184251Smarcel in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 156184251Smarcel CP(*in, *out, f_syncreads); 157184251Smarcel CP(*in, *out, f_asyncreads); 158184251Smarcel strlcpy(out->f_mntfromname, 159184251Smarcel in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN)); 160184251Smarcel} 161184251Smarcel#endif 162184251Smarcel 163184251Smarcel#ifdef COMPAT_FREEBSD4 164184251Smarcelint 165184251Smarcelfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap) 166184251Smarcel{ 167184251Smarcel struct statfs *buf, *sp; 168184251Smarcel struct statfs32 stat32; 169184251Smarcel size_t count, size; 170184251Smarcel int error; 171184251Smarcel 172184251Smarcel count = uap->bufsize / sizeof(struct statfs32); 173184251Smarcel size = count * sizeof(struct statfs); 174184251Smarcel error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 175184251Smarcel if (size > 0) { 176184251Smarcel count = td->td_retval[0]; 177184251Smarcel sp = buf; 178184251Smarcel while (count > 0 && error == 0) { 179184251Smarcel copy_statfs(sp, &stat32); 180184251Smarcel error = copyout(&stat32, uap->buf, sizeof(stat32)); 181184251Smarcel sp++; 182184251Smarcel uap->buf++; 183184251Smarcel count--; 184184251Smarcel } 185184251Smarcel free(buf, M_TEMP); 186184251Smarcel } 187184251Smarcel return (error); 188184251Smarcel} 189184251Smarcel#endif 190184251Smarcel 191188087Ssamstruct sigaltstack32 { 192188087Ssam u_int32_t ss_sp; 193188087Ssam u_int32_t ss_size; 194188087Ssam int ss_flags; 195188087Ssam}; 196188087Ssam 197188087SsamCTASSERT(sizeof(struct sigaltstack32) == 12); 198188087Ssam 199188087Ssamint 200188087Ssamfreebsd32_sigaltstack(struct thread *td, 201184251Smarcel struct freebsd32_sigaltstack_args *uap) 202184251Smarcel{ 203184251Smarcel struct sigaltstack32 s32; 204184251Smarcel struct sigaltstack ss, oss, *ssp; 205184251Smarcel int error; 206184251Smarcel 207184251Smarcel if (uap->ss != NULL) { 208184251Smarcel error = copyin(uap->ss, &s32, sizeof(s32)); 209184251Smarcel if (error) 210184251Smarcel return (error); 211184251Smarcel PTRIN_CP(s32, ss, ss_sp); 212184251Smarcel CP(s32, ss, ss_size); 213184251Smarcel CP(s32, ss, ss_flags); 214184251Smarcel ssp = &ss; 215184251Smarcel } else 216184251Smarcel ssp = NULL; 217184251Smarcel error = kern_sigaltstack(td, ssp, &oss); 218184251Smarcel if (error == 0 && uap->oss != NULL) { 219184251Smarcel PTROUT_CP(oss, s32, ss_sp); 220184251Smarcel CP(oss, s32, ss_size); 221184251Smarcel CP(oss, s32, ss_flags); 222184251Smarcel error = copyout(&s32, uap->oss, sizeof(s32)); 223184251Smarcel } 224184251Smarcel return (error); 225184251Smarcel} 226184251Smarcel 227184251Smarcel/* 228184251Smarcel * Custom version of exec_copyin_args() so that we can translate 229184251Smarcel * the pointers. 230184251Smarcel */ 231184251Smarcelstatic int 232184251Smarcelfreebsd32_exec_copyin_args(struct image_args *args, char *fname, 233184251Smarcel enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv) 234184251Smarcel{ 235184251Smarcel char *argp, *envp; 236184251Smarcel u_int32_t *p32, arg; 237184251Smarcel size_t length; 238184251Smarcel int error; 239184251Smarcel 240184251Smarcel bzero(args, sizeof(*args)); 241184251Smarcel if (argv == NULL) 242184251Smarcel return (EFAULT); 243184251Smarcel 244184251Smarcel /* 245184251Smarcel * Allocate temporary demand zeroed space for argument and 246184251Smarcel * environment strings 247184251Smarcel */ 248184251Smarcel args->buf = (char *) kmem_alloc_wait(exec_map, 249184251Smarcel PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 250184251Smarcel if (args->buf == NULL) 251184251Smarcel return (ENOMEM); 252184251Smarcel args->begin_argv = args->buf; 253184251Smarcel args->endp = args->begin_argv; 254184251Smarcel args->stringspace = ARG_MAX; 255184251Smarcel 256184251Smarcel args->fname = args->buf + ARG_MAX; 257184251Smarcel 258184251Smarcel /* 259184251Smarcel * Copy the file name. 260184251Smarcel */ 261184251Smarcel error = (segflg == UIO_SYSSPACE) ? 262184251Smarcel copystr(fname, args->fname, PATH_MAX, &length) : 263184251Smarcel copyinstr(fname, args->fname, PATH_MAX, &length); 264184251Smarcel if (error != 0) 265184251Smarcel goto err_exit; 266184251Smarcel 267184251Smarcel /* 268184251Smarcel * extract arguments first 269184251Smarcel */ 270184251Smarcel p32 = argv; 271184251Smarcel for (;;) { 272184251Smarcel error = copyin(p32++, &arg, sizeof(arg)); 273255207Sbrooks if (error) 274250115Sbrooks goto err_exit; 275250115Sbrooks if (arg == 0) 276250115Sbrooks break; 277250115Sbrooks argp = PTRIN(arg); 278184251Smarcel error = copyinstr(argp, args->endp, args->stringspace, &length); 279184251Smarcel if (error) { 280184251Smarcel if (error == ENAMETOOLONG) 281184251Smarcel error = E2BIG; 282184251Smarcel goto err_exit; 283184251Smarcel } 284256753Sbrooks args->stringspace -= length; 285184251Smarcel args->endp += length; 286256753Sbrooks args->argc++; 287256753Sbrooks } 288256753Sbrooks 289184251Smarcel args->begin_envv = args->endp; 290184251Smarcel 291184251Smarcel /* 292184251Smarcel * extract environment strings 293184251Smarcel */ 294184251Smarcel if (envv) { 295255207Sbrooks p32 = envv; 296255207Sbrooks for (;;) { 297255207Sbrooks error = copyin(p32++, &arg, sizeof(arg)); 298255207Sbrooks if (error) 299255207Sbrooks goto err_exit; 300255207Sbrooks if (arg == 0) 301255207Sbrooks break; 302255207Sbrooks envp = PTRIN(arg); 303255207Sbrooks error = copyinstr(envp, args->endp, args->stringspace, 304255207Sbrooks &length); 305255207Sbrooks if (error) { 306255207Sbrooks if (error == ENAMETOOLONG) 307255207Sbrooks error = E2BIG; 308255207Sbrooks goto err_exit; 309255207Sbrooks } 310255207Sbrooks args->stringspace -= length; 311255207Sbrooks args->endp += length; 312255207Sbrooks args->envc++; 313255207Sbrooks } 314255207Sbrooks } 315255207Sbrooks 316255207Sbrooks return (0); 317255207Sbrooks 318255207Sbrookserr_exit: 319184251Smarcel kmem_free_wakeup(exec_map, (vm_offset_t)args->buf, 320255207Sbrooks PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); 321255207Sbrooks args->buf = NULL; 322255207Sbrooks return (error); 323255207Sbrooks} 324255207Sbrooks 325255207Sbrooksint 326255207Sbrooksfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap) 327255207Sbrooks{ 328255207Sbrooks struct image_args eargs; 329255207Sbrooks int error; 330255207Sbrooks 331255207Sbrooks error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE, 332255207Sbrooks uap->argv, uap->envv); 333255207Sbrooks if (error == 0) 334255207Sbrooks error = kern_execve(td, &eargs, NULL); 335255207Sbrooks return (error); 336255207Sbrooks} 337255207Sbrooks 338255207Sbrooks#ifdef __ia64__ 339255207Sbrooksstatic int 340255207Sbrooksfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 341255207Sbrooks int prot, int fd, off_t pos) 342255207Sbrooks{ 343255207Sbrooks vm_map_t map; 344255207Sbrooks vm_map_entry_t entry; 345255207Sbrooks int rv; 346255207Sbrooks 347255207Sbrooks map = &td->td_proc->p_vmspace->vm_map; 348255207Sbrooks if (fd != -1) 349255207Sbrooks prot |= VM_PROT_WRITE; 350255207Sbrooks 351255207Sbrooks if (vm_map_lookup_entry(map, start, &entry)) { 352255207Sbrooks if ((entry->protection & prot) != prot) { 353255207Sbrooks rv = vm_map_protect(map, 354255207Sbrooks trunc_page(start), 355255207Sbrooks round_page(end), 356255207Sbrooks entry->protection | prot, 357255207Sbrooks FALSE); 358255207Sbrooks if (rv != KERN_SUCCESS) 359255207Sbrooks return (EINVAL); 360255207Sbrooks } 361255207Sbrooks } else { 362255207Sbrooks vm_offset_t addr = trunc_page(start); 363255207Sbrooks rv = vm_map_find(map, 0, 0, 364255207Sbrooks &addr, PAGE_SIZE, FALSE, prot, 365255207Sbrooks VM_PROT_ALL, 0); 366255207Sbrooks if (rv != KERN_SUCCESS) 367255207Sbrooks return (EINVAL); 368255207Sbrooks } 369184251Smarcel 370184251Smarcel if (fd != -1) { 371184251Smarcel struct pread_args r; 372184251Smarcel r.fd = fd; 373184251Smarcel r.buf = (void *) start; 374184251Smarcel r.nbyte = end - start; 375184251Smarcel r.offset = pos; 376184251Smarcel return (pread(td, &r)); 377184251Smarcel } else { 378184251Smarcel while (start < end) { 379184251Smarcel subyte((void *) start, 0); 380184251Smarcel start++; 381184251Smarcel } 382184251Smarcel return (0); 383184251Smarcel } 384184251Smarcel} 385184251Smarcel#endif 386184251Smarcel 387184251Smarcelint 388184251Smarcelfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap) 389184251Smarcel{ 390184251Smarcel struct mmap_args ap; 391184251Smarcel vm_offset_t addr = (vm_offset_t) uap->addr; 392184251Smarcel vm_size_t len = uap->len; 393184251Smarcel int prot = uap->prot; 394184251Smarcel int flags = uap->flags; 395184251Smarcel int fd = uap->fd; 396184251Smarcel off_t pos = (uap->poslo 397184251Smarcel | ((off_t)uap->poshi << 32)); 398184251Smarcel#ifdef __ia64__ 399184251Smarcel vm_size_t pageoff; 400184251Smarcel int error; 401255207Sbrooks 402255207Sbrooks /* 403250115Sbrooks * Attempt to handle page size hassles. 404250115Sbrooks */ 405250115Sbrooks pageoff = (pos & PAGE_MASK); 406250115Sbrooks if (flags & MAP_FIXED) { 407250115Sbrooks vm_offset_t start, end; 408250115Sbrooks start = addr; 409250115Sbrooks end = addr + len; 410250115Sbrooks 411250115Sbrooks mtx_lock(&Giant); 412250115Sbrooks if (start != trunc_page(start)) { 413250115Sbrooks error = freebsd32_mmap_partial(td, start, 414250115Sbrooks round_page(start), prot, 415250115Sbrooks fd, pos); 416250115Sbrooks if (fd != -1) 417193936Simp pos += round_page(start) - start; 418189606Ssam start = round_page(start); 419189606Ssam } 420184251Smarcel if (end != round_page(end)) { 421184251Smarcel vm_offset_t t = trunc_page(end); 422184251Smarcel error = freebsd32_mmap_partial(td, t, end, 423255207Sbrooks prot, fd, 424255207Sbrooks pos + t - start); 425255207Sbrooks end = trunc_page(end); 426255207Sbrooks } 427255207Sbrooks if (end > start && fd != -1 && (pos & PAGE_MASK)) { 428255207Sbrooks /* 429255207Sbrooks * We can't map this region at all. The specified 430255207Sbrooks * address doesn't have the same alignment as the file 431255207Sbrooks * position. Fake the mapping by simply reading the 432255207Sbrooks * entire region into memory. First we need to make 433255207Sbrooks * sure the region exists. 434255207Sbrooks */ 435255207Sbrooks vm_map_t map; 436255207Sbrooks struct pread_args r; 437255207Sbrooks int rv; 438255207Sbrooks 439255207Sbrooks prot |= VM_PROT_WRITE; 440255207Sbrooks map = &td->td_proc->p_vmspace->vm_map; 441255207Sbrooks rv = vm_map_remove(map, start, end); 442255207Sbrooks if (rv != KERN_SUCCESS) { 443255207Sbrooks mtx_unlock(&Giant); 444255207Sbrooks return (EINVAL); 445255207Sbrooks } 446255207Sbrooks rv = vm_map_find(map, 0, 0, 447255207Sbrooks &start, end - start, FALSE, 448255207Sbrooks prot, VM_PROT_ALL, 0); 449255207Sbrooks mtx_unlock(&Giant); 450255207Sbrooks if (rv != KERN_SUCCESS) 451255207Sbrooks return (EINVAL); 452255207Sbrooks r.fd = fd; 453255207Sbrooks r.buf = (void *) start; 454255207Sbrooks r.nbyte = end - start; 455255207Sbrooks r.offset = pos; 456255207Sbrooks error = pread(td, &r); 457255207Sbrooks if (error) 458255207Sbrooks return (error); 459255207Sbrooks 460255207Sbrooks td->td_retval[0] = addr; 461255207Sbrooks return (0); 462184251Smarcel } 463184251Smarcel mtx_unlock(&Giant); 464184251Smarcel if (end == start) { 465184251Smarcel /* 466184251Smarcel * After dealing with the ragged ends, there 467184251Smarcel * might be none left. 468184251Smarcel */ 469184251Smarcel td->td_retval[0] = addr; 470184251Smarcel return (0); 471184251Smarcel } 472184251Smarcel addr = start; 473184251Smarcel len = end - start; 474184251Smarcel } 475184251Smarcel#endif 476255207Sbrooks 477255207Sbrooks ap.addr = (void *) addr; 478184251Smarcel ap.len = len; 479255207Sbrooks ap.prot = prot; 480188156Ssam ap.flags = flags; 481255207Sbrooks ap.fd = fd; 482184251Smarcel ap.pos = pos; 483184251Smarcel 484184251Smarcel return (mmap(td, &ap)); 485255207Sbrooks} 486255207Sbrooks 487255207Sbrooksstruct itimerval32 { 488255207Sbrooks struct timeval32 it_interval; 489255207Sbrooks struct timeval32 it_value; 490255207Sbrooks}; 491255207Sbrooks 492184251SmarcelCTASSERT(sizeof(struct itimerval32) == 16); 493184251Smarcel 494184251Smarcelint 495184251Smarcelfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap) 496188156Ssam{ 497188156Ssam struct itimerval itv, oitv, *itvp; 498184251Smarcel struct itimerval32 i32; 499188156Ssam int error; 500188156Ssam 501188156Ssam if (uap->itv != NULL) { 502188156Ssam error = copyin(uap->itv, &i32, sizeof(i32)); 503188156Ssam if (error) 504184251Smarcel return (error); 505188156Ssam TV_CP(i32, itv, it_interval); 506184251Smarcel TV_CP(i32, itv, it_value); 507188156Ssam itvp = &itv; 508184251Smarcel } else 509188156Ssam itvp = NULL; 510188156Ssam error = kern_setitimer(td, uap->which, itvp, &oitv); 511184251Smarcel if (error || uap->oitv == NULL) 512184251Smarcel return (error); 513184251Smarcel TV_CP(oitv, i32, it_interval); 514184251Smarcel TV_CP(oitv, i32, it_value); 515188156Ssam return (copyout(&i32, uap->oitv, sizeof(i32))); 516188156Ssam} 517184251Smarcel 518184251Smarcelint 519184251Smarcelfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap) 520255207Sbrooks{ 521255207Sbrooks struct itimerval itv; 522255207Sbrooks struct itimerval32 i32; 523255207Sbrooks int error; 524255207Sbrooks 525255207Sbrooks error = kern_getitimer(td, uap->which, &itv); 526255207Sbrooks if (error || uap->itv == NULL) 527255207Sbrooks return (error); 528255207Sbrooks TV_CP(itv, i32, it_interval); 529255207Sbrooks TV_CP(itv, i32, it_value); 530255207Sbrooks return (copyout(&i32, uap->itv, sizeof(i32))); 531255207Sbrooks} 532255207Sbrooks 533255207Sbrooksint 534255207Sbrooksfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap) 535255207Sbrooks{ 536255207Sbrooks struct timeval32 tv32; 537255207Sbrooks struct timeval tv, *tvp; 538255207Sbrooks int error; 539184251Smarcel 540184251Smarcel if (uap->tv != NULL) { 541184251Smarcel error = copyin(uap->tv, &tv32, sizeof(tv32)); 542184251Smarcel if (error) 543188156Ssam return (error); 544184251Smarcel CP(tv32, tv, tv_sec); 545184251Smarcel CP(tv32, tv, tv_usec); 546184251Smarcel tvp = &tv; 547184251Smarcel } else 548184251Smarcel tvp = NULL; 549184251Smarcel /* 550184251Smarcel * XXX big-endian needs to convert the fd_sets too. 551184251Smarcel * XXX Do pointers need PTRIN()? 552184251Smarcel */ 553184251Smarcel return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); 554255207Sbrooks} 555184251Smarcel 556255207Sbrooksstruct kevent32 { 557255207Sbrooks u_int32_t ident; /* identifier for this event */ 558255207Sbrooks short filter; /* filter for event */ 559255207Sbrooks u_short flags; 560184251Smarcel u_int fflags; 561251118Sbrooks int32_t data; 562251118Sbrooks u_int32_t udata; /* opaque user data identifier */ 563251118Sbrooks}; 564251118Sbrooks 565251118SbrooksCTASSERT(sizeof(struct kevent32) == 20); 566251118Sbrooksstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count); 567251118Sbrooksstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count); 568251118Sbrooks 569251118Sbrooks/* 570251118Sbrooks * Copy 'count' items into the destination list pointed to by uap->eventlist. 571255207Sbrooks */ 572255207Sbrooksstatic int 573255207Sbrooksfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count) 574255207Sbrooks{ 575255207Sbrooks struct freebsd32_kevent_args *uap; 576255207Sbrooks struct kevent32 ks32[KQ_NEVENTS]; 577255207Sbrooks int i, error = 0; 578255207Sbrooks 579255207Sbrooks KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 580255207Sbrooks uap = (struct freebsd32_kevent_args *)arg; 581255207Sbrooks 582255207Sbrooks for (i = 0; i < count; i++) { 583255207Sbrooks CP(kevp[i], ks32[i], ident); 584255207Sbrooks CP(kevp[i], ks32[i], filter); 585255207Sbrooks CP(kevp[i], ks32[i], flags); 586255207Sbrooks CP(kevp[i], ks32[i], fflags); 587255207Sbrooks CP(kevp[i], ks32[i], data); 588255207Sbrooks PTROUT_CP(kevp[i], ks32[i], udata); 589255207Sbrooks } 590255207Sbrooks error = copyout(ks32, uap->eventlist, count * sizeof *ks32); 591255207Sbrooks if (error == 0) 592255207Sbrooks uap->eventlist += count; 593255207Sbrooks return (error); 594255207Sbrooks} 595255207Sbrooks 596255207Sbrooks/* 597255207Sbrooks * Copy 'count' items from the list pointed to by uap->changelist. 598255207Sbrooks */ 599255207Sbrooksstatic int 600255207Sbrooksfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count) 601255207Sbrooks{ 602255207Sbrooks struct freebsd32_kevent_args *uap; 603255207Sbrooks struct kevent32 ks32[KQ_NEVENTS]; 604255207Sbrooks int i, error = 0; 605255207Sbrooks 606255207Sbrooks KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count)); 607255207Sbrooks uap = (struct freebsd32_kevent_args *)arg; 608255207Sbrooks 609255207Sbrooks error = copyin(uap->changelist, ks32, count * sizeof *ks32); 610255207Sbrooks if (error) 611255207Sbrooks goto done; 612255207Sbrooks uap->changelist += count; 613255207Sbrooks 614255207Sbrooks for (i = 0; i < count; i++) { 615255207Sbrooks CP(ks32[i], kevp[i], ident); 616255207Sbrooks CP(ks32[i], kevp[i], filter); 617255207Sbrooks CP(ks32[i], kevp[i], flags); 618255207Sbrooks CP(ks32[i], kevp[i], fflags); 619255207Sbrooks CP(ks32[i], kevp[i], data); 620255207Sbrooks PTRIN_CP(ks32[i], kevp[i], udata); 621255207Sbrooks } 622255207Sbrooksdone: 623255207Sbrooks return (error); 624255207Sbrooks} 625255207Sbrooks 626255207Sbrooksint 627255207Sbrooksfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap) 628255207Sbrooks{ 629255207Sbrooks struct timespec32 ts32; 630255207Sbrooks struct timespec ts, *tsp; 631255207Sbrooks struct kevent_copyops k_ops = { uap, 632255207Sbrooks freebsd32_kevent_copyout, 633255207Sbrooks freebsd32_kevent_copyin}; 634255207Sbrooks int error; 635255207Sbrooks 636255207Sbrooks 637255207Sbrooks if (uap->timeout) { 638255207Sbrooks error = copyin(uap->timeout, &ts32, sizeof(ts32)); 639255207Sbrooks if (error) 640255207Sbrooks return (error); 641255207Sbrooks CP(ts32, ts, tv_sec); 642255207Sbrooks CP(ts32, ts, tv_nsec); 643255207Sbrooks tsp = &ts; 644255207Sbrooks } else 645255207Sbrooks tsp = NULL; 646255207Sbrooks error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, 647255207Sbrooks &k_ops, tsp); 648255207Sbrooks return (error); 649255207Sbrooks} 650255207Sbrooks 651255207Sbrooksint 652255207Sbrooksfreebsd32_gettimeofday(struct thread *td, 653255207Sbrooks struct freebsd32_gettimeofday_args *uap) 654255207Sbrooks{ 655255207Sbrooks struct timeval atv; 656255207Sbrooks struct timeval32 atv32; 657255207Sbrooks struct timezone rtz; 658255207Sbrooks int error = 0; 659255207Sbrooks 660255207Sbrooks if (uap->tp) { 661255207Sbrooks microtime(&atv); 662255207Sbrooks CP(atv, atv32, tv_sec); 663255207Sbrooks CP(atv, atv32, tv_usec); 664255207Sbrooks error = copyout(&atv32, uap->tp, sizeof (atv32)); 665255207Sbrooks } 666184251Smarcel if (error == 0 && uap->tzp != NULL) { 667184251Smarcel rtz.tz_minuteswest = tz_minuteswest; 668255207Sbrooks rtz.tz_dsttime = tz_dsttime; 669184251Smarcel error = copyout(&rtz, uap->tzp, sizeof (rtz)); 670184251Smarcel } 671255207Sbrooks return (error); 672255207Sbrooks} 673255207Sbrooks 674255207Sbrooksint 675255207Sbrooksfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap) 676255207Sbrooks{ 677255207Sbrooks struct rusage32 s32; 678255207Sbrooks struct rusage s; 679255207Sbrooks int error; 680255207Sbrooks 681255207Sbrooks error = kern_getrusage(td, uap->who, &s); 682255207Sbrooks if (error) 683255207Sbrooks return (error); 684255207Sbrooks if (uap->rusage != NULL) { 685255207Sbrooks TV_CP(s, s32, ru_utime); 686255207Sbrooks TV_CP(s, s32, ru_stime); 687255207Sbrooks CP(s, s32, ru_maxrss); 688255207Sbrooks CP(s, s32, ru_ixrss); 689184251Smarcel CP(s, s32, ru_idrss); 690184251Smarcel CP(s, s32, ru_isrss); 691184251Smarcel CP(s, s32, ru_minflt); 692184251Smarcel CP(s, s32, ru_majflt); 693184251Smarcel CP(s, s32, ru_nswap); 694184251Smarcel CP(s, s32, ru_inblock); 695184251Smarcel CP(s, s32, ru_oublock); 696255207Sbrooks CP(s, s32, ru_msgsnd); 697184251Smarcel CP(s, s32, ru_msgrcv); 698184251Smarcel CP(s, s32, ru_nsignals); 699184251Smarcel CP(s, s32, ru_nvcsw); 700184251Smarcel CP(s, s32, ru_nivcsw); 701184251Smarcel error = copyout(&s32, uap->rusage, sizeof(s32)); 702184251Smarcel } 703184251Smarcel return (error); 704184251Smarcel} 705184251Smarcel 706184251Smarcelstruct iovec32 { 707184251Smarcel u_int32_t iov_base; 708184251Smarcel int iov_len; 709184251Smarcel}; 710255207Sbrooks 711184251SmarcelCTASSERT(sizeof(struct iovec32) == 8); 712184251Smarcel 713184251Smarcelstatic int 714255207Sbrooksfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop) 715184251Smarcel{ 716184251Smarcel struct iovec32 iov32; 717184251Smarcel struct iovec *iov; 718255207Sbrooks struct uio *uio; 719184251Smarcel u_int iovlen; 720184251Smarcel int error, i; 721255207Sbrooks 722184251Smarcel *uiop = NULL; 723184251Smarcel if (iovcnt > UIO_MAXIOV) 724255207Sbrooks return (EINVAL); 725255207Sbrooks iovlen = iovcnt * sizeof(struct iovec); 726184251Smarcel uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 727184251Smarcel iov = (struct iovec *)(uio + 1); 728184251Smarcel for (i = 0; i < iovcnt; i++) { 729184251Smarcel error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); 730184251Smarcel if (error) { 731184251Smarcel free(uio, M_IOV); 732184251Smarcel return (error); 733184251Smarcel } 734251118Sbrooks iov[i].iov_base = PTRIN(iov32.iov_base); 735251118Sbrooks iov[i].iov_len = iov32.iov_len; 736251118Sbrooks } 737251118Sbrooks uio->uio_iov = iov; 738251118Sbrooks uio->uio_iovcnt = iovcnt; 739251118Sbrooks uio->uio_segflg = UIO_USERSPACE; 740251118Sbrooks uio->uio_offset = -1; 741251118Sbrooks uio->uio_resid = 0; 742251118Sbrooks for (i = 0; i < iovcnt; i++) { 743251118Sbrooks if (iov->iov_len > INT_MAX - uio->uio_resid) { 744184251Smarcel free(uio, M_IOV); 745184251Smarcel return (EINVAL); 746188156Ssam } 747188156Ssam uio->uio_resid += iov->iov_len; 748188156Ssam iov++; 749188156Ssam } 750188156Ssam *uiop = uio; 751188156Ssam return (0); 752188156Ssam} 753188156Ssam 754188156Ssamint 755188267Ssamfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) 756188332Ssam{ 757188267Ssam struct uio *auio; 758188156Ssam int error; 759188156Ssam 760188156Ssam error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 761188156Ssam if (error) 762188156Ssam return (error); 763188156Ssam error = kern_readv(td, uap->fd, auio); 764188156Ssam free(auio, M_IOV); 765188156Ssam return (error); 766188156Ssam} 767188268Ssam 768188156Ssamint 769188156Ssamfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) 770188156Ssam{ 771188156Ssam struct uio *auio; 772188156Ssam int error; 773188268Ssam 774188156Ssam error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 775188156Ssam if (error) 776188156Ssam return (error); 777188156Ssam error = kern_writev(td, uap->fd, auio); 778188156Ssam free(auio, M_IOV); 779188156Ssam return (error); 780188156Ssam} 781188156Ssam 782188156Ssamint 783188156Ssamfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap) 784188156Ssam{ 785188156Ssam struct uio *auio; 786188156Ssam int error; 787188156Ssam 788188156Ssam error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 789188156Ssam if (error) 790188156Ssam return (error); 791188156Ssam error = kern_preadv(td, uap->fd, auio, uap->offset); 792188156Ssam free(auio, M_IOV); 793188156Ssam return (error); 794188156Ssam} 795188156Ssam 796188156Ssamint 797188156Ssamfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) 798188156Ssam{ 799188156Ssam struct uio *auio; 800188156Ssam int error; 801188156Ssam 802188156Ssam error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); 803188156Ssam if (error) 804188156Ssam return (error); 805188156Ssam error = kern_pwritev(td, uap->fd, auio, uap->offset); 806188156Ssam free(auio, M_IOV); 807188156Ssam return (error); 808188156Ssam} 809188156Ssam 810188156Ssamstatic int 811188156Ssamfreebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp, 812188156Ssam int error) 813188156Ssam{ 814188156Ssam struct iovec32 iov32; 815188267Ssam struct iovec *iov; 816188156Ssam u_int iovlen; 817188156Ssam int i; 818188156Ssam 819188156Ssam *iovp = NULL; 820188267Ssam if (iovcnt > UIO_MAXIOV) 821188156Ssam return (error); 822188156Ssam iovlen = iovcnt * sizeof(struct iovec); 823255207Sbrooks iov = malloc(iovlen, M_IOV, M_WAITOK); 824188267Ssam for (i = 0; i < iovcnt; i++) { 825188156Ssam error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32)); 826188156Ssam if (error) { 827188156Ssam free(iov, M_IOV); 828188156Ssam return (error); 829188156Ssam } 830188267Ssam iov[i].iov_base = PTRIN(iov32.iov_base); 831188156Ssam iov[i].iov_len = iov32.iov_len; 832188156Ssam } 833255207Sbrooks *iovp = iov; 834188156Ssam return (0); 835188156Ssam} 836188156Ssam 837255207Sbrooksstatic int 838255207Sbrooksfreebsd32_copyoutiov(struct iovec *iov, u_int iovcnt, struct iovec32 *iovp, 839188156Ssam int error) 840188156Ssam{ 841188156Ssam struct iovec32 iov32; 842188156Ssam int i; 843188156Ssam 844188267Ssam if (iovcnt > UIO_MAXIOV) 845188267Ssam return (error); 846188267Ssam for (i = 0; i < iovcnt; i++) { 847188267Ssam iov32.iov_base = PTROUT(iov[i].iov_base); 848188267Ssam iov32.iov_len = iov[i].iov_len; 849188156Ssam error = copyout(&iov32, &iovp[i], sizeof(iov32)); 850188156Ssam if (error) 851188156Ssam return (error); 852188156Ssam } 853188156Ssam return (0); 854188156Ssam} 855188156Ssam 856188156Ssam 857188156Ssamstruct msghdr32 { 858188156Ssam u_int32_t msg_name; 859188156Ssam socklen_t msg_namelen; 860188156Ssam u_int32_t msg_iov; 861188156Ssam int msg_iovlen; 862188156Ssam u_int32_t msg_control; 863188156Ssam socklen_t msg_controllen; 864188156Ssam int msg_flags; 865188156Ssam}; 866188156SsamCTASSERT(sizeof(struct msghdr32) == 28); 867188156Ssam 868188156Ssamstatic int 869188156Ssamfreebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg) 870188156Ssam{ 871188156Ssam struct msghdr32 m32; 872188156Ssam int error; 873188156Ssam 874188156Ssam error = copyin(msg32, &m32, sizeof(m32)); 875188156Ssam if (error) 876188156Ssam return (error); 877188268Ssam msg->msg_name = PTRIN(m32.msg_name); 878255207Sbrooks msg->msg_namelen = m32.msg_namelen; 879188156Ssam msg->msg_iov = PTRIN(m32.msg_iov); 880188156Ssam msg->msg_iovlen = m32.msg_iovlen; 881188156Ssam msg->msg_control = PTRIN(m32.msg_control); 882188156Ssam msg->msg_controllen = m32.msg_controllen; 883188156Ssam msg->msg_flags = m32.msg_flags; 884188156Ssam return (0); 885188156Ssam} 886188156Ssam 887188156Ssamstatic int 888255207Sbrooksfreebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32) 889188156Ssam{ 890188156Ssam struct msghdr32 m32; 891188156Ssam int error; 892255207Sbrooks 893255207Sbrooks m32.msg_name = PTROUT(msg->msg_name); 894188156Ssam m32.msg_namelen = msg->msg_namelen; 895188268Ssam m32.msg_iov = PTROUT(msg->msg_iov); 896188156Ssam m32.msg_iovlen = msg->msg_iovlen; 897188156Ssam m32.msg_control = PTROUT(msg->msg_control); 898188156Ssam m32.msg_controllen = msg->msg_controllen; 899188268Ssam m32.msg_flags = msg->msg_flags; 900188156Ssam error = copyout(&m32, msg32, sizeof(m32)); 901188156Ssam return (error); 902188156Ssam} 903 904#define FREEBSD32_ALIGNBYTES (sizeof(int) - 1) 905#define FREEBSD32_ALIGN(p) \ 906 (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES) 907#define FREEBSD32_CMSG_SPACE(l) \ 908 (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l)) 909 910#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \ 911 FREEBSD32_ALIGN(sizeof(struct cmsghdr))) 912static int 913freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control) 914{ 915 struct cmsghdr *cm; 916 void *data; 917 socklen_t clen, datalen; 918 int error; 919 caddr_t ctlbuf; 920 int len, maxlen, copylen; 921 struct mbuf *m; 922 error = 0; 923 924 len = msg->msg_controllen; 925 maxlen = msg->msg_controllen; 926 msg->msg_controllen = 0; 927 928 m = control; 929 ctlbuf = msg->msg_control; 930 931 while (m && len > 0) { 932 cm = mtod(m, struct cmsghdr *); 933 clen = m->m_len; 934 935 while (cm != NULL) { 936 937 if (sizeof(struct cmsghdr) > clen || 938 cm->cmsg_len > clen) { 939 error = EINVAL; 940 break; 941 } 942 943 data = CMSG_DATA(cm); 944 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 945 946 /* Adjust message length */ 947 cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + 948 datalen; 949 950 951 /* Copy cmsghdr */ 952 copylen = sizeof(struct cmsghdr); 953 if (len < copylen) { 954 msg->msg_flags |= MSG_CTRUNC; 955 copylen = len; 956 } 957 958 error = copyout(cm,ctlbuf,copylen); 959 if (error) 960 goto exit; 961 962 ctlbuf += FREEBSD32_ALIGN(copylen); 963 len -= FREEBSD32_ALIGN(copylen); 964 965 if (len <= 0) 966 break; 967 968 /* Copy data */ 969 copylen = datalen; 970 if (len < copylen) { 971 msg->msg_flags |= MSG_CTRUNC; 972 copylen = len; 973 } 974 975 error = copyout(data,ctlbuf,copylen); 976 if (error) 977 goto exit; 978 979 ctlbuf += FREEBSD32_ALIGN(copylen); 980 len -= FREEBSD32_ALIGN(copylen); 981 982 if (CMSG_SPACE(datalen) < clen) { 983 clen -= CMSG_SPACE(datalen); 984 cm = (struct cmsghdr *) 985 ((caddr_t)cm + CMSG_SPACE(datalen)); 986 } else { 987 clen = 0; 988 cm = NULL; 989 } 990 } 991 m = m->m_next; 992 } 993 994 msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control; 995 996exit: 997 return (error); 998 999} 1000 1001int 1002freebsd32_recvmsg(td, uap) 1003 struct thread *td; 1004 struct freebsd32_recvmsg_args /* { 1005 int s; 1006 struct msghdr32 *msg; 1007 int flags; 1008 } */ *uap; 1009{ 1010 struct msghdr msg; 1011 struct msghdr32 m32; 1012 struct iovec *uiov, *iov; 1013 struct mbuf *control = NULL; 1014 struct mbuf **controlp; 1015 1016 int error; 1017 error = copyin(uap->msg, &m32, sizeof(m32)); 1018 if (error) 1019 return (error); 1020 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1021 if (error) 1022 return (error); 1023 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 1024 m32.msg_iovlen, &iov, EMSGSIZE); 1025 if (error) 1026 return (error); 1027 msg.msg_flags = uap->flags; 1028 uiov = msg.msg_iov; 1029 msg.msg_iov = iov; 1030 1031 controlp = (msg.msg_control != NULL) ? &control : NULL; 1032 error = kern_recvit(td, uap->s, &msg, NULL, UIO_USERSPACE, controlp); 1033 if (error == 0) { 1034 msg.msg_iov = uiov; 1035 1036 if (control != NULL) 1037 error = freebsd32_copy_msg_out(&msg, control); 1038 1039 if (error == 0) 1040 error = freebsd32_copyoutmsghdr(&msg, uap->msg); 1041 1042 if (error == 0) 1043 error = freebsd32_copyoutiov(iov, m32.msg_iovlen, 1044 (struct iovec32 *)(uintptr_t)m32.msg_iov, EMSGSIZE); 1045 } 1046 free(iov, M_IOV); 1047 1048 if (control != NULL) 1049 m_freem(control); 1050 1051 return (error); 1052} 1053 1054 1055static int 1056freebsd32_convert_msg_in(struct mbuf **controlp) 1057{ 1058 struct mbuf *control = *controlp; 1059 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 1060 void *data; 1061 socklen_t clen = control->m_len, datalen; 1062 int error; 1063 1064 error = 0; 1065 *controlp = NULL; 1066 1067 while (cm != NULL) { 1068 if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) { 1069 error = EINVAL; 1070 break; 1071 } 1072 1073 data = FREEBSD32_CMSG_DATA(cm); 1074 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1075 1076 *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type, 1077 cm->cmsg_level); 1078 controlp = &(*controlp)->m_next; 1079 1080 if (FREEBSD32_CMSG_SPACE(datalen) < clen) { 1081 clen -= FREEBSD32_CMSG_SPACE(datalen); 1082 cm = (struct cmsghdr *) 1083 ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen)); 1084 } else { 1085 clen = 0; 1086 cm = NULL; 1087 } 1088 } 1089 1090 m_freem(control); 1091 return (error); 1092} 1093 1094 1095int 1096freebsd32_sendmsg(struct thread *td, 1097 struct freebsd32_sendmsg_args *uap) 1098{ 1099 struct msghdr msg; 1100 struct msghdr32 m32; 1101 struct iovec *iov; 1102 struct mbuf *control = NULL; 1103 struct sockaddr *to = NULL; 1104 int error; 1105 1106 error = copyin(uap->msg, &m32, sizeof(m32)); 1107 if (error) 1108 return (error); 1109 error = freebsd32_copyinmsghdr(uap->msg, &msg); 1110 if (error) 1111 return (error); 1112 error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, 1113 m32.msg_iovlen, &iov, EMSGSIZE); 1114 if (error) 1115 return (error); 1116 msg.msg_iov = iov; 1117 if (msg.msg_name != NULL) { 1118 error = getsockaddr(&to, msg.msg_name, msg.msg_namelen); 1119 if (error) { 1120 to = NULL; 1121 goto out; 1122 } 1123 msg.msg_name = to; 1124 } 1125 1126 if (msg.msg_control) { 1127 if (msg.msg_controllen < sizeof(struct cmsghdr)) { 1128 error = EINVAL; 1129 goto out; 1130 } 1131 1132 error = sockargs(&control, msg.msg_control, 1133 msg.msg_controllen, MT_CONTROL); 1134 if (error) 1135 goto out; 1136 1137 error = freebsd32_convert_msg_in(&control); 1138 if (error) 1139 goto out; 1140 } 1141 1142 error = kern_sendit(td, uap->s, &msg, uap->flags, control, 1143 UIO_USERSPACE); 1144 1145out: 1146 free(iov, M_IOV); 1147 if (to) 1148 free(to, M_SONAME); 1149 return (error); 1150} 1151 1152int 1153freebsd32_recvfrom(struct thread *td, 1154 struct freebsd32_recvfrom_args *uap) 1155{ 1156 struct msghdr msg; 1157 struct iovec aiov; 1158 int error; 1159 1160 if (uap->fromlenaddr) { 1161 error = copyin((void *)(uintptr_t)uap->fromlenaddr, 1162 &msg.msg_namelen, sizeof(msg.msg_namelen)); 1163 if (error) 1164 return (error); 1165 } else { 1166 msg.msg_namelen = 0; 1167 } 1168 1169 msg.msg_name = (void *)(uintptr_t)uap->from; 1170 msg.msg_iov = &aiov; 1171 msg.msg_iovlen = 1; 1172 aiov.iov_base = (void *)(uintptr_t)uap->buf; 1173 aiov.iov_len = uap->len; 1174 msg.msg_control = 0; 1175 msg.msg_flags = uap->flags; 1176 error = kern_recvit(td, uap->s, &msg, 1177 (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE, NULL); 1178 return (error); 1179} 1180 1181int 1182freebsd32_settimeofday(struct thread *td, 1183 struct freebsd32_settimeofday_args *uap) 1184{ 1185 struct timeval32 tv32; 1186 struct timeval tv, *tvp; 1187 struct timezone tz, *tzp; 1188 int error; 1189 1190 if (uap->tv) { 1191 error = copyin(uap->tv, &tv32, sizeof(tv32)); 1192 if (error) 1193 return (error); 1194 CP(tv32, tv, tv_sec); 1195 CP(tv32, tv, tv_usec); 1196 tvp = &tv; 1197 } else 1198 tvp = NULL; 1199 if (uap->tzp) { 1200 error = copyin(uap->tzp, &tz, sizeof(tz)); 1201 if (error) 1202 return (error); 1203 tzp = &tz; 1204 } else 1205 tzp = NULL; 1206 return (kern_settimeofday(td, tvp, tzp)); 1207} 1208 1209int 1210freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap) 1211{ 1212 struct timeval32 s32[2]; 1213 struct timeval s[2], *sp; 1214 int error; 1215 1216 if (uap->tptr != NULL) { 1217 error = copyin(uap->tptr, s32, sizeof(s32)); 1218 if (error) 1219 return (error); 1220 CP(s32[0], s[0], tv_sec); 1221 CP(s32[0], s[0], tv_usec); 1222 CP(s32[1], s[1], tv_sec); 1223 CP(s32[1], s[1], tv_usec); 1224 sp = s; 1225 } else 1226 sp = NULL; 1227 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1228} 1229 1230int 1231freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap) 1232{ 1233 struct timeval32 s32[2]; 1234 struct timeval s[2], *sp; 1235 int error; 1236 1237 if (uap->tptr != NULL) { 1238 error = copyin(uap->tptr, s32, sizeof(s32)); 1239 if (error) 1240 return (error); 1241 CP(s32[0], s[0], tv_sec); 1242 CP(s32[0], s[0], tv_usec); 1243 CP(s32[1], s[1], tv_sec); 1244 CP(s32[1], s[1], tv_usec); 1245 sp = s; 1246 } else 1247 sp = NULL; 1248 return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE)); 1249} 1250 1251int 1252freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap) 1253{ 1254 struct timeval32 s32[2]; 1255 struct timeval s[2], *sp; 1256 int error; 1257 1258 if (uap->tptr != NULL) { 1259 error = copyin(uap->tptr, s32, sizeof(s32)); 1260 if (error) 1261 return (error); 1262 CP(s32[0], s[0], tv_sec); 1263 CP(s32[0], s[0], tv_usec); 1264 CP(s32[1], s[1], tv_sec); 1265 CP(s32[1], s[1], tv_usec); 1266 sp = s; 1267 } else 1268 sp = NULL; 1269 return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE)); 1270} 1271 1272 1273int 1274freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) 1275{ 1276 struct timeval32 tv32; 1277 struct timeval delta, olddelta, *deltap; 1278 int error; 1279 1280 if (uap->delta) { 1281 error = copyin(uap->delta, &tv32, sizeof(tv32)); 1282 if (error) 1283 return (error); 1284 CP(tv32, delta, tv_sec); 1285 CP(tv32, delta, tv_usec); 1286 deltap = δ 1287 } else 1288 deltap = NULL; 1289 error = kern_adjtime(td, deltap, &olddelta); 1290 if (uap->olddelta && error == 0) { 1291 CP(olddelta, tv32, tv_sec); 1292 CP(olddelta, tv32, tv_usec); 1293 error = copyout(&tv32, uap->olddelta, sizeof(tv32)); 1294 } 1295 return (error); 1296} 1297 1298#ifdef COMPAT_FREEBSD4 1299int 1300freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap) 1301{ 1302 struct statfs32 s32; 1303 struct statfs s; 1304 int error; 1305 1306 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s); 1307 if (error) 1308 return (error); 1309 copy_statfs(&s, &s32); 1310 return (copyout(&s32, uap->buf, sizeof(s32))); 1311} 1312#endif 1313 1314#ifdef COMPAT_FREEBSD4 1315int 1316freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap) 1317{ 1318 struct statfs32 s32; 1319 struct statfs s; 1320 int error; 1321 1322 error = kern_fstatfs(td, uap->fd, &s); 1323 if (error) 1324 return (error); 1325 copy_statfs(&s, &s32); 1326 return (copyout(&s32, uap->buf, sizeof(s32))); 1327} 1328#endif 1329 1330#ifdef COMPAT_FREEBSD4 1331int 1332freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap) 1333{ 1334 struct statfs32 s32; 1335 struct statfs s; 1336 fhandle_t fh; 1337 int error; 1338 1339 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 1340 return (error); 1341 error = kern_fhstatfs(td, fh, &s); 1342 if (error) 1343 return (error); 1344 copy_statfs(&s, &s32); 1345 return (copyout(&s32, uap->buf, sizeof(s32))); 1346} 1347#endif 1348 1349int 1350freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) 1351{ 1352 /* 1353 * Vector through to semsys if it is loaded. 1354 */ 1355 return sysent[SYS_semsys].sy_call(td, uap); 1356} 1357 1358int 1359freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) 1360{ 1361 /* 1362 * Vector through to msgsys if it is loaded. 1363 */ 1364 return sysent[SYS_msgsys].sy_call(td, uap); 1365} 1366 1367int 1368freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) 1369{ 1370 1371 switch (uap->which) { 1372 case 0: { /* shmat */ 1373 struct shmat_args ap; 1374 1375 ap.shmid = uap->a2; 1376 ap.shmaddr = PTRIN(uap->a3); 1377 ap.shmflg = uap->a4; 1378 return (sysent[SYS_shmat].sy_call(td, &ap)); 1379 } 1380 case 2: { /* shmdt */ 1381 struct shmdt_args ap; 1382 1383 ap.shmaddr = PTRIN(uap->a2); 1384 return (sysent[SYS_shmdt].sy_call(td, &ap)); 1385 } 1386 case 3: { /* shmget */ 1387 struct shmget_args ap; 1388 1389 ap.key = uap->a2; 1390 ap.size = uap->a3; 1391 ap.shmflg = uap->a4; 1392 return (sysent[SYS_shmget].sy_call(td, &ap)); 1393 } 1394 case 4: { /* shmctl */ 1395 struct freebsd32_shmctl_args ap; 1396 1397 ap.shmid = uap->a2; 1398 ap.cmd = uap->a3; 1399 ap.buf = PTRIN(uap->a4); 1400 return (freebsd32_shmctl(td, &ap)); 1401 } 1402 case 1: /* oshmctl */ 1403 default: 1404 return (EINVAL); 1405 } 1406} 1407 1408struct ipc_perm32 { 1409 uint16_t cuid; 1410 uint16_t cgid; 1411 uint16_t uid; 1412 uint16_t gid; 1413 uint16_t mode; 1414 uint16_t seq; 1415 uint32_t key; 1416}; 1417struct shmid_ds32 { 1418 struct ipc_perm32 shm_perm; 1419 int32_t shm_segsz; 1420 int32_t shm_lpid; 1421 int32_t shm_cpid; 1422 int16_t shm_nattch; 1423 int32_t shm_atime; 1424 int32_t shm_dtime; 1425 int32_t shm_ctime; 1426 uint32_t shm_internal; 1427}; 1428struct shm_info32 { 1429 int32_t used_ids; 1430 uint32_t shm_tot; 1431 uint32_t shm_rss; 1432 uint32_t shm_swp; 1433 uint32_t swap_attempts; 1434 uint32_t swap_successes; 1435}; 1436struct shminfo32 { 1437 uint32_t shmmax; 1438 uint32_t shmmin; 1439 uint32_t shmmni; 1440 uint32_t shmseg; 1441 uint32_t shmall; 1442}; 1443 1444int 1445freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap) 1446{ 1447 int error = 0; 1448 union { 1449 struct shmid_ds shmid_ds; 1450 struct shm_info shm_info; 1451 struct shminfo shminfo; 1452 } u; 1453 union { 1454 struct shmid_ds32 shmid_ds32; 1455 struct shm_info32 shm_info32; 1456 struct shminfo32 shminfo32; 1457 } u32; 1458 size_t sz; 1459 1460 if (uap->cmd == IPC_SET) { 1461 if ((error = copyin(uap->buf, &u32.shmid_ds32, 1462 sizeof(u32.shmid_ds32)))) 1463 goto done; 1464 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid); 1465 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid); 1466 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid); 1467 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid); 1468 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode); 1469 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq); 1470 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key); 1471 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz); 1472 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid); 1473 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid); 1474 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch); 1475 CP(u32.shmid_ds32, u.shmid_ds, shm_atime); 1476 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime); 1477 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime); 1478 PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal); 1479 } 1480 1481 error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz); 1482 if (error) 1483 goto done; 1484 1485 /* Cases in which we need to copyout */ 1486 switch (uap->cmd) { 1487 case IPC_INFO: 1488 CP(u.shminfo, u32.shminfo32, shmmax); 1489 CP(u.shminfo, u32.shminfo32, shmmin); 1490 CP(u.shminfo, u32.shminfo32, shmmni); 1491 CP(u.shminfo, u32.shminfo32, shmseg); 1492 CP(u.shminfo, u32.shminfo32, shmall); 1493 error = copyout(&u32.shminfo32, uap->buf, 1494 sizeof(u32.shminfo32)); 1495 break; 1496 case SHM_INFO: 1497 CP(u.shm_info, u32.shm_info32, used_ids); 1498 CP(u.shm_info, u32.shm_info32, shm_rss); 1499 CP(u.shm_info, u32.shm_info32, shm_tot); 1500 CP(u.shm_info, u32.shm_info32, shm_swp); 1501 CP(u.shm_info, u32.shm_info32, swap_attempts); 1502 CP(u.shm_info, u32.shm_info32, swap_successes); 1503 error = copyout(&u32.shm_info32, uap->buf, 1504 sizeof(u32.shm_info32)); 1505 break; 1506 case SHM_STAT: 1507 case IPC_STAT: 1508 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid); 1509 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid); 1510 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid); 1511 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid); 1512 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode); 1513 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq); 1514 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key); 1515 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); 1516 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid); 1517 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid); 1518 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch); 1519 CP(u.shmid_ds, u32.shmid_ds32, shm_atime); 1520 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime); 1521 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime); 1522 PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal); 1523 error = copyout(&u32.shmid_ds32, uap->buf, 1524 sizeof(u32.shmid_ds32)); 1525 break; 1526 } 1527 1528done: 1529 if (error) { 1530 /* Invalidate the return value */ 1531 td->td_retval[0] = -1; 1532 } 1533 return (error); 1534} 1535 1536int 1537freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) 1538{ 1539 struct pread_args ap; 1540 1541 ap.fd = uap->fd; 1542 ap.buf = uap->buf; 1543 ap.nbyte = uap->nbyte; 1544 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1545 return (pread(td, &ap)); 1546} 1547 1548int 1549freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap) 1550{ 1551 struct pwrite_args ap; 1552 1553 ap.fd = uap->fd; 1554 ap.buf = uap->buf; 1555 ap.nbyte = uap->nbyte; 1556 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1557 return (pwrite(td, &ap)); 1558} 1559 1560int 1561freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap) 1562{ 1563 int error; 1564 struct lseek_args ap; 1565 off_t pos; 1566 1567 ap.fd = uap->fd; 1568 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1569 ap.whence = uap->whence; 1570 error = lseek(td, &ap); 1571 /* Expand the quad return into two parts for eax and edx */ 1572 pos = *(off_t *)(td->td_retval); 1573 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1574 td->td_retval[1] = pos >> 32; /* %edx */ 1575 return error; 1576} 1577 1578int 1579freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap) 1580{ 1581 struct truncate_args ap; 1582 1583 ap.path = uap->path; 1584 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1585 return (truncate(td, &ap)); 1586} 1587 1588int 1589freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) 1590{ 1591 struct ftruncate_args ap; 1592 1593 ap.fd = uap->fd; 1594 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32)); 1595 return (ftruncate(td, &ap)); 1596} 1597 1598struct sf_hdtr32 { 1599 uint32_t headers; 1600 int hdr_cnt; 1601 uint32_t trailers; 1602 int trl_cnt; 1603}; 1604 1605static int 1606freebsd32_do_sendfile(struct thread *td, 1607 struct freebsd32_sendfile_args *uap, int compat) 1608{ 1609 struct sendfile_args ap; 1610 struct sf_hdtr32 hdtr32; 1611 struct sf_hdtr hdtr; 1612 struct uio *hdr_uio, *trl_uio; 1613 struct iovec32 *iov32; 1614 int error; 1615 1616 hdr_uio = trl_uio = NULL; 1617 1618 ap.fd = uap->fd; 1619 ap.s = uap->s; 1620 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); 1621 ap.nbytes = uap->nbytes; 1622 ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */ 1623 ap.sbytes = uap->sbytes; 1624 ap.flags = uap->flags; 1625 1626 if (uap->hdtr != NULL) { 1627 error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32)); 1628 if (error) 1629 goto out; 1630 PTRIN_CP(hdtr32, hdtr, headers); 1631 CP(hdtr32, hdtr, hdr_cnt); 1632 PTRIN_CP(hdtr32, hdtr, trailers); 1633 CP(hdtr32, hdtr, trl_cnt); 1634 1635 if (hdtr.headers != NULL) { 1636 iov32 = (struct iovec32 *)(uintptr_t)hdtr32.headers; 1637 error = freebsd32_copyinuio(iov32, 1638 hdtr32.hdr_cnt, &hdr_uio); 1639 if (error) 1640 goto out; 1641 } 1642 if (hdtr.trailers != NULL) { 1643 iov32 = (struct iovec32 *)(uintptr_t)hdtr32.trailers; 1644 error = freebsd32_copyinuio(iov32, 1645 hdtr32.trl_cnt, &trl_uio); 1646 if (error) 1647 goto out; 1648 } 1649 } 1650 1651 error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat); 1652out: 1653 if (hdr_uio) 1654 free(hdr_uio, M_IOV); 1655 if (trl_uio) 1656 free(trl_uio, M_IOV); 1657 return (error); 1658} 1659 1660#ifdef COMPAT_FREEBSD4 1661int 1662freebsd4_freebsd32_sendfile(struct thread *td, 1663 struct freebsd4_freebsd32_sendfile_args *uap) 1664{ 1665 return (freebsd32_do_sendfile(td, 1666 (struct freebsd32_sendfile_args *)uap, 1)); 1667} 1668#endif 1669 1670int 1671freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) 1672{ 1673 1674 return (freebsd32_do_sendfile(td, uap, 0)); 1675} 1676 1677struct stat32 { 1678 dev_t st_dev; 1679 ino_t st_ino; 1680 mode_t st_mode; 1681 nlink_t st_nlink; 1682 uid_t st_uid; 1683 gid_t st_gid; 1684 dev_t st_rdev; 1685 struct timespec32 st_atimespec; 1686 struct timespec32 st_mtimespec; 1687 struct timespec32 st_ctimespec; 1688 off_t st_size; 1689 int64_t st_blocks; 1690 u_int32_t st_blksize; 1691 u_int32_t st_flags; 1692 u_int32_t st_gen; 1693 struct timespec32 st_birthtimespec; 1694 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1695 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); 1696}; 1697 1698 1699CTASSERT(sizeof(struct stat32) == 96); 1700 1701static void 1702copy_stat( struct stat *in, struct stat32 *out) 1703{ 1704 CP(*in, *out, st_dev); 1705 CP(*in, *out, st_ino); 1706 CP(*in, *out, st_mode); 1707 CP(*in, *out, st_nlink); 1708 CP(*in, *out, st_uid); 1709 CP(*in, *out, st_gid); 1710 CP(*in, *out, st_rdev); 1711 TS_CP(*in, *out, st_atimespec); 1712 TS_CP(*in, *out, st_mtimespec); 1713 TS_CP(*in, *out, st_ctimespec); 1714 CP(*in, *out, st_size); 1715 CP(*in, *out, st_blocks); 1716 CP(*in, *out, st_blksize); 1717 CP(*in, *out, st_flags); 1718 CP(*in, *out, st_gen); 1719} 1720 1721int 1722freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap) 1723{ 1724 struct stat sb; 1725 struct stat32 sb32; 1726 int error; 1727 1728 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1729 if (error) 1730 return (error); 1731 copy_stat(&sb, &sb32); 1732 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1733 return (error); 1734} 1735 1736int 1737freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap) 1738{ 1739 struct stat ub; 1740 struct stat32 ub32; 1741 int error; 1742 1743 error = kern_fstat(td, uap->fd, &ub); 1744 if (error) 1745 return (error); 1746 copy_stat(&ub, &ub32); 1747 error = copyout(&ub32, uap->ub, sizeof(ub32)); 1748 return (error); 1749} 1750 1751int 1752freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap) 1753{ 1754 struct stat sb; 1755 struct stat32 sb32; 1756 int error; 1757 1758 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1759 if (error) 1760 return (error); 1761 copy_stat(&sb, &sb32); 1762 error = copyout(&sb32, uap->ub, sizeof (sb32)); 1763 return (error); 1764} 1765 1766/* 1767 * MPSAFE 1768 */ 1769int 1770freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap) 1771{ 1772 int error, name[CTL_MAXNAME]; 1773 size_t j, oldlen; 1774 1775 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1776 return (EINVAL); 1777 error = copyin(uap->name, name, uap->namelen * sizeof(int)); 1778 if (error) 1779 return (error); 1780 mtx_lock(&Giant); 1781 if (uap->oldlenp) 1782 oldlen = fuword32(uap->oldlenp); 1783 else 1784 oldlen = 0; 1785 error = userland_sysctl(td, name, uap->namelen, 1786 uap->old, &oldlen, 1, 1787 uap->new, uap->newlen, &j, SCTL_MASK32); 1788 if (error && error != ENOMEM) 1789 goto done2; 1790 if (uap->oldlenp) 1791 suword32(uap->oldlenp, j); 1792done2: 1793 mtx_unlock(&Giant); 1794 return (error); 1795} 1796 1797struct sigaction32 { 1798 u_int32_t sa_u; 1799 int sa_flags; 1800 sigset_t sa_mask; 1801}; 1802 1803CTASSERT(sizeof(struct sigaction32) == 24); 1804 1805int 1806freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) 1807{ 1808 struct sigaction32 s32; 1809 struct sigaction sa, osa, *sap; 1810 int error; 1811 1812 if (uap->act) { 1813 error = copyin(uap->act, &s32, sizeof(s32)); 1814 if (error) 1815 return (error); 1816 sa.sa_handler = PTRIN(s32.sa_u); 1817 CP(s32, sa, sa_flags); 1818 CP(s32, sa, sa_mask); 1819 sap = &sa; 1820 } else 1821 sap = NULL; 1822 error = kern_sigaction(td, uap->sig, sap, &osa, 0); 1823 if (error == 0 && uap->oact != NULL) { 1824 s32.sa_u = PTROUT(osa.sa_handler); 1825 CP(osa, s32, sa_flags); 1826 CP(osa, s32, sa_mask); 1827 error = copyout(&s32, uap->oact, sizeof(s32)); 1828 } 1829 return (error); 1830} 1831 1832#ifdef COMPAT_FREEBSD4 1833int 1834freebsd4_freebsd32_sigaction(struct thread *td, 1835 struct freebsd4_freebsd32_sigaction_args *uap) 1836{ 1837 struct sigaction32 s32; 1838 struct sigaction sa, osa, *sap; 1839 int error; 1840 1841 if (uap->act) { 1842 error = copyin(uap->act, &s32, sizeof(s32)); 1843 if (error) 1844 return (error); 1845 sa.sa_handler = PTRIN(s32.sa_u); 1846 CP(s32, sa, sa_flags); 1847 CP(s32, sa, sa_mask); 1848 sap = &sa; 1849 } else 1850 sap = NULL; 1851 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4); 1852 if (error == 0 && uap->oact != NULL) { 1853 s32.sa_u = PTROUT(osa.sa_handler); 1854 CP(osa, s32, sa_flags); 1855 CP(osa, s32, sa_mask); 1856 error = copyout(&s32, uap->oact, sizeof(s32)); 1857 } 1858 return (error); 1859} 1860#endif 1861 1862#ifdef COMPAT_43 1863struct osigaction32 { 1864 u_int32_t sa_u; 1865 osigset_t sa_mask; 1866 int sa_flags; 1867}; 1868 1869#define ONSIG 32 1870 1871int 1872ofreebsd32_sigaction(struct thread *td, 1873 struct ofreebsd32_sigaction_args *uap) 1874{ 1875 struct osigaction32 s32; 1876 struct sigaction sa, osa, *sap; 1877 int error; 1878 1879 if (uap->signum <= 0 || uap->signum >= ONSIG) 1880 return (EINVAL); 1881 1882 if (uap->nsa) { 1883 error = copyin(uap->nsa, &s32, sizeof(s32)); 1884 if (error) 1885 return (error); 1886 sa.sa_handler = PTRIN(s32.sa_u); 1887 CP(s32, sa, sa_flags); 1888 OSIG2SIG(s32.sa_mask, sa.sa_mask); 1889 sap = &sa; 1890 } else 1891 sap = NULL; 1892 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1893 if (error == 0 && uap->osa != NULL) { 1894 s32.sa_u = PTROUT(osa.sa_handler); 1895 CP(osa, s32, sa_flags); 1896 SIG2OSIG(osa.sa_mask, s32.sa_mask); 1897 error = copyout(&s32, uap->osa, sizeof(s32)); 1898 } 1899 return (error); 1900} 1901 1902int 1903ofreebsd32_sigprocmask(struct thread *td, 1904 struct ofreebsd32_sigprocmask_args *uap) 1905{ 1906 sigset_t set, oset; 1907 int error; 1908 1909 OSIG2SIG(uap->mask, set); 1910 error = kern_sigprocmask(td, uap->how, &set, &oset, 1); 1911 SIG2OSIG(oset, td->td_retval[0]); 1912 return (error); 1913} 1914 1915int 1916ofreebsd32_sigpending(struct thread *td, 1917 struct ofreebsd32_sigpending_args *uap) 1918{ 1919 struct proc *p = td->td_proc; 1920 sigset_t siglist; 1921 1922 PROC_LOCK(p); 1923 siglist = p->p_siglist; 1924 SIGSETOR(siglist, td->td_siglist); 1925 PROC_UNLOCK(p); 1926 SIG2OSIG(siglist, td->td_retval[0]); 1927 return (0); 1928} 1929 1930struct sigvec32 { 1931 u_int32_t sv_handler; 1932 int sv_mask; 1933 int sv_flags; 1934}; 1935 1936int 1937ofreebsd32_sigvec(struct thread *td, 1938 struct ofreebsd32_sigvec_args *uap) 1939{ 1940 struct sigvec32 vec; 1941 struct sigaction sa, osa, *sap; 1942 int error; 1943 1944 if (uap->signum <= 0 || uap->signum >= ONSIG) 1945 return (EINVAL); 1946 1947 if (uap->nsv) { 1948 error = copyin(uap->nsv, &vec, sizeof(vec)); 1949 if (error) 1950 return (error); 1951 sa.sa_handler = PTRIN(vec.sv_handler); 1952 OSIG2SIG(vec.sv_mask, sa.sa_mask); 1953 sa.sa_flags = vec.sv_flags; 1954 sa.sa_flags ^= SA_RESTART; 1955 sap = &sa; 1956 } else 1957 sap = NULL; 1958 error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET); 1959 if (error == 0 && uap->osv != NULL) { 1960 vec.sv_handler = PTROUT(osa.sa_handler); 1961 SIG2OSIG(osa.sa_mask, vec.sv_mask); 1962 vec.sv_flags = osa.sa_flags; 1963 vec.sv_flags &= ~SA_NOCLDWAIT; 1964 vec.sv_flags ^= SA_RESTART; 1965 error = copyout(&vec, uap->osv, sizeof(vec)); 1966 } 1967 return (error); 1968} 1969 1970int 1971ofreebsd32_sigblock(struct thread *td, 1972 struct ofreebsd32_sigblock_args *uap) 1973{ 1974 struct proc *p = td->td_proc; 1975 sigset_t set; 1976 1977 OSIG2SIG(uap->mask, set); 1978 SIG_CANTMASK(set); 1979 PROC_LOCK(p); 1980 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 1981 SIGSETOR(td->td_sigmask, set); 1982 PROC_UNLOCK(p); 1983 return (0); 1984} 1985 1986int 1987ofreebsd32_sigsetmask(struct thread *td, 1988 struct ofreebsd32_sigsetmask_args *uap) 1989{ 1990 struct proc *p = td->td_proc; 1991 sigset_t set; 1992 1993 OSIG2SIG(uap->mask, set); 1994 SIG_CANTMASK(set); 1995 PROC_LOCK(p); 1996 SIG2OSIG(td->td_sigmask, td->td_retval[0]); 1997 SIGSETLO(td->td_sigmask, set); 1998 signotify(td); 1999 PROC_UNLOCK(p); 2000 return (0); 2001} 2002 2003int 2004ofreebsd32_sigsuspend(struct thread *td, 2005 struct ofreebsd32_sigsuspend_args *uap) 2006{ 2007 struct proc *p = td->td_proc; 2008 sigset_t mask; 2009 2010 PROC_LOCK(p); 2011 td->td_oldsigmask = td->td_sigmask; 2012 td->td_pflags |= TDP_OLDMASK; 2013 OSIG2SIG(uap->mask, mask); 2014 SIG_CANTMASK(mask); 2015 SIGSETLO(td->td_sigmask, mask); 2016 signotify(td); 2017 while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) 2018 /* void */; 2019 PROC_UNLOCK(p); 2020 /* always return EINTR rather than ERESTART... */ 2021 return (EINTR); 2022} 2023 2024struct sigstack32 { 2025 u_int32_t ss_sp; 2026 int ss_onstack; 2027}; 2028 2029int 2030ofreebsd32_sigstack(struct thread *td, 2031 struct ofreebsd32_sigstack_args *uap) 2032{ 2033 struct sigstack32 s32; 2034 struct sigstack nss, oss; 2035 int error = 0; 2036 2037 if (uap->nss != NULL) { 2038 error = copyin(uap->nss, &s32, sizeof(s32)); 2039 if (error) 2040 return (error); 2041 nss.ss_sp = PTRIN(s32.ss_sp); 2042 CP(s32, nss, ss_onstack); 2043 } 2044 oss.ss_sp = td->td_sigstk.ss_sp; 2045 oss.ss_onstack = sigonstack(cpu_getstack(td)); 2046 if (uap->nss != NULL) { 2047 td->td_sigstk.ss_sp = nss.ss_sp; 2048 td->td_sigstk.ss_size = 0; 2049 td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK; 2050 td->td_pflags |= TDP_ALTSTACK; 2051 } 2052 if (uap->oss != NULL) { 2053 s32.ss_sp = PTROUT(oss.ss_sp); 2054 CP(oss, s32, ss_onstack); 2055 error = copyout(&s32, uap->oss, sizeof(s32)); 2056 } 2057 return (error); 2058} 2059#endif 2060 2061int 2062freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap) 2063{ 2064 struct timespec32 rmt32, rqt32; 2065 struct timespec rmt, rqt; 2066 int error; 2067 2068 error = copyin(uap->rqtp, &rqt32, sizeof(rqt32)); 2069 if (error) 2070 return (error); 2071 2072 CP(rqt32, rqt, tv_sec); 2073 CP(rqt32, rqt, tv_nsec); 2074 2075 if (uap->rmtp && 2076 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 2077 return (EFAULT); 2078 error = kern_nanosleep(td, &rqt, &rmt); 2079 if (error && uap->rmtp) { 2080 int error2; 2081 2082 CP(rmt, rmt32, tv_sec); 2083 CP(rmt, rmt32, tv_nsec); 2084 2085 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32)); 2086 if (error2) 2087 error = error2; 2088 } 2089 return (error); 2090} 2091 2092int 2093freebsd32_clock_gettime(struct thread *td, 2094 struct freebsd32_clock_gettime_args *uap) 2095{ 2096 struct timespec ats; 2097 struct timespec32 ats32; 2098 int error; 2099 2100 error = kern_clock_gettime(td, uap->clock_id, &ats); 2101 if (error == 0) { 2102 CP(ats, ats32, tv_sec); 2103 CP(ats, ats32, tv_nsec); 2104 error = copyout(&ats32, uap->tp, sizeof(ats32)); 2105 } 2106 return (error); 2107} 2108 2109int 2110freebsd32_clock_settime(struct thread *td, 2111 struct freebsd32_clock_settime_args *uap) 2112{ 2113 struct timespec ats; 2114 struct timespec32 ats32; 2115 int error; 2116 2117 error = copyin(uap->tp, &ats32, sizeof(ats32)); 2118 if (error) 2119 return (error); 2120 CP(ats32, ats, tv_sec); 2121 CP(ats32, ats, tv_nsec); 2122 2123 return (kern_clock_settime(td, uap->clock_id, &ats)); 2124} 2125 2126int 2127freebsd32_clock_getres(struct thread *td, 2128 struct freebsd32_clock_getres_args *uap) 2129{ 2130 struct timespec ts; 2131 struct timespec32 ts32; 2132 int error; 2133 2134 if (uap->tp == NULL) 2135 return (0); 2136 error = kern_clock_getres(td, uap->clock_id, &ts); 2137 if (error == 0) { 2138 CP(ts, ts32, tv_sec); 2139 CP(ts, ts32, tv_nsec); 2140 error = copyout(&ts32, uap->tp, sizeof(ts32)); 2141 } 2142 return (error); 2143} 2144 2145#if 0 2146 2147int 2148freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) 2149{ 2150 int error; 2151 struct yyy32 *p32, s32; 2152 struct yyy *p = NULL, s; 2153 2154 if (uap->zzz) { 2155 error = copyin(uap->zzz, &s32, sizeof(s32)); 2156 if (error) 2157 return (error); 2158 /* translate in */ 2159 p = &s; 2160 } 2161 error = kern_xxx(td, p); 2162 if (error) 2163 return (error); 2164 if (uap->zzz) { 2165 /* translate out */ 2166 error = copyout(&s32, p32, sizeof(s32)); 2167 } 2168 return (error); 2169} 2170 2171#endif 2172