[BACK]Return to linux_misc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / linux / common

Annotation of src/sys/compat/linux/common/linux_misc.c, Revision 1.201.4.2

1.201.4.2! skrll       1: /*     $NetBSD: linux_misc.c,v 1.201.4.1 2009/01/19 13:17:31 skrll Exp $       */
1.47      erh         2:
                      3: /*-
1.194     ad          4:  * Copyright (c) 1995, 1998, 1999, 2008 The NetBSD Foundation, Inc.
1.47      erh         5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.56      thorpej     8:  * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe
                      9:  * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center.
1.47      erh        10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
1.1       fvdl       31:  */
                     32:
                     33: /*
                     34:  * Linux compatibility module. Try to deal with various Linux system calls.
                     35:  */
                     36:
1.47      erh        37: /*
                     38:  * These functions have been moved to multiarch to allow
1.135     perry      39:  * selection of which machines include them to be
1.47      erh        40:  * determined by the individual files.linux_<arch> files.
                     41:  *
                     42:  * Function in multiarch:
                     43:  *     linux_sys_break                 : linux_break.c
                     44:  *     linux_sys_alarm                 : linux_misc_notalpha.c
1.57      thorpej    45:  *     linux_sys_getresgid             : linux_misc_notalpha.c
1.47      erh        46:  *     linux_sys_nice                  : linux_misc_notalpha.c
                     47:  *     linux_sys_readdir               : linux_misc_notalpha.c
1.57      thorpej    48:  *     linux_sys_setresgid             : linux_misc_notalpha.c
1.47      erh        49:  *     linux_sys_time                  : linux_misc_notalpha.c
                     50:  *     linux_sys_utime                 : linux_misc_notalpha.c
                     51:  *     linux_sys_waitpid               : linux_misc_notalpha.c
                     52:  *     linux_sys_old_mmap              : linux_oldmmap.c
                     53:  *     linux_sys_oldolduname           : linux_oldolduname.c
                     54:  *     linux_sys_oldselect             : linux_oldselect.c
                     55:  *     linux_sys_olduname              : linux_olduname.c
                     56:  *     linux_sys_pipe                  : linux_pipe.c
                     57:  */
1.95      lukem      58:
                     59: #include <sys/cdefs.h>
1.201.4.2! skrll      60: __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.201.4.1 2009/01/19 13:17:31 skrll Exp $");
1.47      erh        61:
1.1       fvdl       62: #include <sys/param.h>
                     63: #include <sys/systm.h>
                     64: #include <sys/namei.h>
                     65: #include <sys/proc.h>
1.29      mycroft    66: #include <sys/dirent.h>
1.1       fvdl       67: #include <sys/file.h>
                     68: #include <sys/stat.h>
                     69: #include <sys/filedesc.h>
                     70: #include <sys/ioctl.h>
                     71: #include <sys/kernel.h>
                     72: #include <sys/malloc.h>
                     73: #include <sys/mbuf.h>
                     74: #include <sys/mman.h>
                     75: #include <sys/mount.h>
1.179     dsl        76: #include <sys/prot.h>
1.67      erh        77: #include <sys/reboot.h>
1.1       fvdl       78: #include <sys/resource.h>
                     79: #include <sys/resourcevar.h>
1.177     dsl        80: #include <sys/select.h>
1.1       fvdl       81: #include <sys/signal.h>
                     82: #include <sys/signalvar.h>
                     83: #include <sys/socket.h>
                     84: #include <sys/time.h>
                     85: #include <sys/times.h>
                     86: #include <sys/vnode.h>
                     87: #include <sys/uio.h>
                     88: #include <sys/wait.h>
                     89: #include <sys/utsname.h>
                     90: #include <sys/unistd.h>
1.172     dsl        91: #include <sys/vfs_syscalls.h>
1.75      jdolecek   92: #include <sys/swap.h>          /* for SWAP_ON */
                     93: #include <sys/sysctl.h>                /* for KERN_DOMAINNAME */
1.154     elad       94: #include <sys/kauth.h>
1.1       fvdl       95:
1.73      jdolecek   96: #include <sys/ptrace.h>
                     97: #include <machine/ptrace.h>
                     98:
1.161     matt       99: #include <sys/syscall.h>
1.1       fvdl      100: #include <sys/syscallargs.h>
                    101:
1.201.4.1  skrll     102: #include <compat/sys/resource.h>
                    103:
1.143     manu      104: #include <compat/linux/common/linux_machdep.h>
1.49      christos  105: #include <compat/linux/common/linux_types.h>
                    106: #include <compat/linux/common/linux_signal.h>
1.184     njoly     107: #include <compat/linux/common/linux_ipc.h>
                    108: #include <compat/linux/common/linux_sem.h>
1.49      christos  109:
1.1       fvdl      110: #include <compat/linux/linux_syscallargs.h>
1.49      christos  111:
                    112: #include <compat/linux/common/linux_fcntl.h>
                    113: #include <compat/linux/common/linux_mmap.h>
                    114: #include <compat/linux/common/linux_dirent.h>
                    115: #include <compat/linux/common/linux_util.h>
                    116: #include <compat/linux/common/linux_misc.h>
1.150     manu      117: #ifndef COMPAT_LINUX32
1.170     njoly     118: #include <compat/linux/common/linux_statfs.h>
1.150     manu      119: #include <compat/linux/common/linux_limit.h>
                    120: #endif
1.62      tron      121: #include <compat/linux/common/linux_ptrace.h>
1.67      erh       122: #include <compat/linux/common/linux_reboot.h>
1.84      manu      123: #include <compat/linux/common/linux_emuldata.h>
1.49      christos  124:
1.150     manu      125: #ifndef COMPAT_LINUX32
1.73      jdolecek  126: const int linux_ptrace_request_map[] = {
1.62      tron      127:        LINUX_PTRACE_TRACEME,   PT_TRACE_ME,
                    128:        LINUX_PTRACE_PEEKTEXT,  PT_READ_I,
                    129:        LINUX_PTRACE_PEEKDATA,  PT_READ_D,
                    130:        LINUX_PTRACE_POKETEXT,  PT_WRITE_I,
                    131:        LINUX_PTRACE_POKEDATA,  PT_WRITE_D,
                    132:        LINUX_PTRACE_CONT,      PT_CONTINUE,
                    133:        LINUX_PTRACE_KILL,      PT_KILL,
                    134:        LINUX_PTRACE_ATTACH,    PT_ATTACH,
                    135:        LINUX_PTRACE_DETACH,    PT_DETACH,
1.150     manu      136: # ifdef PT_STEP
1.73      jdolecek  137:        LINUX_PTRACE_SINGLESTEP,        PT_STEP,
1.150     manu      138: # endif
1.170     njoly     139:        LINUX_PTRACE_SYSCALL,   PT_SYSCALL,
1.62      tron      140:        -1
                    141: };
1.1       fvdl      142:
1.132     jdolecek  143: const struct linux_mnttypes linux_fstypes[] = {
1.101     christos  144:        { MOUNT_FFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    145:        { MOUNT_NFS,            LINUX_NFS_SUPER_MAGIC           },
                    146:        { MOUNT_MFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    147:        { MOUNT_MSDOS,          LINUX_MSDOS_SUPER_MAGIC         },
                    148:        { MOUNT_LFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    149:        { MOUNT_FDESC,          LINUX_DEFAULT_SUPER_MAGIC       },
                    150:        { MOUNT_PORTAL,         LINUX_DEFAULT_SUPER_MAGIC       },
                    151:        { MOUNT_NULL,           LINUX_DEFAULT_SUPER_MAGIC       },
1.135     perry     152:        { MOUNT_OVERLAY,        LINUX_DEFAULT_SUPER_MAGIC       },
1.101     christos  153:        { MOUNT_UMAP,           LINUX_DEFAULT_SUPER_MAGIC       },
                    154:        { MOUNT_KERNFS,         LINUX_DEFAULT_SUPER_MAGIC       },
                    155:        { MOUNT_PROCFS,         LINUX_PROC_SUPER_MAGIC          },
                    156:        { MOUNT_AFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    157:        { MOUNT_CD9660,         LINUX_ISOFS_SUPER_MAGIC         },
                    158:        { MOUNT_UNION,          LINUX_DEFAULT_SUPER_MAGIC       },
                    159:        { MOUNT_ADOSFS,         LINUX_ADFS_SUPER_MAGIC          },
                    160:        { MOUNT_EXT2FS,         LINUX_EXT2_SUPER_MAGIC          },
                    161:        { MOUNT_CFS,            LINUX_DEFAULT_SUPER_MAGIC       },
                    162:        { MOUNT_CODA,           LINUX_CODA_SUPER_MAGIC          },
                    163:        { MOUNT_FILECORE,       LINUX_DEFAULT_SUPER_MAGIC       },
                    164:        { MOUNT_NTFS,           LINUX_DEFAULT_SUPER_MAGIC       },
1.134     christos  165:        { MOUNT_SMBFS,          LINUX_SMB_SUPER_MAGIC           },
1.140     jmmv      166:        { MOUNT_PTYFS,          LINUX_DEVPTS_SUPER_MAGIC        },
1.199     njoly     167:        { MOUNT_TMPFS,          LINUX_TMPFS_SUPER_MAGIC         }
1.101     christos  168: };
1.132     jdolecek  169: const int linux_fstypes_cnt = sizeof(linux_fstypes) / sizeof(linux_fstypes[0]);
1.101     christos  170:
1.150     manu      171: # ifdef DEBUG_LINUX
1.104     christos  172: #define DPRINTF(a)     uprintf a
1.150     manu      173: # else
1.104     christos  174: #define DPRINTF(a)
1.150     manu      175: # endif
1.104     christos  176:
1.47      erh       177: /* Local linux_misc.c functions: */
1.188     dsl       178: static void linux_to_bsd_mmap_args(struct sys_mmap_args *,
                    179:     const struct linux_sys_mmap_args *);
1.190     dsl       180: static int linux_mmap(struct lwp *, const struct linux_sys_mmap_args *,
1.188     dsl       181:     register_t *, off_t);
1.128     jdolecek  182:
1.26      christos  183:
1.1       fvdl      184: /*
                    185:  * The information on a terminated (or stopped) process needs
                    186:  * to be converted in order for Linux binaries to get a valid signal
                    187:  * number out of it.
                    188:  */
1.173     dsl       189: int
                    190: bsd_to_linux_wstat(int st)
1.1       fvdl      191: {
1.21      mycroft   192:
1.52      christos  193:        int sig;
                    194:
1.173     dsl       195:        if (WIFSIGNALED(st)) {
                    196:                sig = WTERMSIG(st);
1.52      christos  197:                if (sig >= 0 && sig < NSIG)
1.173     dsl       198:                        st= (st & ~0177) | native_to_linux_signo[sig];
                    199:        } else if (WIFSTOPPED(st)) {
                    200:                sig = WSTOPSIG(st);
1.52      christos  201:                if (sig >= 0 && sig < NSIG)
1.173     dsl       202:                        st = (st & ~0xff00) |
1.105     christos  203:                            (native_to_linux_signo[sig] << 8);
1.52      christos  204:        }
1.173     dsl       205:        return st;
1.1       fvdl      206: }
                    207:
                    208: /*
1.133     erh       209:  * wait4(2).  Passed on to the NetBSD call, surrounded by code to
                    210:  * reserve some space for a NetBSD-style wait status, and converting
                    211:  * it to what Linux wants.
1.1       fvdl      212:  */
                    213: int
1.190     dsl       214: linux_sys_wait4(struct lwp *l, const struct linux_sys_wait4_args *uap, register_t *retval)
1.20      thorpej   215: {
1.190     dsl       216:        /* {
1.1       fvdl      217:                syscallarg(int) pid;
                    218:                syscallarg(int *) status;
                    219:                syscallarg(int) options;
1.201.4.1  skrll     220:                syscallarg(struct rusage50 *) rusage;
1.190     dsl       221:        } */
1.173     dsl       222:        int error, status, options, linux_options, was_zombie;
                    223:        struct rusage ru;
1.201.4.1  skrll     224:        struct rusage50 ru50;
1.190     dsl       225:        int pid = SCARG(uap, pid);
1.196     ad        226:        proc_t *p;
1.1       fvdl      227:
1.55      thorpej   228:        linux_options = SCARG(uap, options);
1.173     dsl       229:        options = WOPTSCHECKED;
1.133     erh       230:        if (linux_options & ~(LINUX_WAIT4_KNOWNFLAGS))
1.55      thorpej   231:                return (EINVAL);
                    232:
                    233:        if (linux_options & LINUX_WAIT4_WNOHANG)
                    234:                options |= WNOHANG;
                    235:        if (linux_options & LINUX_WAIT4_WUNTRACED)
                    236:                options |= WUNTRACED;
1.93      thorpej   237:        if (linux_options & LINUX_WAIT4_WALL)
                    238:                options |= WALLSIG;
1.55      thorpej   239:        if (linux_options & LINUX_WAIT4_WCLONE)
                    240:                options |= WALTSIG;
1.150     manu      241: # ifdef DIAGNOSTIC
1.133     erh       242:        if (linux_options & LINUX_WAIT4_WNOTHREAD)
                    243:                printf("WARNING: %s: linux process %d.%d called "
                    244:                       "waitpid with __WNOTHREAD set!",
1.173     dsl       245:                       __FILE__, l->l_proc->p_pid, l->l_lid);
1.133     erh       246:
1.150     manu      247: # endif
1.55      thorpej   248:
1.190     dsl       249:        error = do_sys_wait(l, &pid, &status, options,
1.174     dsl       250:            SCARG(uap, rusage) != NULL ? &ru : NULL, &was_zombie);
1.1       fvdl      251:
1.190     dsl       252:        retval[0] = pid;
                    253:        if (pid == 0)
1.1       fvdl      254:                return error;
                    255:
1.196     ad        256:         p = curproc;
1.197     ad        257:         mutex_enter(p->p_lock);
1.196     ad        258:        sigdelset(&p->p_sigpend.sp_set, SIGCHLD); /* XXXAD ksiginfo leak */
1.197     ad        259:         mutex_exit(p->p_lock);
1.18      fvdl      260:
1.201.4.1  skrll     261:        if (SCARG(uap, rusage) != NULL) {
                    262:                rusage_to_rusage50(&ru, &ru50);
1.174     dsl       263:                error = copyout(&ru, SCARG(uap, rusage), sizeof(ru));
1.201.4.1  skrll     264:        }
1.174     dsl       265:
                    266:        if (error == 0 && SCARG(uap, status) != NULL) {
1.173     dsl       267:                status = bsd_to_linux_wstat(status);
1.174     dsl       268:                error = copyout(&status, SCARG(uap, status), sizeof status);
1.16      fvdl      269:        }
1.1       fvdl      270:
1.174     dsl       271:        return error;
1.1       fvdl      272: }
                    273:
                    274: /*
                    275:  * Linux brk(2). The check if the new address is >= the old one is
                    276:  * done in the kernel in Linux. NetBSD does it in the library.
                    277:  */
                    278: int
1.190     dsl       279: linux_sys_brk(struct lwp *l, const struct linux_sys_brk_args *uap, register_t *retval)
1.20      thorpej   280: {
1.190     dsl       281:        /* {
1.1       fvdl      282:                syscallarg(char *) nsize;
1.190     dsl       283:        } */
1.116     thorpej   284:        struct proc *p = l->l_proc;
1.1       fvdl      285:        char *nbrk = SCARG(uap, nsize);
1.21      mycroft   286:        struct sys_obreak_args oba;
1.1       fvdl      287:        struct vmspace *vm = p->p_vmspace;
1.85      manu      288:        struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata;
1.84      manu      289:
1.1       fvdl      290:        SCARG(&oba, nsize) = nbrk;
                    291:
1.167     christos  292:        if ((void *) nbrk > vm->vm_daddr && sys_obreak(l, &oba, retval) == 0)
1.127     jdolecek  293:                ed->s->p_break = (char*)nbrk;
1.135     perry     294:        else
1.127     jdolecek  295:                nbrk = ed->s->p_break;
1.85      manu      296:
                    297:        retval[0] = (register_t)nbrk;
1.1       fvdl      298:
                    299:        return 0;
                    300: }
                    301:
                    302: /*
1.2       fvdl      303:  * Implement the fs stat functions. Straightforward.
1.1       fvdl      304:  */
                    305: int
1.190     dsl       306: linux_sys_statfs(struct lwp *l, const struct linux_sys_statfs_args *uap, register_t *retval)
1.20      thorpej   307: {
1.190     dsl       308:        /* {
1.53      christos  309:                syscallarg(const char *) path;
1.1       fvdl      310:                syscallarg(struct linux_statfs *) sp;
1.190     dsl       311:        } */
1.172     dsl       312:        struct statvfs *sb;
1.2       fvdl      313:        struct linux_statfs ltmp;
                    314:        int error;
                    315:
1.172     dsl       316:        sb = STATVFSBUF_GET();
                    317:        error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb);
                    318:        if (error == 0) {
                    319:                bsd_to_linux_statfs(sb, &ltmp);
                    320:                error = copyout(&ltmp, SCARG(uap, sp), sizeof ltmp);
                    321:        }
                    322:        STATVFSBUF_PUT(sb);
1.2       fvdl      323:
1.153     yamt      324:        return error;
1.1       fvdl      325: }
                    326:
                    327: int
1.190     dsl       328: linux_sys_fstatfs(struct lwp *l, const struct linux_sys_fstatfs_args *uap, register_t *retval)
1.20      thorpej   329: {
1.190     dsl       330:        /* {
1.2       fvdl      331:                syscallarg(int) fd;
1.1       fvdl      332:                syscallarg(struct linux_statfs *) sp;
1.190     dsl       333:        } */
1.172     dsl       334:        struct statvfs *sb;
1.2       fvdl      335:        struct linux_statfs ltmp;
                    336:        int error;
                    337:
1.172     dsl       338:        sb = STATVFSBUF_GET();
                    339:        error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
                    340:        if (error == 0) {
                    341:                bsd_to_linux_statfs(sb, &ltmp);
                    342:                error = copyout(&ltmp, SCARG(uap, sp), sizeof ltmp);
                    343:        }
                    344:        STATVFSBUF_PUT(sb);
1.2       fvdl      345:
1.153     yamt      346:        return error;
1.1       fvdl      347: }
1.82      fvdl      348:
1.1       fvdl      349: /*
                    350:  * uname(). Just copy the info from the various strings stored in the
                    351:  * kernel, and put it in the Linux utsname structure. That structure
                    352:  * is almost the same as the NetBSD one, only it has fields 65 characters
                    353:  * long, and an extra domainname field.
                    354:  */
                    355: int
1.190     dsl       356: linux_sys_uname(struct lwp *l, const struct linux_sys_uname_args *uap, register_t *retval)
1.20      thorpej   357: {
1.190     dsl       358:        /* {
1.1       fvdl      359:                syscallarg(struct linux_utsname *) up;
1.190     dsl       360:        } */
1.15      mycroft   361:        struct linux_utsname luts;
1.1       fvdl      362:
1.186     njoly     363:        strlcpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname));
                    364:        strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
                    365:        strlcpy(luts.l_release, linux_release, sizeof(luts.l_release));
                    366:        strlcpy(luts.l_version, linux_version, sizeof(luts.l_version));
                    367:        strlcpy(luts.l_machine, LINUX_UNAME_ARCH, sizeof(luts.l_machine));
                    368:        strlcpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
1.15      mycroft   369:
                    370:        return copyout(&luts, SCARG(uap, up), sizeof(luts));
                    371: }
                    372:
1.47      erh       373: /* Used directly on: alpha, mips, ppc, sparc, sparc64 */
                    374: /* Used indirectly on: arm, i386, m68k */
1.1       fvdl      375:
                    376: /*
1.47      erh       377:  * New type Linux mmap call.
                    378:  * Only called directly on machines with >= 6 free regs.
1.1       fvdl      379:  */
                    380: int
1.190     dsl       381: linux_sys_mmap(struct lwp *l, const struct linux_sys_mmap_args *uap, register_t *retval)
1.20      thorpej   382: {
1.190     dsl       383:        /* {
1.47      erh       384:                syscallarg(unsigned long) addr;
                    385:                syscallarg(size_t) len;
                    386:                syscallarg(int) prot;
                    387:                syscallarg(int) flags;
                    388:                syscallarg(int) fd;
1.94      manu      389:                syscallarg(linux_off_t) offset;
1.190     dsl       390:        } */
1.118     christos  391:
1.115     christos  392:        if (SCARG(uap, offset) & PAGE_MASK)
                    393:                return EINVAL;
                    394:
1.128     jdolecek  395:        return linux_mmap(l, uap, retval, SCARG(uap, offset));
1.118     christos  396: }
                    397:
                    398: /*
                    399:  * Guts of most architectures' mmap64() implementations.  This shares
                    400:  * its list of arguments with linux_sys_mmap().
                    401:  *
                    402:  * The difference in linux_sys_mmap2() is that "offset" is actually
                    403:  * (offset / pagesize), not an absolute byte count.  This translation
                    404:  * to pagesize offsets is done inside glibc between the mmap64() call
                    405:  * point, and the actual syscall.
                    406:  */
                    407: int
1.190     dsl       408: linux_sys_mmap2(struct lwp *l, const struct linux_sys_mmap2_args *uap, register_t *retval)
1.118     christos  409: {
1.190     dsl       410:        /* {
1.118     christos  411:                syscallarg(unsigned long) addr;
                    412:                syscallarg(size_t) len;
                    413:                syscallarg(int) prot;
                    414:                syscallarg(int) flags;
                    415:                syscallarg(int) fd;
                    416:                syscallarg(linux_off_t) offset;
1.190     dsl       417:        } */
1.128     jdolecek  418:
                    419:        return linux_mmap(l, uap, retval,
                    420:            ((off_t)SCARG(uap, offset)) << PAGE_SHIFT);
                    421: }
                    422:
                    423: /*
                    424:  * Massage arguments and call system mmap(2).
                    425:  */
                    426: static int
1.190     dsl       427: linux_mmap(struct lwp *l, const struct linux_sys_mmap_args *uap, register_t *retval, off_t offset)
1.128     jdolecek  428: {
1.118     christos  429:        struct sys_mmap_args cma;
1.128     jdolecek  430:        int error;
                    431:        size_t mmoff=0;
                    432:
1.190     dsl       433:        linux_to_bsd_mmap_args(&cma, uap);
                    434:        SCARG(&cma, pos) = offset;
                    435:
1.128     jdolecek  436:        if (SCARG(uap, flags) & LINUX_MAP_GROWSDOWN) {
                    437:                /*
                    438:                 * Request for stack-like memory segment. On linux, this
                    439:                 * works by mmap()ping (small) segment, which is automatically
                    440:                 * extended when page fault happens below the currently
                    441:                 * allocated area. We emulate this by allocating (typically
                    442:                 * bigger) segment sized at current stack size limit, and
                    443:                 * offsetting the requested and returned address accordingly.
                    444:                 * Since physical pages are only allocated on-demand, this
                    445:                 * is effectively identical.
                    446:                 */
                    447:                rlim_t ssl = l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur;
                    448:
1.190     dsl       449:                if (SCARG(&cma, len) < ssl) {
1.128     jdolecek  450:                        /* Compute the address offset */
                    451:                        mmoff = round_page(ssl) - SCARG(uap, len);
                    452:
1.190     dsl       453:                        if (SCARG(&cma, addr))
                    454:                                SCARG(&cma, addr) = (char *)SCARG(&cma, addr) - mmoff;
1.128     jdolecek  455:
1.190     dsl       456:                        SCARG(&cma, len) = (size_t) ssl;
1.128     jdolecek  457:                }
                    458:        }
1.118     christos  459:
1.128     jdolecek  460:        error = sys_mmap(l, &cma, retval);
                    461:        if (error)
                    462:                return (error);
                    463:
                    464:        /* Shift the returned address for stack-like segment if necessary */
1.190     dsl       465:        retval[0] += mmoff;
1.118     christos  466:
1.128     jdolecek  467:        return (0);
1.118     christos  468: }
                    469:
                    470: static void
1.189     dsl       471: linux_to_bsd_mmap_args(struct sys_mmap_args *cma, const struct linux_sys_mmap_args *uap)
1.118     christos  472: {
1.119     christos  473:        int flags = MAP_TRYFIXED, fl = SCARG(uap, flags);
1.135     perry     474:
1.103     christos  475:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_SHARED, MAP_SHARED);
                    476:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_PRIVATE, MAP_PRIVATE);
                    477:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_FIXED, MAP_FIXED);
                    478:        flags |= cvtto_bsd_mask(fl, LINUX_MAP_ANON, MAP_ANON);
1.47      erh       479:        /* XXX XAX ERH: Any other flags here?  There are more defined... */
                    480:
1.118     christos  481:        SCARG(cma, addr) = (void *)SCARG(uap, addr);
                    482:        SCARG(cma, len) = SCARG(uap, len);
                    483:        SCARG(cma, prot) = SCARG(uap, prot);
                    484:        if (SCARG(cma, prot) & VM_PROT_WRITE) /* XXX */
                    485:                SCARG(cma, prot) |= VM_PROT_READ;
                    486:        SCARG(cma, flags) = flags;
                    487:        SCARG(cma, fd) = flags & MAP_ANON ? -1 : SCARG(uap, fd);
                    488:        SCARG(cma, pad) = 0;
1.97      christos  489: }
                    490:
1.148     yamt      491: #define        LINUX_MREMAP_MAYMOVE    1
                    492: #define        LINUX_MREMAP_FIXED      2
                    493:
1.34      mycroft   494: int
1.190     dsl       495: linux_sys_mremap(struct lwp *l, const struct linux_sys_mremap_args *uap, register_t *retval)
1.34      mycroft   496: {
1.190     dsl       497:        /* {
1.34      mycroft   498:                syscallarg(void *) old_address;
                    499:                syscallarg(size_t) old_size;
                    500:                syscallarg(size_t) new_size;
                    501:                syscallarg(u_long) flags;
1.190     dsl       502:        } */
1.148     yamt      503:
                    504:        struct proc *p;
                    505:        struct vm_map *map;
                    506:        vaddr_t oldva;
                    507:        vaddr_t newva;
                    508:        size_t oldsize;
                    509:        size_t newsize;
                    510:        int flags;
                    511:        int uvmflags;
1.42      thorpej   512:        int error;
                    513:
1.148     yamt      514:        flags = SCARG(uap, flags);
                    515:        oldva = (vaddr_t)SCARG(uap, old_address);
                    516:        oldsize = round_page(SCARG(uap, old_size));
                    517:        newsize = round_page(SCARG(uap, new_size));
1.149     yamt      518:        if ((flags & ~(LINUX_MREMAP_FIXED|LINUX_MREMAP_MAYMOVE)) != 0) {
                    519:                error = EINVAL;
                    520:                goto done;
                    521:        }
1.148     yamt      522:        if ((flags & LINUX_MREMAP_FIXED) != 0) {
1.149     yamt      523:                if ((flags & LINUX_MREMAP_MAYMOVE) == 0) {
                    524:                        error = EINVAL;
                    525:                        goto done;
                    526:                }
1.148     yamt      527: #if 0 /* notyet */
                    528:                newva = SCARG(uap, new_address);
1.183     joerg     529:                uvmflags = MAP_FIXED;
1.148     yamt      530: #else /* notyet */
                    531:                error = EOPNOTSUPP;
                    532:                goto done;
                    533: #endif /* notyet */
                    534:        } else if ((flags & LINUX_MREMAP_MAYMOVE) != 0) {
                    535:                uvmflags = 0;
                    536:        } else {
                    537:                newva = oldva;
1.183     joerg     538:                uvmflags = MAP_FIXED;
1.42      thorpej   539:        }
1.148     yamt      540:        p = l->l_proc;
                    541:        map = &p->p_vmspace->vm_map;
                    542:        error = uvm_mremap(map, oldva, oldsize, map, &newva, newsize, p,
                    543:            uvmflags);
1.42      thorpej   544:
1.148     yamt      545: done:
                    546:        *retval = (error != 0) ? 0 : (register_t)newva;
                    547:        return error;
1.24      fvdl      548: }
                    549:
                    550: int
1.190     dsl       551: linux_sys_mprotect(struct lwp *l, const struct linux_sys_mprotect_args *uap, register_t *retval)
1.103     christos  552: {
1.190     dsl       553:        /* {
1.103     christos  554:                syscallarg(const void *) start;
                    555:                syscallarg(unsigned long) len;
                    556:                syscallarg(int) prot;
1.190     dsl       557:        } */
1.103     christos  558:        struct vm_map_entry *entry;
1.141     chs       559:        struct vm_map *map;
                    560:        struct proc *p;
                    561:        vaddr_t end, start, len, stacklim;
                    562:        int prot, grows;
1.103     christos  563:
1.141     chs       564:        start = (vaddr_t)SCARG(uap, start);
1.103     christos  565:        len = round_page(SCARG(uap, len));
1.141     chs       566:        prot = SCARG(uap, prot);
                    567:        grows = prot & (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP);
                    568:        prot &= ~grows;
1.103     christos  569:        end = start + len;
                    570:
1.141     chs       571:        if (start & PAGE_MASK)
                    572:                return EINVAL;
1.103     christos  573:        if (end < start)
                    574:                return EINVAL;
1.141     chs       575:        if (end == start)
1.103     christos  576:                return 0;
                    577:
1.141     chs       578:        if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
                    579:                return EINVAL;
                    580:        if (grows == (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP))
1.103     christos  581:                return EINVAL;
                    582:
1.141     chs       583:        p = l->l_proc;
                    584:        map = &p->p_vmspace->vm_map;
1.103     christos  585:        vm_map_lock(map);
1.150     manu      586: # ifdef notdef
1.103     christos  587:        VM_MAP_RANGE_CHECK(map, start, end);
1.150     manu      588: # endif
1.103     christos  589:        if (!uvm_map_lookup_entry(map, start, &entry) || entry->start > start) {
                    590:                vm_map_unlock(map);
1.126     jdolecek  591:                return ENOMEM;
1.103     christos  592:        }
1.141     chs       593:
                    594:        /*
                    595:         * Approximate the behaviour of PROT_GROWS{DOWN,UP}.
                    596:         */
                    597:
                    598:        stacklim = (vaddr_t)p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_cur;
                    599:        if (grows & LINUX_PROT_GROWSDOWN) {
                    600:                if (USRSTACK - stacklim <= start && start < USRSTACK) {
                    601:                        start = USRSTACK - stacklim;
                    602:                } else {
                    603:                        start = entry->start;
                    604:                }
                    605:        } else if (grows & LINUX_PROT_GROWSUP) {
                    606:                if (USRSTACK <= end && end < USRSTACK + stacklim) {
                    607:                        end = USRSTACK + stacklim;
                    608:                } else {
                    609:                        end = entry->end;
                    610:                }
                    611:        }
1.103     christos  612:        vm_map_unlock(map);
                    613:        return uvm_map_protect(map, start, end, prot, FALSE);
1.1       fvdl      614: }
                    615:
                    616: /*
                    617:  * This code is partly stolen from src/lib/libc/compat-43/times.c
                    618:  */
                    619:
1.113     jdolecek  620: #define        CONVTCK(r)      (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
1.1       fvdl      621:
                    622: int
1.190     dsl       623: linux_sys_times(struct lwp *l, const struct linux_sys_times_args *uap, register_t *retval)
1.20      thorpej   624: {
1.190     dsl       625:        /* {
1.1       fvdl      626:                syscallarg(struct times *) tms;
1.190     dsl       627:        } */
1.116     thorpej   628:        struct proc *p = l->l_proc;
1.1       fvdl      629:        struct timeval t;
1.155     kardel    630:        int error;
1.1       fvdl      631:
1.112     jdolecek  632:        if (SCARG(uap, tms)) {
                    633:                struct linux_tms ltms;
                    634:                struct rusage ru;
                    635:
1.197     ad        636:                mutex_enter(p->p_lock);
1.166     ad        637:                calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
1.112     jdolecek  638:                ltms.ltms_utime = CONVTCK(ru.ru_utime);
                    639:                ltms.ltms_stime = CONVTCK(ru.ru_stime);
                    640:                ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
                    641:                ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
1.197     ad        642:                mutex_exit(p->p_lock);
1.1       fvdl      643:
1.112     jdolecek  644:                if ((error = copyout(&ltms, SCARG(uap, tms), sizeof ltms)))
                    645:                        return error;
                    646:        }
1.1       fvdl      647:
1.155     kardel    648:        getmicrouptime(&t);
1.1       fvdl      649:
                    650:        retval[0] = ((linux_clock_t)(CONVTCK(t)));
                    651:        return 0;
                    652: }
1.113     jdolecek  653:
                    654: #undef CONVTCK
1.1       fvdl      655:
                    656: /*
                    657:  * Linux 'readdir' call. This code is mostly taken from the
                    658:  * SunOS getdents call (see compat/sunos/sunos_misc.c), though
                    659:  * an attempt has been made to keep it a little cleaner (failing
                    660:  * miserably, because of the cruft needed if count 1 is passed).
                    661:  *
1.17      fvdl      662:  * The d_off field should contain the offset of the next valid entry,
                    663:  * but in Linux it has the offset of the entry itself. We emulate
                    664:  * that bug here.
                    665:  *
1.1       fvdl      666:  * Read in BSD-style entries, convert them, and copy them out.
                    667:  *
                    668:  * Note that this doesn't handle union-mounted filesystems.
                    669:  */
                    670: int
1.190     dsl       671: linux_sys_getdents(struct lwp *l, const struct linux_sys_getdents_args *uap, register_t *retval)
1.20      thorpej   672: {
1.190     dsl       673:        /* {
1.1       fvdl      674:                syscallarg(int) fd;
1.47      erh       675:                syscallarg(struct linux_dirent *) dent;
1.1       fvdl      676:                syscallarg(unsigned int) count;
1.190     dsl       677:        } */
1.69      augustss  678:        struct dirent *bdp;
1.1       fvdl      679:        struct vnode *vp;
1.167     christos  680:        char *inp, *tbuf;               /* BSD-format */
1.26      christos  681:        int len, reclen;                /* BSD-format */
1.167     christos  682:        char *outp;                     /* Linux-format */
1.26      christos  683:        int resid, linux_reclen = 0;    /* Linux-format */
1.1       fvdl      684:        struct file *fp;
                    685:        struct uio auio;
                    686:        struct iovec aiov;
                    687:        struct linux_dirent idb;
                    688:        off_t off;              /* true file offset */
1.17      fvdl      689:        int buflen, error, eofflag, nbytes, oldcall;
1.1       fvdl      690:        struct vattr va;
1.40      fvdl      691:        off_t *cookiebuf = NULL, *cookie;
1.22      mycroft   692:        int ncookies;
1.1       fvdl      693:
1.201     ad        694:        /* fd_getvnode() will use the descriptor for us */
                    695:        if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
1.1       fvdl      696:                return (error);
                    697:
1.54      thorpej   698:        if ((fp->f_flag & FREAD) == 0) {
                    699:                error = EBADF;
                    700:                goto out1;
                    701:        }
1.1       fvdl      702:
1.5       mycroft   703:        vp = (struct vnode *)fp->f_data;
1.54      thorpej   704:        if (vp->v_type != VDIR) {
                    705:                error = EINVAL;
                    706:                goto out1;
                    707:        }
1.1       fvdl      708:
1.187     pooka     709:        if ((error = VOP_GETATTR(vp, &va, l->l_cred)))
1.54      thorpej   710:                goto out1;
1.1       fvdl      711:
                    712:        nbytes = SCARG(uap, count);
1.17      fvdl      713:        if (nbytes == 1) {      /* emulating old, broken behaviour */
1.107     christos  714:                nbytes = sizeof (idb);
1.5       mycroft   715:                buflen = max(va.va_blocksize, nbytes);
1.17      fvdl      716:                oldcall = 1;
1.5       mycroft   717:        } else {
                    718:                buflen = min(MAXBSIZE, nbytes);
1.33      fvdl      719:                if (buflen < va.va_blocksize)
                    720:                        buflen = va.va_blocksize;
1.17      fvdl      721:                oldcall = 0;
1.1       fvdl      722:        }
1.138     christos  723:        tbuf = malloc(buflen, M_TEMP, M_WAITOK);
1.33      fvdl      724:
1.39      fvdl      725:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1       fvdl      726:        off = fp->f_offset;
                    727: again:
1.138     christos  728:        aiov.iov_base = tbuf;
1.1       fvdl      729:        aiov.iov_len = buflen;
                    730:        auio.uio_iov = &aiov;
                    731:        auio.uio_iovcnt = 1;
                    732:        auio.uio_rw = UIO_READ;
                    733:        auio.uio_resid = buflen;
                    734:        auio.uio_offset = off;
1.151     yamt      735:        UIO_SETUP_SYSSPACE(&auio);
1.1       fvdl      736:        /*
                    737:          * First we read into the malloc'ed buffer, then
                    738:          * we massage it into user space, one record at a time.
                    739:          */
1.39      fvdl      740:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
                    741:            &ncookies);
1.1       fvdl      742:        if (error)
                    743:                goto out;
                    744:
1.138     christos  745:        inp = tbuf;
1.167     christos  746:        outp = (void *)SCARG(uap, dent);
1.1       fvdl      747:        resid = nbytes;
1.35      fvdl      748:        if ((len = buflen - auio.uio_resid) == 0)
1.1       fvdl      749:                goto eof;
                    750:
1.22      mycroft   751:        for (cookie = cookiebuf; len > 0; len -= reclen) {
1.5       mycroft   752:                bdp = (struct dirent *)inp;
                    753:                reclen = bdp->d_reclen;
1.1       fvdl      754:                if (reclen & 3)
                    755:                        panic("linux_readdir");
                    756:                if (bdp->d_fileno == 0) {
                    757:                        inp += reclen;  /* it is a hole; squish it out */
1.136     christos  758:                        if (cookie)
                    759:                                off = *cookie++;
                    760:                        else
                    761:                                off += reclen;
1.1       fvdl      762:                        continue;
                    763:                }
1.21      mycroft   764:                linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen);
                    765:                if (reclen > len || resid < linux_reclen) {
1.1       fvdl      766:                        /* entry too big for buffer, so just stop */
                    767:                        outp++;
                    768:                        break;
                    769:                }
                    770:                /*
                    771:                 * Massage in place to make a Linux-shaped dirent (otherwise
                    772:                 * we have to worry about touching user memory outside of
                    773:                 * the copyout() call).
                    774:                 */
1.107     christos  775:                idb.d_ino = bdp->d_fileno;
1.17      fvdl      776:                /*
1.21      mycroft   777:                 * The old readdir() call misuses the offset and reclen fields.
1.17      fvdl      778:                 */
1.22      mycroft   779:                if (oldcall) {
                    780:                        idb.d_off = (linux_off_t)linux_reclen;
                    781:                        idb.d_reclen = (u_short)bdp->d_namlen;
                    782:                } else {
1.109     tron      783:                        if (sizeof (idb.d_off) <= 4 && (off >> 32) != 0) {
1.33      fvdl      784:                                compat_offseterr(vp, "linux_getdents");
                    785:                                error = EINVAL;
                    786:                                goto out;
                    787:                        }
1.22      mycroft   788:                        idb.d_off = (linux_off_t)off;
1.107     christos  789:                        idb.d_reclen = (u_short)linux_reclen;
                    790:                }
                    791:                strcpy(idb.d_name, bdp->d_name);
1.167     christos  792:                if ((error = copyout((void *)&idb, outp, linux_reclen)))
1.107     christos  793:                        goto out;
                    794:                /* advance past this real entry */
                    795:                inp += reclen;
1.136     christos  796:                if (cookie)
                    797:                        off = *cookie++; /* each entry points to itself */
                    798:                else
                    799:                        off += reclen;
1.107     christos  800:                /* advance output past Linux-shaped entry */
                    801:                outp += linux_reclen;
                    802:                resid -= linux_reclen;
                    803:                if (oldcall)
                    804:                        break;
                    805:        }
                    806:
                    807:        /* if we squished out the whole block, try again */
1.167     christos  808:        if (outp == (void *)SCARG(uap, dent))
1.107     christos  809:                goto again;
                    810:        fp->f_offset = off;     /* update the vnode offset */
                    811:
                    812:        if (oldcall)
                    813:                nbytes = resid + linux_reclen;
                    814:
                    815: eof:
                    816:        *retval = nbytes - resid;
                    817: out:
                    818:        VOP_UNLOCK(vp, 0);
                    819:        if (cookiebuf)
                    820:                free(cookiebuf, M_TEMP);
1.138     christos  821:        free(tbuf, M_TEMP);
1.107     christos  822: out1:
1.194     ad        823:        fd_putfile(SCARG(uap, fd));
1.1       fvdl      824:        return error;
                    825: }
                    826:
                    827: /*
1.17      fvdl      828:  * Even when just using registers to pass arguments to syscalls you can
                    829:  * have 5 of them on the i386. So this newer version of select() does
                    830:  * this.
1.1       fvdl      831:  */
                    832: int
1.190     dsl       833: linux_sys_select(struct lwp *l, const struct linux_sys_select_args *uap, register_t *retval)
1.20      thorpej   834: {
1.190     dsl       835:        /* {
1.17      fvdl      836:                syscallarg(int) nfds;
                    837:                syscallarg(fd_set *) readfds;
                    838:                syscallarg(fd_set *) writefds;
                    839:                syscallarg(fd_set *) exceptfds;
1.201.4.1  skrll     840:                syscallarg(struct timeval50 *) timeout;
1.190     dsl       841:        } */
1.20      thorpej   842:
1.116     thorpej   843:        return linux_select1(l, retval, SCARG(uap, nfds), SCARG(uap, readfds),
1.201.4.1  skrll     844:            SCARG(uap, writefds), SCARG(uap, exceptfds),
                    845:            (struct linux_timeval *)SCARG(uap, timeout));
1.17      fvdl      846: }
                    847:
                    848: /*
                    849:  * Common code for the old and new versions of select(). A couple of
                    850:  * things are important:
                    851:  * 1) return the amount of time left in the 'timeout' parameter
                    852:  * 2) select never returns ERESTART on Linux, always return EINTR
                    853:  */
                    854: int
1.116     thorpej   855: linux_select1(l, retval, nfds, readfds, writefds, exceptfds, timeout)
                    856:        struct lwp *l;
1.17      fvdl      857:        register_t *retval;
                    858:        int nfds;
                    859:        fd_set *readfds, *writefds, *exceptfds;
1.201.4.1  skrll     860:        struct linux_timeval *timeout;
1.17      fvdl      861: {
1.178     dsl       862:        struct timeval tv0, tv1, utv, *tv = NULL;
1.201.4.1  skrll     863:        struct linux_timeval ltv;
1.1       fvdl      864:        int error;
                    865:
1.7       fvdl      866:        /*
                    867:         * Store current time for computation of the amount of
                    868:         * time left.
                    869:         */
1.17      fvdl      870:        if (timeout) {
1.201.4.1  skrll     871:                if ((error = copyin(timeout, &ltv, sizeof(ltv))))
1.13      mycroft   872:                        return error;
1.201.4.1  skrll     873:                utv.tv_sec = ltv.tv_sec;
                    874:                utv.tv_usec = ltv.tv_usec;
1.13      mycroft   875:                if (itimerfix(&utv)) {
                    876:                        /*
                    877:                         * The timeval was invalid.  Convert it to something
                    878:                         * valid that will act as it does under Linux.
                    879:                         */
                    880:                        utv.tv_sec += utv.tv_usec / 1000000;
                    881:                        utv.tv_usec %= 1000000;
                    882:                        if (utv.tv_usec < 0) {
                    883:                                utv.tv_sec -= 1;
                    884:                                utv.tv_usec += 1000000;
                    885:                        }
                    886:                        if (utv.tv_sec < 0)
                    887:                                timerclear(&utv);
                    888:                }
1.178     dsl       889:                tv = &utv;
1.7       fvdl      890:                microtime(&tv0);
1.13      mycroft   891:        }
1.7       fvdl      892:
1.177     dsl       893:        error = selcommon(l, retval, nfds, readfds, writefds, exceptfds,
1.178     dsl       894:            tv, NULL);
1.177     dsl       895:
1.10      mycroft   896:        if (error) {
                    897:                /*
                    898:                 * See fs/select.c in the Linux kernel.  Without this,
                    899:                 * Maelstrom doesn't work.
                    900:                 */
                    901:                if (error == ERESTART)
                    902:                        error = EINTR;
1.7       fvdl      903:                return error;
1.10      mycroft   904:        }
1.7       fvdl      905:
1.17      fvdl      906:        if (timeout) {
1.14      mycroft   907:                if (*retval) {
1.7       fvdl      908:                        /*
1.13      mycroft   909:                         * Compute how much time was left of the timeout,
1.7       fvdl      910:                         * by subtracting the current time and the time
                    911:                         * before we started the call, and subtracting
                    912:                         * that result from the user-supplied value.
                    913:                         */
                    914:                        microtime(&tv1);
                    915:                        timersub(&tv1, &tv0, &tv1);
                    916:                        timersub(&utv, &tv1, &utv);
1.14      mycroft   917:                        if (utv.tv_sec < 0)
                    918:                                timerclear(&utv);
                    919:                } else
                    920:                        timerclear(&utv);
1.201.4.1  skrll     921:                ltv.tv_sec = utv.tv_sec;
                    922:                ltv.tv_usec = utv.tv_usec;
                    923:                if ((error = copyout(&ltv, timeout, sizeof(ltv))))
1.7       fvdl      924:                        return error;
                    925:        }
1.13      mycroft   926:
1.7       fvdl      927:        return 0;
1.1       fvdl      928: }
                    929:
                    930: /*
1.6       fvdl      931:  * Set the 'personality' (emulation mode) for the current process. Only
                    932:  * accept the Linux personality here (0). This call is needed because
                    933:  * the Linux ELF crt0 issues it in an ugly kludge to make sure that
                    934:  * ELF binaries run in Linux mode, not SVR4 mode.
                    935:  */
                    936: int
1.190     dsl       937: linux_sys_personality(struct lwp *l, const struct linux_sys_personality_args *uap, register_t *retval)
1.20      thorpej   938: {
1.190     dsl       939:        /* {
1.6       fvdl      940:                syscallarg(int) per;
1.190     dsl       941:        } */
1.20      thorpej   942:
1.201.4.2! skrll     943:        switch (SCARG(uap, per)) {
        !           944:        case LINUX_PER_LINUX:
        !           945:        case LINUX_PER_QUERY:
        !           946:                break;
        !           947:        default:
1.6       fvdl      948:                return EINVAL;
1.201.4.2! skrll     949:        }
        !           950:
        !           951:        retval[0] = LINUX_PER_LINUX;
1.1       fvdl      952:        return 0;
1.18      fvdl      953: }
1.81      fvdl      954:
1.63      abs       955: /*
1.64      abs       956:  * We have nonexistent fsuid equal to uid.
                    957:  * If modification is requested, refuse.
1.63      abs       958:  */
                    959: int
1.190     dsl       960: linux_sys_setfsuid(struct lwp *l, const struct linux_sys_setfsuid_args *uap, register_t *retval)
1.63      abs       961: {
1.190     dsl       962:         /* {
1.63      abs       963:                 syscallarg(uid_t) uid;
1.190     dsl       964:         } */
1.63      abs       965:         uid_t uid;
                    966:
                    967:         uid = SCARG(uap, uid);
1.158     ad        968:         if (kauth_cred_getuid(l->l_cred) != uid)
1.190     dsl       969:                 return sys_nosys(l, uap, retval);
1.191     njoly     970:
                    971:         *retval = uid;
                    972:         return 0;
1.63      abs       973: }
                    974:
                    975: int
1.191     njoly     976: linux_sys_setfsgid(struct lwp *l, const struct linux_sys_setfsgid_args *uap, register_t *retval)
1.63      abs       977: {
1.191     njoly     978:        /* {
                    979:                syscallarg(gid_t) gid;
                    980:        } */
                    981:        gid_t gid;
                    982:
                    983:        gid = SCARG(uap, gid);
                    984:        if (kauth_cred_getgid(l->l_cred) != gid)
                    985:                return sys_nosys(l, uap, retval);
                    986:
                    987:        *retval = gid;
                    988:        return 0;
1.27      fvdl      989: }
                    990:
                    991: int
1.190     dsl       992: linux_sys_setresuid(struct lwp *l, const struct linux_sys_setresuid_args *uap, register_t *retval)
1.57      thorpej   993: {
1.190     dsl       994:        /* {
1.57      thorpej   995:                syscallarg(uid_t) ruid;
                    996:                syscallarg(uid_t) euid;
                    997:                syscallarg(uid_t) suid;
1.190     dsl       998:        } */
1.57      thorpej   999:
                   1000:        /*
                   1001:         * Note: These checks are a little different than the NetBSD
                   1002:         * setreuid(2) call performs.  This precisely follows the
                   1003:         * behavior of the Linux kernel.
                   1004:         */
                   1005:
1.117     dsl      1006:        return do_setresuid(l, SCARG(uap, ruid), SCARG(uap, euid),
                   1007:                            SCARG(uap, suid),
                   1008:                            ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S |
                   1009:                            ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
                   1010:                            ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S );
1.57      thorpej  1011: }
                   1012:
                   1013: int
1.190     dsl      1014: linux_sys_getresuid(struct lwp *l, const struct linux_sys_getresuid_args *uap, register_t *retval)
1.57      thorpej  1015: {
1.190     dsl      1016:        /* {
1.57      thorpej  1017:                syscallarg(uid_t *) ruid;
                   1018:                syscallarg(uid_t *) euid;
                   1019:                syscallarg(uid_t *) suid;
1.190     dsl      1020:        } */
1.158     ad       1021:        kauth_cred_t pc = l->l_cred;
1.57      thorpej  1022:        int error;
1.154     elad     1023:        uid_t uid;
1.57      thorpej  1024:
                   1025:        /*
                   1026:         * Linux copies these values out to userspace like so:
                   1027:         *
                   1028:         *      1. Copy out ruid.
                   1029:         *      2. If that succeeds, copy out euid.
                   1030:         *      3. If both of those succeed, copy out suid.
                   1031:         */
1.154     elad     1032:        uid = kauth_cred_getuid(pc);
                   1033:        if ((error = copyout(&uid, SCARG(uap, ruid), sizeof(uid_t))) != 0)
1.57      thorpej  1034:                return (error);
                   1035:
1.154     elad     1036:        uid = kauth_cred_geteuid(pc);
                   1037:        if ((error = copyout(&uid, SCARG(uap, euid), sizeof(uid_t))) != 0)
1.57      thorpej  1038:                return (error);
                   1039:
1.154     elad     1040:        uid = kauth_cred_getsvuid(pc);
                   1041:
                   1042:        return (copyout(&uid, SCARG(uap, suid), sizeof(uid_t)));
1.78      fvdl     1043: }
1.62      tron     1044:
                   1045: int
1.190     dsl      1046: linux_sys_ptrace(struct lwp *l, const struct linux_sys_ptrace_args *uap, register_t *retval)
1.62      tron     1047: {
1.190     dsl      1048:        /* {
1.88      manu     1049:                i386, m68k, powerpc: T=int
1.137     manu     1050:                alpha, amd64: T=long
1.66      erh      1051:                syscallarg(T) request;
                   1052:                syscallarg(T) pid;
                   1053:                syscallarg(T) addr;
                   1054:                syscallarg(T) data;
1.190     dsl      1055:        } */
1.73      jdolecek 1056:        const int *ptr;
                   1057:        int request;
1.89      manu     1058:        int error;
1.62      tron     1059:
                   1060:        ptr = linux_ptrace_request_map;
                   1061:        request = SCARG(uap, request);
                   1062:        while (*ptr != -1)
                   1063:                if (*ptr++ == request) {
                   1064:                        struct sys_ptrace_args pta;
                   1065:
                   1066:                        SCARG(&pta, req) = *ptr;
                   1067:                        SCARG(&pta, pid) = SCARG(uap, pid);
1.167     christos 1068:                        SCARG(&pta, addr) = (void *)SCARG(uap, addr);
1.62      tron     1069:                        SCARG(&pta, data) = SCARG(uap, data);
                   1070:
1.73      jdolecek 1071:                        /*
                   1072:                         * Linux ptrace(PTRACE_CONT, pid, 0, 0) means actually
1.90      jdolecek 1073:                         * to continue where the process left off previously.
1.201.4.1  skrll    1074:                         * The same thing is achieved by addr == (void *) 1
1.90      jdolecek 1075:                         * on NetBSD, so rewrite 'addr' appropriately.
1.73      jdolecek 1076:                         */
                   1077:                        if (request == LINUX_PTRACE_CONT && SCARG(uap, addr)==0)
1.167     christos 1078:                                SCARG(&pta, addr) = (void *) 1;
1.135     perry    1079:
1.201.4.1  skrll    1080:                        error = sysent[SYS_ptrace].sy_call(l, &pta, retval);
1.135     perry    1081:                        if (error)
1.92      manu     1082:                                return error;
                   1083:                        switch (request) {
                   1084:                        case LINUX_PTRACE_PEEKTEXT:
                   1085:                        case LINUX_PTRACE_PEEKDATA:
1.135     perry    1086:                                error = copyout (retval,
1.167     christos 1087:                                    (void *)SCARG(uap, data),
1.137     manu     1088:                                    sizeof *retval);
1.92      manu     1089:                                *retval = SCARG(uap, data);
                   1090:                                break;
1.135     perry    1091:                        default:
1.92      manu     1092:                                break;
                   1093:                        }
1.89      manu     1094:                        return error;
1.62      tron     1095:                }
                   1096:                else
                   1097:                        ptr++;
                   1098:
1.116     thorpej  1099:        return LINUX_SYS_PTRACE_ARCH(l, uap, retval);
1.1       fvdl     1100: }
1.67      erh      1101:
                   1102: int
1.190     dsl      1103: linux_sys_reboot(struct lwp *l, const struct linux_sys_reboot_args *uap, register_t *retval)
1.67      erh      1104: {
1.190     dsl      1105:        /* {
1.67      erh      1106:                syscallarg(int) magic1;
                   1107:                syscallarg(int) magic2;
                   1108:                syscallarg(int) cmd;
                   1109:                syscallarg(void *) arg;
1.190     dsl      1110:        } */
1.67      erh      1111:        struct sys_reboot_args /* {
                   1112:                syscallarg(int) opt;
                   1113:                syscallarg(char *) bootstr;
                   1114:        } */ sra;
                   1115:        int error;
                   1116:
1.164     elad     1117:        if ((error = kauth_authorize_system(l->l_cred,
                   1118:            KAUTH_SYSTEM_REBOOT, 0, NULL, NULL, NULL)) != 0)
1.67      erh      1119:                return(error);
                   1120:
                   1121:        if (SCARG(uap, magic1) != LINUX_REBOOT_MAGIC1)
                   1122:                return(EINVAL);
                   1123:        if (SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2 &&
                   1124:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2A &&
                   1125:            SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2B)
                   1126:                return(EINVAL);
                   1127:
1.200     gmcgarry 1128:        switch ((unsigned long)SCARG(uap, cmd)) {
1.67      erh      1129:        case LINUX_REBOOT_CMD_RESTART:
                   1130:                SCARG(&sra, opt) = RB_AUTOBOOT;
                   1131:                break;
                   1132:        case LINUX_REBOOT_CMD_HALT:
                   1133:                SCARG(&sra, opt) = RB_HALT;
                   1134:                break;
                   1135:        case LINUX_REBOOT_CMD_POWER_OFF:
                   1136:                SCARG(&sra, opt) = RB_HALT|RB_POWERDOWN;
                   1137:                break;
                   1138:        case LINUX_REBOOT_CMD_RESTART2:
                   1139:                /* Reboot with an argument. */
                   1140:                SCARG(&sra, opt) = RB_AUTOBOOT|RB_STRING;
                   1141:                SCARG(&sra, bootstr) = SCARG(uap, arg);
                   1142:                break;
                   1143:        case LINUX_REBOOT_CMD_CAD_ON:
                   1144:                return(EINVAL); /* We don't implement ctrl-alt-delete */
                   1145:        case LINUX_REBOOT_CMD_CAD_OFF:
                   1146:                return(0);
                   1147:        default:
                   1148:                return(EINVAL);
                   1149:        }
                   1150:
1.116     thorpej  1151:        return(sys_reboot(l, &sra, retval));
1.75      jdolecek 1152: }
                   1153:
                   1154: /*
                   1155:  * Copy of compat_12_sys_swapon().
                   1156:  */
                   1157: int
1.190     dsl      1158: linux_sys_swapon(struct lwp *l, const struct linux_sys_swapon_args *uap, register_t *retval)
1.75      jdolecek 1159: {
1.190     dsl      1160:        /* {
                   1161:                syscallarg(const char *) name;
                   1162:        } */
1.75      jdolecek 1163:        struct sys_swapctl_args ua;
                   1164:
                   1165:        SCARG(&ua, cmd) = SWAP_ON;
1.139     drochner 1166:        SCARG(&ua, arg) = (void *)__UNCONST(SCARG(uap, name));
1.75      jdolecek 1167:        SCARG(&ua, misc) = 0;   /* priority */
1.116     thorpej  1168:        return (sys_swapctl(l, &ua, retval));
1.76      jdolecek 1169: }
                   1170:
                   1171: /*
                   1172:  * Stop swapping to the file or block device specified by path.
                   1173:  */
                   1174: int
1.190     dsl      1175: linux_sys_swapoff(struct lwp *l, const struct linux_sys_swapoff_args *uap, register_t *retval)
1.76      jdolecek 1176: {
1.190     dsl      1177:        /* {
                   1178:                syscallarg(const char *) path;
                   1179:        } */
1.76      jdolecek 1180:        struct sys_swapctl_args ua;
                   1181:
                   1182:        SCARG(&ua, cmd) = SWAP_OFF;
1.138     christos 1183:        SCARG(&ua, arg) = __UNCONST(SCARG(uap, path)); /*XXXUNCONST*/
1.116     thorpej  1184:        return (sys_swapctl(l, &ua, retval));
1.75      jdolecek 1185: }
                   1186:
                   1187: /*
                   1188:  * Copy of compat_09_sys_setdomainname()
                   1189:  */
                   1190: /* ARGSUSED */
                   1191: int
1.190     dsl      1192: linux_sys_setdomainname(struct lwp *l, const struct linux_sys_setdomainname_args *uap, register_t *retval)
1.75      jdolecek 1193: {
1.190     dsl      1194:        /* {
1.75      jdolecek 1195:                syscallarg(char *) domainname;
                   1196:                syscallarg(int) len;
1.190     dsl      1197:        } */
1.122     atatat   1198:        int name[2];
1.75      jdolecek 1199:
1.122     atatat   1200:        name[0] = CTL_KERN;
                   1201:        name[1] = KERN_DOMAINNAME;
                   1202:        return (old_sysctl(&name[0], 2, 0, 0, SCARG(uap, domainname),
                   1203:                            SCARG(uap, len), l));
1.77      augustss 1204: }
                   1205:
                   1206: /*
                   1207:  * sysinfo()
                   1208:  */
                   1209: /* ARGSUSED */
                   1210: int
1.190     dsl      1211: linux_sys_sysinfo(struct lwp *l, const struct linux_sys_sysinfo_args *uap, register_t *retval)
1.77      augustss 1212: {
1.190     dsl      1213:        /* {
1.77      augustss 1214:                syscallarg(struct linux_sysinfo *) arg;
1.190     dsl      1215:        } */
1.77      augustss 1216:        struct linux_sysinfo si;
                   1217:        struct loadavg *la;
                   1218:
1.155     kardel   1219:        si.uptime = time_uptime;
1.77      augustss 1220:        la = &averunnable;
                   1221:        si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1222:        si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
                   1223:        si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
1.162     manu     1224:        si.totalram = ctob((u_long)physmem);
                   1225:        si.freeram = (u_long)uvmexp.free * uvmexp.pagesize;
1.77      augustss 1226:        si.sharedram = 0;       /* XXX */
1.162     manu     1227:        si.bufferram = (u_long)uvmexp.filepages * uvmexp.pagesize;
                   1228:        si.totalswap = (u_long)uvmexp.swpages * uvmexp.pagesize;
                   1229:        si.freeswap =
                   1230:            (u_long)(uvmexp.swpages - uvmexp.swpginuse) * uvmexp.pagesize;
1.77      augustss 1231:        si.procs = nprocs;
                   1232:
                   1233:        /* The following are only present in newer Linux kernels. */
                   1234:        si.totalbig = 0;
                   1235:        si.freebig = 0;
                   1236:        si.mem_unit = 1;
                   1237:
                   1238:        return (copyout(&si, SCARG(uap, arg), sizeof si));
1.97      christos 1239: }
                   1240:
                   1241: int
1.190     dsl      1242: linux_sys_getrlimit(struct lwp *l, const struct linux_sys_getrlimit_args *uap, register_t *retval)
1.97      christos 1243: {
1.190     dsl      1244:        /* {
1.97      christos 1245:                syscallarg(int) which;
1.150     manu     1246: # ifdef LINUX_LARGEFILE64
1.144     manu     1247:                syscallarg(struct rlimit *) rlp;
1.150     manu     1248: # else
1.97      christos 1249:                syscallarg(struct orlimit *) rlp;
1.150     manu     1250: # endif
1.190     dsl      1251:        } */
1.150     manu     1252: # ifdef LINUX_LARGEFILE64
1.144     manu     1253:        struct rlimit orl;
1.150     manu     1254: # else
1.97      christos 1255:        struct orlimit orl;
1.150     manu     1256: # endif
1.176     dsl      1257:        int which;
                   1258:
                   1259:        which = linux_to_bsd_limit(SCARG(uap, which));
                   1260:        if (which < 0)
                   1261:                return -which;
1.97      christos 1262:
1.176     dsl      1263:        bsd_to_linux_rlimit(&orl, &l->l_proc->p_rlimit[which]);
1.146     rpaulo   1264:
1.97      christos 1265:        return copyout(&orl, SCARG(uap, rlp), sizeof(orl));
                   1266: }
                   1267:
                   1268: int
1.190     dsl      1269: linux_sys_setrlimit(struct lwp *l, const struct linux_sys_setrlimit_args *uap, register_t *retval)
1.97      christos 1270: {
1.190     dsl      1271:        /* {
1.97      christos 1272:                syscallarg(int) which;
1.150     manu     1273: # ifdef LINUX_LARGEFILE64
1.144     manu     1274:                syscallarg(struct rlimit *) rlp;
1.150     manu     1275: # else
1.97      christos 1276:                syscallarg(struct orlimit *) rlp;
1.150     manu     1277: # endif
1.190     dsl      1278:        } */
1.97      christos 1279:        struct rlimit rl;
1.150     manu     1280: # ifdef LINUX_LARGEFILE64
1.144     manu     1281:        struct rlimit orl;
1.150     manu     1282: # else
1.97      christos 1283:        struct orlimit orl;
1.150     manu     1284: # endif
1.97      christos 1285:        int error;
1.176     dsl      1286:        int which;
1.97      christos 1287:
                   1288:        if ((error = copyin(SCARG(uap, rlp), &orl, sizeof(orl))) != 0)
                   1289:                return error;
1.176     dsl      1290:
                   1291:        which = linux_to_bsd_limit(SCARG(uap, which));
                   1292:        if (which < 0)
                   1293:                return -which;
                   1294:
1.97      christos 1295:        linux_to_bsd_rlimit(&rl, &orl);
1.176     dsl      1296:        return dosetrlimit(l, l->l_proc, which, &rl);
1.97      christos 1297: }
                   1298:
1.150     manu     1299: # if !defined(__mips__) && !defined(__amd64__)
1.98      rafal    1300: /* XXX: this doesn't look 100% common, at least mips doesn't have it */
1.97      christos 1301: int
1.190     dsl      1302: linux_sys_ugetrlimit(struct lwp *l, const struct linux_sys_ugetrlimit_args *uap, register_t *retval)
1.97      christos 1303: {
1.190     dsl      1304:        return linux_sys_getrlimit(l, (const void *)uap, retval);
1.87      jdolecek 1305: }
1.150     manu     1306: # endif
1.87      jdolecek 1307:
                   1308: /*
                   1309:  * This gets called for unsupported syscalls. The difference to sys_nosys()
                   1310:  * is that process does not get SIGSYS, the call just returns with ENOSYS.
                   1311:  * This is the way Linux does it and glibc depends on this behaviour.
                   1312:  */
                   1313: int
1.190     dsl      1314: linux_sys_nosys(struct lwp *l, const void *v, register_t *retval)
1.87      jdolecek 1315: {
                   1316:        return (ENOSYS);
1.67      erh      1317: }
1.150     manu     1318:
1.156     christos 1319: int
1.190     dsl      1320: linux_sys_getpriority(struct lwp *l, const struct linux_sys_getpriority_args *uap, register_t *retval)
1.156     christos 1321: {
1.190     dsl      1322:         /* {
1.156     christos 1323:                 syscallarg(int) which;
                   1324:                 syscallarg(int) who;
1.190     dsl      1325:         } */
1.156     christos 1326:         struct sys_getpriority_args bsa;
                   1327:         int error;
                   1328:
                   1329:         SCARG(&bsa, which) = SCARG(uap, which);
                   1330:         SCARG(&bsa, who) = SCARG(uap, who);
                   1331:
                   1332:         if ((error = sys_getpriority(l, &bsa, retval)))
                   1333:                 return error;
                   1334:
1.157     christos 1335:         *retval = NZERO - *retval;
1.156     christos 1336:
                   1337:         return 0;
                   1338: }
                   1339:
1.150     manu     1340: #endif /* !COMPAT_LINUX32 */

CVSweb <webmaster@jp.NetBSD.org>