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, <mp);
320: error = copyout(<mp, 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, <mp);
342: error = copyout(<mp, 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(<ms, 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, <v, 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(<v, 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>