1 1.267 riastrad /* $NetBSD: linux_misc.c,v 1.267 2024/10/01 16:41:29 riastradh Exp $ */ 2 1.47 erh 3 1.47 erh /*- 4 1.194 ad * Copyright (c) 1995, 1998, 1999, 2008 The NetBSD Foundation, Inc. 5 1.47 erh * All rights reserved. 6 1.47 erh * 7 1.47 erh * This code is derived from software contributed to The NetBSD Foundation 8 1.56 thorpej * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe 9 1.56 thorpej * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center. 10 1.47 erh * 11 1.47 erh * Redistribution and use in source and binary forms, with or without 12 1.47 erh * modification, are permitted provided that the following conditions 13 1.47 erh * are met: 14 1.47 erh * 1. Redistributions of source code must retain the above copyright 15 1.47 erh * notice, this list of conditions and the following disclaimer. 16 1.47 erh * 2. Redistributions in binary form must reproduce the above copyright 17 1.47 erh * notice, this list of conditions and the following disclaimer in the 18 1.47 erh * documentation and/or other materials provided with the distribution. 19 1.47 erh * 20 1.47 erh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.47 erh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.47 erh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.47 erh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.47 erh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.47 erh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.47 erh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.47 erh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.47 erh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.47 erh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.47 erh * POSSIBILITY OF SUCH DAMAGE. 31 1.1 fvdl */ 32 1.1 fvdl 33 1.1 fvdl /* 34 1.1 fvdl * Linux compatibility module. Try to deal with various Linux system calls. 35 1.1 fvdl */ 36 1.1 fvdl 37 1.47 erh /* 38 1.47 erh * These functions have been moved to multiarch to allow 39 1.135 perry * selection of which machines include them to be 40 1.47 erh * determined by the individual files.linux_<arch> files. 41 1.47 erh * 42 1.47 erh * Function in multiarch: 43 1.47 erh * linux_sys_break : linux_break.c 44 1.47 erh * linux_sys_alarm : linux_misc_notalpha.c 45 1.57 thorpej * linux_sys_getresgid : linux_misc_notalpha.c 46 1.47 erh * linux_sys_nice : linux_misc_notalpha.c 47 1.47 erh * linux_sys_readdir : linux_misc_notalpha.c 48 1.57 thorpej * linux_sys_setresgid : linux_misc_notalpha.c 49 1.47 erh * linux_sys_time : linux_misc_notalpha.c 50 1.47 erh * linux_sys_utime : linux_misc_notalpha.c 51 1.47 erh * linux_sys_waitpid : linux_misc_notalpha.c 52 1.47 erh * linux_sys_old_mmap : linux_oldmmap.c 53 1.47 erh * linux_sys_oldolduname : linux_oldolduname.c 54 1.47 erh * linux_sys_oldselect : linux_oldselect.c 55 1.47 erh * linux_sys_olduname : linux_olduname.c 56 1.47 erh * linux_sys_pipe : linux_pipe.c 57 1.47 erh */ 58 1.95 lukem 59 1.95 lukem #include <sys/cdefs.h> 60 1.267 riastrad __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.267 2024/10/01 16:41:29 riastradh Exp $"); 61 1.47 erh 62 1.1 fvdl #include <sys/param.h> 63 1.1 fvdl #include <sys/systm.h> 64 1.1 fvdl #include <sys/namei.h> 65 1.1 fvdl #include <sys/proc.h> 66 1.29 mycroft #include <sys/dirent.h> 67 1.258 christos #include <sys/epoll.h> 68 1.253 thorpej #include <sys/eventfd.h> 69 1.1 fvdl #include <sys/file.h> 70 1.1 fvdl #include <sys/stat.h> 71 1.1 fvdl #include <sys/filedesc.h> 72 1.1 fvdl #include <sys/ioctl.h> 73 1.1 fvdl #include <sys/kernel.h> 74 1.1 fvdl #include <sys/malloc.h> 75 1.1 fvdl #include <sys/mbuf.h> 76 1.1 fvdl #include <sys/mman.h> 77 1.1 fvdl #include <sys/mount.h> 78 1.220 pooka #include <sys/poll.h> 79 1.179 dsl #include <sys/prot.h> 80 1.67 erh #include <sys/reboot.h> 81 1.1 fvdl #include <sys/resource.h> 82 1.1 fvdl #include <sys/resourcevar.h> 83 1.177 dsl #include <sys/select.h> 84 1.1 fvdl #include <sys/signal.h> 85 1.1 fvdl #include <sys/signalvar.h> 86 1.1 fvdl #include <sys/socket.h> 87 1.1 fvdl #include <sys/time.h> 88 1.1 fvdl #include <sys/times.h> 89 1.1 fvdl #include <sys/vnode.h> 90 1.1 fvdl #include <sys/uio.h> 91 1.1 fvdl #include <sys/wait.h> 92 1.1 fvdl #include <sys/utsname.h> 93 1.1 fvdl #include <sys/unistd.h> 94 1.172 dsl #include <sys/vfs_syscalls.h> 95 1.75 jdolecek #include <sys/swap.h> /* for SWAP_ON */ 96 1.75 jdolecek #include <sys/sysctl.h> /* for KERN_DOMAINNAME */ 97 1.154 elad #include <sys/kauth.h> 98 1.249 thorpej #include <sys/futex.h> 99 1.1 fvdl 100 1.73 jdolecek #include <sys/ptrace.h> 101 1.73 jdolecek #include <machine/ptrace.h> 102 1.73 jdolecek 103 1.161 matt #include <sys/syscall.h> 104 1.1 fvdl #include <sys/syscallargs.h> 105 1.1 fvdl 106 1.204 njoly #include <compat/sys/resource.h> 107 1.204 njoly 108 1.143 manu #include <compat/linux/common/linux_machdep.h> 109 1.49 christos #include <compat/linux/common/linux_types.h> 110 1.49 christos #include <compat/linux/common/linux_signal.h> 111 1.184 njoly #include <compat/linux/common/linux_ipc.h> 112 1.184 njoly #include <compat/linux/common/linux_sem.h> 113 1.49 christos 114 1.49 christos #include <compat/linux/common/linux_fcntl.h> 115 1.49 christos #include <compat/linux/common/linux_mmap.h> 116 1.49 christos #include <compat/linux/common/linux_dirent.h> 117 1.49 christos #include <compat/linux/common/linux_util.h> 118 1.49 christos #include <compat/linux/common/linux_misc.h> 119 1.170 njoly #include <compat/linux/common/linux_statfs.h> 120 1.150 manu #include <compat/linux/common/linux_limit.h> 121 1.62 tron #include <compat/linux/common/linux_ptrace.h> 122 1.67 erh #include <compat/linux/common/linux_reboot.h> 123 1.84 manu #include <compat/linux/common/linux_emuldata.h> 124 1.220 pooka #include <compat/linux/common/linux_sched.h> 125 1.49 christos 126 1.216 chs #include <compat/linux/linux_syscallargs.h> 127 1.216 chs 128 1.73 jdolecek const int linux_ptrace_request_map[] = { 129 1.62 tron LINUX_PTRACE_TRACEME, PT_TRACE_ME, 130 1.62 tron LINUX_PTRACE_PEEKTEXT, PT_READ_I, 131 1.62 tron LINUX_PTRACE_PEEKDATA, PT_READ_D, 132 1.62 tron LINUX_PTRACE_POKETEXT, PT_WRITE_I, 133 1.62 tron LINUX_PTRACE_POKEDATA, PT_WRITE_D, 134 1.62 tron LINUX_PTRACE_CONT, PT_CONTINUE, 135 1.62 tron LINUX_PTRACE_KILL, PT_KILL, 136 1.62 tron LINUX_PTRACE_ATTACH, PT_ATTACH, 137 1.62 tron LINUX_PTRACE_DETACH, PT_DETACH, 138 1.150 manu # ifdef PT_STEP 139 1.73 jdolecek LINUX_PTRACE_SINGLESTEP, PT_STEP, 140 1.150 manu # endif 141 1.170 njoly LINUX_PTRACE_SYSCALL, PT_SYSCALL, 142 1.62 tron -1 143 1.62 tron }; 144 1.1 fvdl 145 1.132 jdolecek const struct linux_mnttypes linux_fstypes[] = { 146 1.101 christos { MOUNT_FFS, LINUX_DEFAULT_SUPER_MAGIC }, 147 1.101 christos { MOUNT_NFS, LINUX_NFS_SUPER_MAGIC }, 148 1.101 christos { MOUNT_MFS, LINUX_DEFAULT_SUPER_MAGIC }, 149 1.101 christos { MOUNT_MSDOS, LINUX_MSDOS_SUPER_MAGIC }, 150 1.101 christos { MOUNT_LFS, LINUX_DEFAULT_SUPER_MAGIC }, 151 1.101 christos { MOUNT_FDESC, LINUX_DEFAULT_SUPER_MAGIC }, 152 1.101 christos { MOUNT_NULL, LINUX_DEFAULT_SUPER_MAGIC }, 153 1.135 perry { MOUNT_OVERLAY, LINUX_DEFAULT_SUPER_MAGIC }, 154 1.101 christos { MOUNT_UMAP, LINUX_DEFAULT_SUPER_MAGIC }, 155 1.101 christos { MOUNT_KERNFS, LINUX_DEFAULT_SUPER_MAGIC }, 156 1.101 christos { MOUNT_PROCFS, LINUX_PROC_SUPER_MAGIC }, 157 1.101 christos { MOUNT_AFS, LINUX_DEFAULT_SUPER_MAGIC }, 158 1.101 christos { MOUNT_CD9660, LINUX_ISOFS_SUPER_MAGIC }, 159 1.101 christos { MOUNT_UNION, LINUX_DEFAULT_SUPER_MAGIC }, 160 1.101 christos { MOUNT_ADOSFS, LINUX_ADFS_SUPER_MAGIC }, 161 1.101 christos { MOUNT_EXT2FS, LINUX_EXT2_SUPER_MAGIC }, 162 1.101 christos { MOUNT_CFS, LINUX_DEFAULT_SUPER_MAGIC }, 163 1.101 christos { MOUNT_CODA, LINUX_CODA_SUPER_MAGIC }, 164 1.101 christos { MOUNT_FILECORE, LINUX_DEFAULT_SUPER_MAGIC }, 165 1.101 christos { MOUNT_NTFS, LINUX_DEFAULT_SUPER_MAGIC }, 166 1.134 christos { MOUNT_SMBFS, LINUX_SMB_SUPER_MAGIC }, 167 1.140 jmmv { MOUNT_PTYFS, LINUX_DEVPTS_SUPER_MAGIC }, 168 1.199 njoly { MOUNT_TMPFS, LINUX_TMPFS_SUPER_MAGIC } 169 1.101 christos }; 170 1.132 jdolecek const int linux_fstypes_cnt = sizeof(linux_fstypes) / sizeof(linux_fstypes[0]); 171 1.101 christos 172 1.265 christos #ifdef DEBUG_LINUX 173 1.265 christos #define DPRINTF(a, ...) uprintf(a, __VA_ARGS__) 174 1.265 christos #else 175 1.265 christos #define DPRINTF(a, ...) 176 1.265 christos #endif 177 1.104 christos 178 1.47 erh /* Local linux_misc.c functions: */ 179 1.188 dsl static void linux_to_bsd_mmap_args(struct sys_mmap_args *, 180 1.188 dsl const struct linux_sys_mmap_args *); 181 1.190 dsl static int linux_mmap(struct lwp *, const struct linux_sys_mmap_args *, 182 1.188 dsl register_t *, off_t); 183 1.262 christos static int linux_to_native_wait_options(int); 184 1.26 christos 185 1.1 fvdl /* 186 1.1 fvdl * The information on a terminated (or stopped) process needs 187 1.1 fvdl * to be converted in order for Linux binaries to get a valid signal 188 1.1 fvdl * number out of it. 189 1.1 fvdl */ 190 1.173 dsl int 191 1.173 dsl bsd_to_linux_wstat(int st) 192 1.1 fvdl { 193 1.21 mycroft 194 1.52 christos int sig; 195 1.52 christos 196 1.173 dsl if (WIFSIGNALED(st)) { 197 1.173 dsl sig = WTERMSIG(st); 198 1.52 christos if (sig >= 0 && sig < NSIG) 199 1.173 dsl st= (st & ~0177) | native_to_linux_signo[sig]; 200 1.173 dsl } else if (WIFSTOPPED(st)) { 201 1.173 dsl sig = WSTOPSIG(st); 202 1.52 christos if (sig >= 0 && sig < NSIG) 203 1.173 dsl st = (st & ~0xff00) | 204 1.105 christos (native_to_linux_signo[sig] << 8); 205 1.52 christos } 206 1.173 dsl return st; 207 1.1 fvdl } 208 1.1 fvdl 209 1.1 fvdl /* 210 1.133 erh * wait4(2). Passed on to the NetBSD call, surrounded by code to 211 1.133 erh * reserve some space for a NetBSD-style wait status, and converting 212 1.133 erh * it to what Linux wants. 213 1.1 fvdl */ 214 1.1 fvdl int 215 1.190 dsl linux_sys_wait4(struct lwp *l, const struct linux_sys_wait4_args *uap, register_t *retval) 216 1.20 thorpej { 217 1.190 dsl /* { 218 1.1 fvdl syscallarg(int) pid; 219 1.1 fvdl syscallarg(int *) status; 220 1.1 fvdl syscallarg(int) options; 221 1.204 njoly syscallarg(struct rusage50 *) rusage; 222 1.190 dsl } */ 223 1.210 rmind int error, status, options, linux_options, pid = SCARG(uap, pid); 224 1.210 rmind struct rusage50 ru50; 225 1.173 dsl struct rusage ru; 226 1.196 ad proc_t *p; 227 1.1 fvdl 228 1.55 thorpej linux_options = SCARG(uap, options); 229 1.133 erh if (linux_options & ~(LINUX_WAIT4_KNOWNFLAGS)) 230 1.55 thorpej return (EINVAL); 231 1.55 thorpej 232 1.262 christos options = linux_to_native_wait_options(linux_options); 233 1.150 manu # ifdef DIAGNOSTIC 234 1.262 christos if (linux_options & LINUX_WNOTHREAD) 235 1.133 erh printf("WARNING: %s: linux process %d.%d called " 236 1.244 maxv "waitpid with __WNOTHREAD set!\n", 237 1.173 dsl __FILE__, l->l_proc->p_pid, l->l_lid); 238 1.133 erh 239 1.150 manu # endif 240 1.55 thorpej 241 1.210 rmind error = do_sys_wait(&pid, &status, options, 242 1.210 rmind SCARG(uap, rusage) != NULL ? &ru : NULL); 243 1.1 fvdl 244 1.190 dsl retval[0] = pid; 245 1.190 dsl if (pid == 0) 246 1.1 fvdl return error; 247 1.1 fvdl 248 1.210 rmind p = curproc; 249 1.210 rmind mutex_enter(p->p_lock); 250 1.196 ad sigdelset(&p->p_sigpend.sp_set, SIGCHLD); /* XXXAD ksiginfo leak */ 251 1.210 rmind mutex_exit(p->p_lock); 252 1.18 fvdl 253 1.204 njoly if (SCARG(uap, rusage) != NULL) { 254 1.204 njoly rusage_to_rusage50(&ru, &ru50); 255 1.174 dsl error = copyout(&ru, SCARG(uap, rusage), sizeof(ru)); 256 1.204 njoly } 257 1.174 dsl 258 1.174 dsl if (error == 0 && SCARG(uap, status) != NULL) { 259 1.173 dsl status = bsd_to_linux_wstat(status); 260 1.174 dsl error = copyout(&status, SCARG(uap, status), sizeof status); 261 1.16 fvdl } 262 1.1 fvdl 263 1.174 dsl return error; 264 1.1 fvdl } 265 1.1 fvdl 266 1.1 fvdl /* 267 1.262 christos * waitid(2). Converting arguments to the NetBSD equivalent and 268 1.262 christos * calling it. 269 1.262 christos */ 270 1.262 christos int 271 1.262 christos linux_sys_waitid(struct lwp *l, const struct linux_sys_waitid_args *uap, register_t *retval) 272 1.262 christos { 273 1.262 christos /* { 274 1.262 christos syscallarg(int) idtype; 275 1.262 christos syscallarg(id_t) id; 276 1.262 christos syscallarg(linux_siginfo_t *) infop; 277 1.262 christos syscallarg(int) options; 278 1.262 christos syscallarg(struct rusage50 *) rusage; 279 1.262 christos } */ 280 1.262 christos int error, linux_options, options, linux_idtype, status; 281 1.262 christos pid_t pid; 282 1.262 christos idtype_t idtype; 283 1.262 christos id_t id; 284 1.262 christos siginfo_t info; 285 1.262 christos linux_siginfo_t linux_info; 286 1.262 christos struct wrusage wru; 287 1.262 christos struct rusage50 ru50; 288 1.262 christos 289 1.262 christos linux_idtype = SCARG(uap, idtype); 290 1.262 christos switch (linux_idtype) { 291 1.262 christos case LINUX_P_ALL: 292 1.262 christos idtype = P_ALL; 293 1.262 christos break; 294 1.262 christos case LINUX_P_PID: 295 1.262 christos idtype = P_PID; 296 1.262 christos break; 297 1.262 christos case LINUX_P_PGID: 298 1.262 christos idtype = P_PGID; 299 1.262 christos break; 300 1.262 christos case LINUX_P_PIDFD: 301 1.262 christos return EOPNOTSUPP; 302 1.262 christos default: 303 1.262 christos return EINVAL; 304 1.262 christos } 305 1.262 christos 306 1.262 christos linux_options = SCARG(uap, options); 307 1.262 christos if (linux_options & ~(LINUX_WAITID_KNOWNFLAGS)) 308 1.262 christos return EINVAL; 309 1.262 christos 310 1.262 christos options = linux_to_native_wait_options(linux_options); 311 1.262 christos id = SCARG(uap, id); 312 1.262 christos 313 1.262 christos error = do_sys_waitid(idtype, id, &pid, &status, options, &wru, &info); 314 1.262 christos if (pid == 0 && options & WNOHANG) { 315 1.262 christos info.si_signo = 0; 316 1.262 christos info.si_pid = 0; 317 1.262 christos } 318 1.262 christos 319 1.262 christos if (error == 0 && SCARG(uap, infop) != NULL) { 320 1.262 christos /* POSIX says that this NULL check is a bug, but Linux does this. */ 321 1.262 christos native_to_linux_siginfo(&linux_info, &info._info); 322 1.262 christos error = copyout(&linux_info, SCARG(uap, infop), sizeof(linux_info)); 323 1.262 christos } 324 1.262 christos 325 1.262 christos if (error == 0 && SCARG(uap, rusage) != NULL) { 326 1.262 christos rusage_to_rusage50(&wru.wru_children, &ru50); 327 1.262 christos error = copyout(&ru50, SCARG(uap, rusage), sizeof(ru50)); 328 1.262 christos } 329 1.262 christos 330 1.262 christos return error; 331 1.262 christos } 332 1.262 christos 333 1.262 christos /* 334 1.263 andvar * Convert the options argument for wait4(2) and waitid(2) from what 335 1.262 christos * Linux wants to what NetBSD wants. 336 1.262 christos */ 337 1.262 christos static int 338 1.262 christos linux_to_native_wait_options(int linux_options) 339 1.262 christos { 340 1.262 christos int options = 0; 341 1.262 christos 342 1.262 christos if (linux_options & LINUX_WNOHANG) 343 1.262 christos options |= WNOHANG; 344 1.262 christos if (linux_options & LINUX_WUNTRACED) 345 1.262 christos options |= WUNTRACED; 346 1.262 christos if (linux_options & LINUX_WEXITED) 347 1.262 christos options |= WEXITED; 348 1.262 christos if (linux_options & LINUX_WCONTINUED) 349 1.262 christos options |= WCONTINUED; 350 1.262 christos if (linux_options & LINUX_WNOWAIT) 351 1.262 christos options |= WNOWAIT; 352 1.262 christos if (linux_options & LINUX_WALL) 353 1.262 christos options |= WALLSIG; 354 1.262 christos if (linux_options & LINUX_WCLONE) 355 1.262 christos options |= WALTSIG; 356 1.262 christos 357 1.262 christos return options; 358 1.262 christos } 359 1.262 christos 360 1.262 christos /* 361 1.216 chs * Linux brk(2). Like native, but always return the new break value. 362 1.1 fvdl */ 363 1.1 fvdl int 364 1.190 dsl linux_sys_brk(struct lwp *l, const struct linux_sys_brk_args *uap, register_t *retval) 365 1.20 thorpej { 366 1.190 dsl /* { 367 1.1 fvdl syscallarg(char *) nsize; 368 1.190 dsl } */ 369 1.116 thorpej struct proc *p = l->l_proc; 370 1.216 chs struct vmspace *vm = p->p_vmspace; 371 1.21 mycroft struct sys_obreak_args oba; 372 1.1 fvdl 373 1.216 chs SCARG(&oba, nsize) = SCARG(uap, nsize); 374 1.1 fvdl 375 1.216 chs (void) sys_obreak(l, &oba, retval); 376 1.216 chs retval[0] = (register_t)((char *)vm->vm_daddr + ptoa(vm->vm_dsize)); 377 1.1 fvdl return 0; 378 1.1 fvdl } 379 1.1 fvdl 380 1.1 fvdl /* 381 1.2 fvdl * Implement the fs stat functions. Straightforward. 382 1.1 fvdl */ 383 1.1 fvdl int 384 1.190 dsl linux_sys_statfs(struct lwp *l, const struct linux_sys_statfs_args *uap, register_t *retval) 385 1.20 thorpej { 386 1.190 dsl /* { 387 1.53 christos syscallarg(const char *) path; 388 1.1 fvdl syscallarg(struct linux_statfs *) sp; 389 1.190 dsl } */ 390 1.172 dsl struct statvfs *sb; 391 1.2 fvdl struct linux_statfs ltmp; 392 1.2 fvdl int error; 393 1.2 fvdl 394 1.172 dsl sb = STATVFSBUF_GET(); 395 1.172 dsl error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb); 396 1.172 dsl if (error == 0) { 397 1.172 dsl bsd_to_linux_statfs(sb, <mp); 398 1.172 dsl error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 399 1.172 dsl } 400 1.172 dsl STATVFSBUF_PUT(sb); 401 1.2 fvdl 402 1.153 yamt return error; 403 1.1 fvdl } 404 1.1 fvdl 405 1.1 fvdl int 406 1.190 dsl linux_sys_fstatfs(struct lwp *l, const struct linux_sys_fstatfs_args *uap, register_t *retval) 407 1.20 thorpej { 408 1.190 dsl /* { 409 1.2 fvdl syscallarg(int) fd; 410 1.1 fvdl syscallarg(struct linux_statfs *) sp; 411 1.190 dsl } */ 412 1.172 dsl struct statvfs *sb; 413 1.2 fvdl struct linux_statfs ltmp; 414 1.2 fvdl int error; 415 1.2 fvdl 416 1.172 dsl sb = STATVFSBUF_GET(); 417 1.172 dsl error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb); 418 1.172 dsl if (error == 0) { 419 1.172 dsl bsd_to_linux_statfs(sb, <mp); 420 1.172 dsl error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 421 1.172 dsl } 422 1.172 dsl STATVFSBUF_PUT(sb); 423 1.2 fvdl 424 1.153 yamt return error; 425 1.1 fvdl } 426 1.82 fvdl 427 1.1 fvdl /* 428 1.1 fvdl * uname(). Just copy the info from the various strings stored in the 429 1.1 fvdl * kernel, and put it in the Linux utsname structure. That structure 430 1.1 fvdl * is almost the same as the NetBSD one, only it has fields 65 characters 431 1.1 fvdl * long, and an extra domainname field. 432 1.1 fvdl */ 433 1.1 fvdl int 434 1.190 dsl linux_sys_uname(struct lwp *l, const struct linux_sys_uname_args *uap, register_t *retval) 435 1.20 thorpej { 436 1.190 dsl /* { 437 1.1 fvdl syscallarg(struct linux_utsname *) up; 438 1.190 dsl } */ 439 1.15 mycroft struct linux_utsname luts; 440 1.1 fvdl 441 1.241 maxv memset(&luts, 0, sizeof(luts)); 442 1.186 njoly strlcpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname)); 443 1.186 njoly strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); 444 1.186 njoly strlcpy(luts.l_release, linux_release, sizeof(luts.l_release)); 445 1.186 njoly strlcpy(luts.l_version, linux_version, sizeof(luts.l_version)); 446 1.186 njoly strlcpy(luts.l_machine, LINUX_UNAME_ARCH, sizeof(luts.l_machine)); 447 1.186 njoly strlcpy(luts.l_domainname, domainname, sizeof(luts.l_domainname)); 448 1.15 mycroft 449 1.15 mycroft return copyout(&luts, SCARG(uap, up), sizeof(luts)); 450 1.15 mycroft } 451 1.15 mycroft 452 1.47 erh /* Used directly on: alpha, mips, ppc, sparc, sparc64 */ 453 1.47 erh /* Used indirectly on: arm, i386, m68k */ 454 1.1 fvdl 455 1.1 fvdl /* 456 1.47 erh * New type Linux mmap call. 457 1.47 erh * Only called directly on machines with >= 6 free regs. 458 1.1 fvdl */ 459 1.1 fvdl int 460 1.190 dsl linux_sys_mmap(struct lwp *l, const struct linux_sys_mmap_args *uap, register_t *retval) 461 1.20 thorpej { 462 1.190 dsl /* { 463 1.47 erh syscallarg(unsigned long) addr; 464 1.47 erh syscallarg(size_t) len; 465 1.47 erh syscallarg(int) prot; 466 1.47 erh syscallarg(int) flags; 467 1.47 erh syscallarg(int) fd; 468 1.94 manu syscallarg(linux_off_t) offset; 469 1.190 dsl } */ 470 1.118 christos 471 1.115 christos if (SCARG(uap, offset) & PAGE_MASK) 472 1.115 christos return EINVAL; 473 1.115 christos 474 1.128 jdolecek return linux_mmap(l, uap, retval, SCARG(uap, offset)); 475 1.118 christos } 476 1.118 christos 477 1.118 christos /* 478 1.118 christos * Guts of most architectures' mmap64() implementations. This shares 479 1.118 christos * its list of arguments with linux_sys_mmap(). 480 1.118 christos * 481 1.118 christos * The difference in linux_sys_mmap2() is that "offset" is actually 482 1.118 christos * (offset / pagesize), not an absolute byte count. This translation 483 1.118 christos * to pagesize offsets is done inside glibc between the mmap64() call 484 1.118 christos * point, and the actual syscall. 485 1.118 christos */ 486 1.118 christos int 487 1.190 dsl linux_sys_mmap2(struct lwp *l, const struct linux_sys_mmap2_args *uap, register_t *retval) 488 1.118 christos { 489 1.190 dsl /* { 490 1.118 christos syscallarg(unsigned long) addr; 491 1.118 christos syscallarg(size_t) len; 492 1.118 christos syscallarg(int) prot; 493 1.118 christos syscallarg(int) flags; 494 1.118 christos syscallarg(int) fd; 495 1.118 christos syscallarg(linux_off_t) offset; 496 1.190 dsl } */ 497 1.128 jdolecek 498 1.128 jdolecek return linux_mmap(l, uap, retval, 499 1.128 jdolecek ((off_t)SCARG(uap, offset)) << PAGE_SHIFT); 500 1.128 jdolecek } 501 1.128 jdolecek 502 1.128 jdolecek /* 503 1.128 jdolecek * Massage arguments and call system mmap(2). 504 1.128 jdolecek */ 505 1.128 jdolecek static int 506 1.190 dsl linux_mmap(struct lwp *l, const struct linux_sys_mmap_args *uap, register_t *retval, off_t offset) 507 1.128 jdolecek { 508 1.118 christos struct sys_mmap_args cma; 509 1.128 jdolecek int error; 510 1.128 jdolecek size_t mmoff=0; 511 1.128 jdolecek 512 1.190 dsl linux_to_bsd_mmap_args(&cma, uap); 513 1.190 dsl SCARG(&cma, pos) = offset; 514 1.190 dsl 515 1.128 jdolecek if (SCARG(uap, flags) & LINUX_MAP_GROWSDOWN) { 516 1.128 jdolecek /* 517 1.128 jdolecek * Request for stack-like memory segment. On linux, this 518 1.128 jdolecek * works by mmap()ping (small) segment, which is automatically 519 1.128 jdolecek * extended when page fault happens below the currently 520 1.128 jdolecek * allocated area. We emulate this by allocating (typically 521 1.128 jdolecek * bigger) segment sized at current stack size limit, and 522 1.128 jdolecek * offsetting the requested and returned address accordingly. 523 1.128 jdolecek * Since physical pages are only allocated on-demand, this 524 1.128 jdolecek * is effectively identical. 525 1.128 jdolecek */ 526 1.128 jdolecek rlim_t ssl = l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur; 527 1.128 jdolecek 528 1.190 dsl if (SCARG(&cma, len) < ssl) { 529 1.128 jdolecek /* Compute the address offset */ 530 1.128 jdolecek mmoff = round_page(ssl) - SCARG(uap, len); 531 1.128 jdolecek 532 1.190 dsl if (SCARG(&cma, addr)) 533 1.190 dsl SCARG(&cma, addr) = (char *)SCARG(&cma, addr) - mmoff; 534 1.128 jdolecek 535 1.190 dsl SCARG(&cma, len) = (size_t) ssl; 536 1.128 jdolecek } 537 1.128 jdolecek } 538 1.118 christos 539 1.128 jdolecek error = sys_mmap(l, &cma, retval); 540 1.128 jdolecek if (error) 541 1.128 jdolecek return (error); 542 1.128 jdolecek 543 1.128 jdolecek /* Shift the returned address for stack-like segment if necessary */ 544 1.190 dsl retval[0] += mmoff; 545 1.118 christos 546 1.128 jdolecek return (0); 547 1.118 christos } 548 1.118 christos 549 1.118 christos static void 550 1.189 dsl linux_to_bsd_mmap_args(struct sys_mmap_args *cma, const struct linux_sys_mmap_args *uap) 551 1.118 christos { 552 1.119 christos int flags = MAP_TRYFIXED, fl = SCARG(uap, flags); 553 1.135 perry 554 1.103 christos flags |= cvtto_bsd_mask(fl, LINUX_MAP_SHARED, MAP_SHARED); 555 1.103 christos flags |= cvtto_bsd_mask(fl, LINUX_MAP_PRIVATE, MAP_PRIVATE); 556 1.103 christos flags |= cvtto_bsd_mask(fl, LINUX_MAP_FIXED, MAP_FIXED); 557 1.103 christos flags |= cvtto_bsd_mask(fl, LINUX_MAP_ANON, MAP_ANON); 558 1.231 njoly flags |= cvtto_bsd_mask(fl, LINUX_MAP_LOCKED, MAP_WIRED); 559 1.47 erh /* XXX XAX ERH: Any other flags here? There are more defined... */ 560 1.47 erh 561 1.118 christos SCARG(cma, addr) = (void *)SCARG(uap, addr); 562 1.118 christos SCARG(cma, len) = SCARG(uap, len); 563 1.118 christos SCARG(cma, prot) = SCARG(uap, prot); 564 1.118 christos if (SCARG(cma, prot) & VM_PROT_WRITE) /* XXX */ 565 1.118 christos SCARG(cma, prot) |= VM_PROT_READ; 566 1.118 christos SCARG(cma, flags) = flags; 567 1.118 christos SCARG(cma, fd) = flags & MAP_ANON ? -1 : SCARG(uap, fd); 568 1.208 pooka SCARG(cma, PAD) = 0; 569 1.97 christos } 570 1.97 christos 571 1.148 yamt #define LINUX_MREMAP_MAYMOVE 1 572 1.148 yamt #define LINUX_MREMAP_FIXED 2 573 1.148 yamt 574 1.34 mycroft int 575 1.190 dsl linux_sys_mremap(struct lwp *l, const struct linux_sys_mremap_args *uap, register_t *retval) 576 1.34 mycroft { 577 1.190 dsl /* { 578 1.34 mycroft syscallarg(void *) old_address; 579 1.34 mycroft syscallarg(size_t) old_size; 580 1.34 mycroft syscallarg(size_t) new_size; 581 1.34 mycroft syscallarg(u_long) flags; 582 1.190 dsl } */ 583 1.148 yamt 584 1.148 yamt struct proc *p; 585 1.148 yamt struct vm_map *map; 586 1.148 yamt vaddr_t oldva; 587 1.148 yamt vaddr_t newva; 588 1.148 yamt size_t oldsize; 589 1.148 yamt size_t newsize; 590 1.148 yamt int flags; 591 1.148 yamt int uvmflags; 592 1.42 thorpej int error; 593 1.42 thorpej 594 1.148 yamt flags = SCARG(uap, flags); 595 1.148 yamt oldva = (vaddr_t)SCARG(uap, old_address); 596 1.148 yamt oldsize = round_page(SCARG(uap, old_size)); 597 1.148 yamt newsize = round_page(SCARG(uap, new_size)); 598 1.149 yamt if ((flags & ~(LINUX_MREMAP_FIXED|LINUX_MREMAP_MAYMOVE)) != 0) { 599 1.149 yamt error = EINVAL; 600 1.149 yamt goto done; 601 1.149 yamt } 602 1.148 yamt if ((flags & LINUX_MREMAP_FIXED) != 0) { 603 1.149 yamt if ((flags & LINUX_MREMAP_MAYMOVE) == 0) { 604 1.149 yamt error = EINVAL; 605 1.149 yamt goto done; 606 1.149 yamt } 607 1.148 yamt #if 0 /* notyet */ 608 1.148 yamt newva = SCARG(uap, new_address); 609 1.183 joerg uvmflags = MAP_FIXED; 610 1.148 yamt #else /* notyet */ 611 1.148 yamt error = EOPNOTSUPP; 612 1.148 yamt goto done; 613 1.148 yamt #endif /* notyet */ 614 1.148 yamt } else if ((flags & LINUX_MREMAP_MAYMOVE) != 0) { 615 1.148 yamt uvmflags = 0; 616 1.148 yamt } else { 617 1.148 yamt newva = oldva; 618 1.183 joerg uvmflags = MAP_FIXED; 619 1.42 thorpej } 620 1.148 yamt p = l->l_proc; 621 1.148 yamt map = &p->p_vmspace->vm_map; 622 1.148 yamt error = uvm_mremap(map, oldva, oldsize, map, &newva, newsize, p, 623 1.148 yamt uvmflags); 624 1.42 thorpej 625 1.148 yamt done: 626 1.148 yamt *retval = (error != 0) ? 0 : (register_t)newva; 627 1.148 yamt return error; 628 1.24 fvdl } 629 1.24 fvdl 630 1.224 pooka #ifdef USRSTACK 631 1.24 fvdl int 632 1.190 dsl linux_sys_mprotect(struct lwp *l, const struct linux_sys_mprotect_args *uap, register_t *retval) 633 1.103 christos { 634 1.190 dsl /* { 635 1.103 christos syscallarg(const void *) start; 636 1.103 christos syscallarg(unsigned long) len; 637 1.103 christos syscallarg(int) prot; 638 1.190 dsl } */ 639 1.103 christos struct vm_map_entry *entry; 640 1.141 chs struct vm_map *map; 641 1.141 chs struct proc *p; 642 1.141 chs vaddr_t end, start, len, stacklim; 643 1.141 chs int prot, grows; 644 1.103 christos 645 1.141 chs start = (vaddr_t)SCARG(uap, start); 646 1.103 christos len = round_page(SCARG(uap, len)); 647 1.141 chs prot = SCARG(uap, prot); 648 1.141 chs grows = prot & (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP); 649 1.141 chs prot &= ~grows; 650 1.103 christos end = start + len; 651 1.103 christos 652 1.141 chs if (start & PAGE_MASK) 653 1.141 chs return EINVAL; 654 1.103 christos if (end < start) 655 1.103 christos return EINVAL; 656 1.141 chs if (end == start) 657 1.103 christos return 0; 658 1.103 christos 659 1.141 chs if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) 660 1.141 chs return EINVAL; 661 1.141 chs if (grows == (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP)) 662 1.103 christos return EINVAL; 663 1.103 christos 664 1.141 chs p = l->l_proc; 665 1.141 chs map = &p->p_vmspace->vm_map; 666 1.103 christos vm_map_lock(map); 667 1.150 manu # ifdef notdef 668 1.103 christos VM_MAP_RANGE_CHECK(map, start, end); 669 1.150 manu # endif 670 1.103 christos if (!uvm_map_lookup_entry(map, start, &entry) || entry->start > start) { 671 1.103 christos vm_map_unlock(map); 672 1.126 jdolecek return ENOMEM; 673 1.103 christos } 674 1.141 chs 675 1.141 chs /* 676 1.141 chs * Approximate the behaviour of PROT_GROWS{DOWN,UP}. 677 1.141 chs */ 678 1.141 chs 679 1.141 chs stacklim = (vaddr_t)p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_cur; 680 1.141 chs if (grows & LINUX_PROT_GROWSDOWN) { 681 1.141 chs if (USRSTACK - stacklim <= start && start < USRSTACK) { 682 1.141 chs start = USRSTACK - stacklim; 683 1.141 chs } else { 684 1.141 chs start = entry->start; 685 1.141 chs } 686 1.141 chs } else if (grows & LINUX_PROT_GROWSUP) { 687 1.141 chs if (USRSTACK <= end && end < USRSTACK + stacklim) { 688 1.141 chs end = USRSTACK + stacklim; 689 1.141 chs } else { 690 1.141 chs end = entry->end; 691 1.141 chs } 692 1.141 chs } 693 1.103 christos vm_map_unlock(map); 694 1.238 joerg return uvm_map_protect_user(l, start, end, prot); 695 1.1 fvdl } 696 1.224 pooka #endif /* USRSTACK */ 697 1.1 fvdl 698 1.1 fvdl /* 699 1.1 fvdl * This code is partly stolen from src/lib/libc/compat-43/times.c 700 1.1 fvdl */ 701 1.1 fvdl 702 1.113 jdolecek #define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz)) 703 1.1 fvdl 704 1.1 fvdl int 705 1.190 dsl linux_sys_times(struct lwp *l, const struct linux_sys_times_args *uap, register_t *retval) 706 1.20 thorpej { 707 1.190 dsl /* { 708 1.1 fvdl syscallarg(struct times *) tms; 709 1.190 dsl } */ 710 1.116 thorpej struct proc *p = l->l_proc; 711 1.1 fvdl struct timeval t; 712 1.155 kardel int error; 713 1.1 fvdl 714 1.112 jdolecek if (SCARG(uap, tms)) { 715 1.112 jdolecek struct linux_tms ltms; 716 1.112 jdolecek struct rusage ru; 717 1.112 jdolecek 718 1.252 riastrad memset(<ms, 0, sizeof(ltms)); 719 1.252 riastrad 720 1.197 ad mutex_enter(p->p_lock); 721 1.166 ad calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL); 722 1.112 jdolecek ltms.ltms_utime = CONVTCK(ru.ru_utime); 723 1.112 jdolecek ltms.ltms_stime = CONVTCK(ru.ru_stime); 724 1.112 jdolecek ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime); 725 1.112 jdolecek ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime); 726 1.197 ad mutex_exit(p->p_lock); 727 1.1 fvdl 728 1.112 jdolecek if ((error = copyout(<ms, SCARG(uap, tms), sizeof ltms))) 729 1.112 jdolecek return error; 730 1.112 jdolecek } 731 1.1 fvdl 732 1.155 kardel getmicrouptime(&t); 733 1.1 fvdl 734 1.1 fvdl retval[0] = ((linux_clock_t)(CONVTCK(t))); 735 1.1 fvdl return 0; 736 1.1 fvdl } 737 1.113 jdolecek 738 1.113 jdolecek #undef CONVTCK 739 1.1 fvdl 740 1.254 ryo #if !defined(__aarch64__) 741 1.1 fvdl /* 742 1.1 fvdl * Linux 'readdir' call. This code is mostly taken from the 743 1.1 fvdl * SunOS getdents call (see compat/sunos/sunos_misc.c), though 744 1.1 fvdl * an attempt has been made to keep it a little cleaner (failing 745 1.1 fvdl * miserably, because of the cruft needed if count 1 is passed). 746 1.1 fvdl * 747 1.17 fvdl * The d_off field should contain the offset of the next valid entry, 748 1.17 fvdl * but in Linux it has the offset of the entry itself. We emulate 749 1.17 fvdl * that bug here. 750 1.17 fvdl * 751 1.1 fvdl * Read in BSD-style entries, convert them, and copy them out. 752 1.1 fvdl * 753 1.1 fvdl * Note that this doesn't handle union-mounted filesystems. 754 1.1 fvdl */ 755 1.1 fvdl int 756 1.190 dsl linux_sys_getdents(struct lwp *l, const struct linux_sys_getdents_args *uap, register_t *retval) 757 1.20 thorpej { 758 1.190 dsl /* { 759 1.1 fvdl syscallarg(int) fd; 760 1.47 erh syscallarg(struct linux_dirent *) dent; 761 1.1 fvdl syscallarg(unsigned int) count; 762 1.190 dsl } */ 763 1.69 augustss struct dirent *bdp; 764 1.1 fvdl struct vnode *vp; 765 1.167 christos char *inp, *tbuf; /* BSD-format */ 766 1.26 christos int len, reclen; /* BSD-format */ 767 1.167 christos char *outp; /* Linux-format */ 768 1.26 christos int resid, linux_reclen = 0; /* Linux-format */ 769 1.1 fvdl struct file *fp; 770 1.1 fvdl struct uio auio; 771 1.1 fvdl struct iovec aiov; 772 1.1 fvdl struct linux_dirent idb; 773 1.1 fvdl off_t off; /* true file offset */ 774 1.17 fvdl int buflen, error, eofflag, nbytes, oldcall; 775 1.1 fvdl struct vattr va; 776 1.40 fvdl off_t *cookiebuf = NULL, *cookie; 777 1.22 mycroft int ncookies; 778 1.1 fvdl 779 1.201 ad /* fd_getvnode() will use the descriptor for us */ 780 1.201 ad if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 781 1.1 fvdl return (error); 782 1.1 fvdl 783 1.54 thorpej if ((fp->f_flag & FREAD) == 0) { 784 1.54 thorpej error = EBADF; 785 1.54 thorpej goto out1; 786 1.54 thorpej } 787 1.1 fvdl 788 1.5 mycroft vp = (struct vnode *)fp->f_data; 789 1.54 thorpej if (vp->v_type != VDIR) { 790 1.209 njoly error = ENOTDIR; 791 1.54 thorpej goto out1; 792 1.54 thorpej } 793 1.1 fvdl 794 1.219 hannken vn_lock(vp, LK_SHARED | LK_RETRY); 795 1.219 hannken error = VOP_GETATTR(vp, &va, l->l_cred); 796 1.219 hannken VOP_UNLOCK(vp); 797 1.219 hannken if (error) 798 1.54 thorpej goto out1; 799 1.1 fvdl 800 1.1 fvdl nbytes = SCARG(uap, count); 801 1.17 fvdl if (nbytes == 1) { /* emulating old, broken behaviour */ 802 1.107 christos nbytes = sizeof (idb); 803 1.240 riastrad buflen = uimax(va.va_blocksize, nbytes); 804 1.17 fvdl oldcall = 1; 805 1.5 mycroft } else { 806 1.240 riastrad buflen = uimin(MAXBSIZE, nbytes); 807 1.33 fvdl if (buflen < va.va_blocksize) 808 1.33 fvdl buflen = va.va_blocksize; 809 1.17 fvdl oldcall = 0; 810 1.1 fvdl } 811 1.138 christos tbuf = malloc(buflen, M_TEMP, M_WAITOK); 812 1.33 fvdl 813 1.39 fvdl vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 814 1.1 fvdl off = fp->f_offset; 815 1.1 fvdl again: 816 1.138 christos aiov.iov_base = tbuf; 817 1.1 fvdl aiov.iov_len = buflen; 818 1.1 fvdl auio.uio_iov = &aiov; 819 1.1 fvdl auio.uio_iovcnt = 1; 820 1.1 fvdl auio.uio_rw = UIO_READ; 821 1.1 fvdl auio.uio_resid = buflen; 822 1.1 fvdl auio.uio_offset = off; 823 1.151 yamt UIO_SETUP_SYSSPACE(&auio); 824 1.1 fvdl /* 825 1.1 fvdl * First we read into the malloc'ed buffer, then 826 1.1 fvdl * we massage it into user space, one record at a time. 827 1.1 fvdl */ 828 1.39 fvdl error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf, 829 1.39 fvdl &ncookies); 830 1.1 fvdl if (error) 831 1.1 fvdl goto out; 832 1.1 fvdl 833 1.138 christos inp = tbuf; 834 1.167 christos outp = (void *)SCARG(uap, dent); 835 1.1 fvdl resid = nbytes; 836 1.35 fvdl if ((len = buflen - auio.uio_resid) == 0) 837 1.1 fvdl goto eof; 838 1.1 fvdl 839 1.22 mycroft for (cookie = cookiebuf; len > 0; len -= reclen) { 840 1.5 mycroft bdp = (struct dirent *)inp; 841 1.5 mycroft reclen = bdp->d_reclen; 842 1.239 riastrad if (reclen & 3) { 843 1.239 riastrad error = EIO; 844 1.239 riastrad goto out; 845 1.239 riastrad } 846 1.1 fvdl if (bdp->d_fileno == 0) { 847 1.1 fvdl inp += reclen; /* it is a hole; squish it out */ 848 1.136 christos if (cookie) 849 1.136 christos off = *cookie++; 850 1.136 christos else 851 1.136 christos off += reclen; 852 1.1 fvdl continue; 853 1.1 fvdl } 854 1.21 mycroft linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen); 855 1.21 mycroft if (reclen > len || resid < linux_reclen) { 856 1.1 fvdl /* entry too big for buffer, so just stop */ 857 1.1 fvdl outp++; 858 1.1 fvdl break; 859 1.1 fvdl } 860 1.1 fvdl /* 861 1.1 fvdl * Massage in place to make a Linux-shaped dirent (otherwise 862 1.1 fvdl * we have to worry about touching user memory outside of 863 1.1 fvdl * the copyout() call). 864 1.1 fvdl */ 865 1.242 maxv memset(&idb, 0, sizeof(idb)); 866 1.107 christos idb.d_ino = bdp->d_fileno; 867 1.17 fvdl /* 868 1.21 mycroft * The old readdir() call misuses the offset and reclen fields. 869 1.17 fvdl */ 870 1.22 mycroft if (oldcall) { 871 1.22 mycroft idb.d_off = (linux_off_t)linux_reclen; 872 1.22 mycroft idb.d_reclen = (u_short)bdp->d_namlen; 873 1.22 mycroft } else { 874 1.109 tron if (sizeof (idb.d_off) <= 4 && (off >> 32) != 0) { 875 1.33 fvdl compat_offseterr(vp, "linux_getdents"); 876 1.33 fvdl error = EINVAL; 877 1.33 fvdl goto out; 878 1.33 fvdl } 879 1.22 mycroft idb.d_off = (linux_off_t)off; 880 1.107 christos idb.d_reclen = (u_short)linux_reclen; 881 1.227 slp /* Linux puts d_type at the end of each record */ 882 1.227 slp *((char *)&idb + idb.d_reclen - 1) = bdp->d_type; 883 1.107 christos } 884 1.235 christos memcpy(idb.d_name, bdp->d_name, 885 1.237 christos MIN(sizeof(idb.d_name), bdp->d_namlen + 1)); 886 1.167 christos if ((error = copyout((void *)&idb, outp, linux_reclen))) 887 1.107 christos goto out; 888 1.107 christos /* advance past this real entry */ 889 1.107 christos inp += reclen; 890 1.136 christos if (cookie) 891 1.136 christos off = *cookie++; /* each entry points to itself */ 892 1.136 christos else 893 1.136 christos off += reclen; 894 1.107 christos /* advance output past Linux-shaped entry */ 895 1.107 christos outp += linux_reclen; 896 1.107 christos resid -= linux_reclen; 897 1.107 christos if (oldcall) 898 1.107 christos break; 899 1.107 christos } 900 1.107 christos 901 1.107 christos /* if we squished out the whole block, try again */ 902 1.214 he if (outp == (void *)SCARG(uap, dent)) { 903 1.214 he if (cookiebuf) 904 1.214 he free(cookiebuf, M_TEMP); 905 1.214 he cookiebuf = NULL; 906 1.107 christos goto again; 907 1.214 he } 908 1.107 christos fp->f_offset = off; /* update the vnode offset */ 909 1.107 christos 910 1.107 christos if (oldcall) 911 1.107 christos nbytes = resid + linux_reclen; 912 1.107 christos 913 1.107 christos eof: 914 1.107 christos *retval = nbytes - resid; 915 1.107 christos out: 916 1.215 hannken VOP_UNLOCK(vp); 917 1.107 christos if (cookiebuf) 918 1.107 christos free(cookiebuf, M_TEMP); 919 1.138 christos free(tbuf, M_TEMP); 920 1.107 christos out1: 921 1.194 ad fd_putfile(SCARG(uap, fd)); 922 1.1 fvdl return error; 923 1.1 fvdl } 924 1.254 ryo #endif 925 1.1 fvdl 926 1.254 ryo #if !defined(__aarch64__) 927 1.1 fvdl /* 928 1.17 fvdl * Even when just using registers to pass arguments to syscalls you can 929 1.17 fvdl * have 5 of them on the i386. So this newer version of select() does 930 1.17 fvdl * this. 931 1.1 fvdl */ 932 1.1 fvdl int 933 1.190 dsl linux_sys_select(struct lwp *l, const struct linux_sys_select_args *uap, register_t *retval) 934 1.20 thorpej { 935 1.190 dsl /* { 936 1.17 fvdl syscallarg(int) nfds; 937 1.17 fvdl syscallarg(fd_set *) readfds; 938 1.17 fvdl syscallarg(fd_set *) writefds; 939 1.17 fvdl syscallarg(fd_set *) exceptfds; 940 1.203 christos syscallarg(struct timeval50 *) timeout; 941 1.190 dsl } */ 942 1.20 thorpej 943 1.116 thorpej return linux_select1(l, retval, SCARG(uap, nfds), SCARG(uap, readfds), 944 1.203 christos SCARG(uap, writefds), SCARG(uap, exceptfds), 945 1.203 christos (struct linux_timeval *)SCARG(uap, timeout)); 946 1.17 fvdl } 947 1.17 fvdl 948 1.17 fvdl /* 949 1.17 fvdl * Common code for the old and new versions of select(). A couple of 950 1.17 fvdl * things are important: 951 1.17 fvdl * 1) return the amount of time left in the 'timeout' parameter 952 1.17 fvdl * 2) select never returns ERESTART on Linux, always return EINTR 953 1.17 fvdl */ 954 1.17 fvdl int 955 1.211 rmind linux_select1(struct lwp *l, register_t *retval, int nfds, fd_set *readfds, 956 1.211 rmind fd_set *writefds, fd_set *exceptfds, struct linux_timeval *timeout) 957 1.17 fvdl { 958 1.207 christos struct timespec ts0, ts1, uts, *ts = NULL; 959 1.203 christos struct linux_timeval ltv; 960 1.1 fvdl int error; 961 1.1 fvdl 962 1.7 fvdl /* 963 1.7 fvdl * Store current time for computation of the amount of 964 1.7 fvdl * time left. 965 1.7 fvdl */ 966 1.17 fvdl if (timeout) { 967 1.203 christos if ((error = copyin(timeout, <v, sizeof(ltv)))) 968 1.13 mycroft return error; 969 1.207 christos uts.tv_sec = ltv.tv_sec; 970 1.245 kamil uts.tv_nsec = (long)((unsigned long)ltv.tv_usec * 1000); 971 1.207 christos if (itimespecfix(&uts)) { 972 1.13 mycroft /* 973 1.13 mycroft * The timeval was invalid. Convert it to something 974 1.13 mycroft * valid that will act as it does under Linux. 975 1.13 mycroft */ 976 1.207 christos uts.tv_sec += uts.tv_nsec / 1000000000; 977 1.207 christos uts.tv_nsec %= 1000000000; 978 1.207 christos if (uts.tv_nsec < 0) { 979 1.207 christos uts.tv_sec -= 1; 980 1.207 christos uts.tv_nsec += 1000000000; 981 1.13 mycroft } 982 1.207 christos if (uts.tv_sec < 0) 983 1.207 christos timespecclear(&uts); 984 1.13 mycroft } 985 1.207 christos ts = &uts; 986 1.207 christos nanotime(&ts0); 987 1.13 mycroft } 988 1.7 fvdl 989 1.211 rmind error = selcommon(retval, nfds, readfds, writefds, exceptfds, ts, NULL); 990 1.177 dsl 991 1.10 mycroft if (error) { 992 1.10 mycroft /* 993 1.10 mycroft * See fs/select.c in the Linux kernel. Without this, 994 1.10 mycroft * Maelstrom doesn't work. 995 1.10 mycroft */ 996 1.10 mycroft if (error == ERESTART) 997 1.10 mycroft error = EINTR; 998 1.7 fvdl return error; 999 1.10 mycroft } 1000 1.7 fvdl 1001 1.17 fvdl if (timeout) { 1002 1.14 mycroft if (*retval) { 1003 1.7 fvdl /* 1004 1.13 mycroft * Compute how much time was left of the timeout, 1005 1.7 fvdl * by subtracting the current time and the time 1006 1.7 fvdl * before we started the call, and subtracting 1007 1.7 fvdl * that result from the user-supplied value. 1008 1.7 fvdl */ 1009 1.207 christos nanotime(&ts1); 1010 1.207 christos timespecsub(&ts1, &ts0, &ts1); 1011 1.207 christos timespecsub(&uts, &ts1, &uts); 1012 1.207 christos if (uts.tv_sec < 0) 1013 1.207 christos timespecclear(&uts); 1014 1.14 mycroft } else 1015 1.207 christos timespecclear(&uts); 1016 1.207 christos ltv.tv_sec = uts.tv_sec; 1017 1.207 christos ltv.tv_usec = uts.tv_nsec / 1000; 1018 1.203 christos if ((error = copyout(<v, timeout, sizeof(ltv)))) 1019 1.7 fvdl return error; 1020 1.7 fvdl } 1021 1.13 mycroft 1022 1.7 fvdl return 0; 1023 1.1 fvdl } 1024 1.254 ryo #endif 1025 1.1 fvdl 1026 1.234 manu /* 1027 1.234 manu * Derived from FreeBSD's sys/compat/linux/linux_misc.c:linux_pselect6() 1028 1.234 manu * which was contributed by Dmitry Chagin 1029 1.234 manu * https://svnweb.freebsd.org/base?view=revision&revision=283403 1030 1.234 manu */ 1031 1.234 manu int 1032 1.234 manu linux_sys_pselect6(struct lwp *l, 1033 1.234 manu const struct linux_sys_pselect6_args *uap, register_t *retval) 1034 1.234 manu { 1035 1.234 manu /* { 1036 1.234 manu syscallarg(int) nfds; 1037 1.234 manu syscallarg(fd_set *) readfds; 1038 1.234 manu syscallarg(fd_set *) writefds; 1039 1.234 manu syscallarg(fd_set *) exceptfds; 1040 1.234 manu syscallarg(struct timespec *) timeout; 1041 1.234 manu syscallarg(linux_sized_sigset_t *) ss; 1042 1.234 manu } */ 1043 1.234 manu struct timespec uts, ts0, ts1, *tsp; 1044 1.234 manu linux_sized_sigset_t lsss; 1045 1.234 manu struct linux_timespec lts; 1046 1.234 manu linux_sigset_t lss; 1047 1.234 manu sigset_t *ssp; 1048 1.234 manu sigset_t ss; 1049 1.234 manu int error; 1050 1.234 manu 1051 1.234 manu ssp = NULL; 1052 1.234 manu if (SCARG(uap, ss) != NULL) { 1053 1.234 manu if ((error = copyin(SCARG(uap, ss), &lsss, sizeof(lsss))) != 0) 1054 1.234 manu return (error); 1055 1.234 manu if (lsss.ss_len != sizeof(lss)) 1056 1.234 manu return (EINVAL); 1057 1.234 manu if (lsss.ss != NULL) { 1058 1.234 manu if ((error = copyin(lsss.ss, &lss, sizeof(lss))) != 0) 1059 1.234 manu return (error); 1060 1.234 manu linux_to_native_sigset(&ss, &lss); 1061 1.234 manu ssp = &ss; 1062 1.234 manu } 1063 1.234 manu } 1064 1.234 manu 1065 1.234 manu if (SCARG(uap, timeout) != NULL) { 1066 1.234 manu error = copyin(SCARG(uap, timeout), <s, sizeof(lts)); 1067 1.234 manu if (error != 0) 1068 1.234 manu return (error); 1069 1.234 manu linux_to_native_timespec(&uts, <s); 1070 1.234 manu 1071 1.234 manu if (itimespecfix(&uts)) 1072 1.234 manu return (EINVAL); 1073 1.234 manu 1074 1.234 manu nanotime(&ts0); 1075 1.234 manu tsp = &uts; 1076 1.234 manu } else { 1077 1.234 manu tsp = NULL; 1078 1.234 manu } 1079 1.234 manu 1080 1.234 manu error = selcommon(retval, SCARG(uap, nfds), SCARG(uap, readfds), 1081 1.234 manu SCARG(uap, writefds), SCARG(uap, exceptfds), tsp, ssp); 1082 1.234 manu 1083 1.234 manu if (error == 0 && tsp != NULL) { 1084 1.234 manu if (retval != 0) { 1085 1.234 manu /* 1086 1.234 manu * Compute how much time was left of the timeout, 1087 1.234 manu * by subtracting the current time and the time 1088 1.234 manu * before we started the call, and subtracting 1089 1.234 manu * that result from the user-supplied value. 1090 1.234 manu */ 1091 1.234 manu nanotime(&ts1); 1092 1.234 manu timespecsub(&ts1, &ts0, &ts1); 1093 1.234 manu timespecsub(&uts, &ts1, &uts); 1094 1.234 manu if (uts.tv_sec < 0) 1095 1.234 manu timespecclear(&uts); 1096 1.234 manu } else { 1097 1.234 manu timespecclear(&uts); 1098 1.234 manu } 1099 1.234 manu 1100 1.234 manu native_to_linux_timespec(<s, &uts); 1101 1.234 manu error = copyout(<s, SCARG(uap, timeout), sizeof(lts)); 1102 1.234 manu } 1103 1.234 manu 1104 1.234 manu return (error); 1105 1.234 manu } 1106 1.234 manu 1107 1.220 pooka int 1108 1.220 pooka linux_sys_ppoll(struct lwp *l, 1109 1.220 pooka const struct linux_sys_ppoll_args *uap, register_t *retval) 1110 1.220 pooka { 1111 1.220 pooka /* { 1112 1.220 pooka syscallarg(struct pollfd *) fds; 1113 1.230 njoly syscallarg(u_int) nfds; 1114 1.220 pooka syscallarg(struct linux_timespec *) timeout; 1115 1.220 pooka syscallarg(linux_sigset_t *) sigset; 1116 1.220 pooka } */ 1117 1.220 pooka struct linux_timespec lts0, *lts; 1118 1.220 pooka struct timespec ts0, *ts = NULL; 1119 1.220 pooka linux_sigset_t lsigmask0, *lsigmask; 1120 1.220 pooka sigset_t sigmask0, *sigmask = NULL; 1121 1.220 pooka int error; 1122 1.220 pooka 1123 1.220 pooka lts = SCARG(uap, timeout); 1124 1.220 pooka if (lts) { 1125 1.220 pooka if ((error = copyin(lts, <s0, sizeof(lts0))) != 0) 1126 1.220 pooka return error; 1127 1.220 pooka linux_to_native_timespec(&ts0, <s0); 1128 1.220 pooka ts = &ts0; 1129 1.220 pooka } 1130 1.220 pooka 1131 1.220 pooka lsigmask = SCARG(uap, sigset); 1132 1.220 pooka if (lsigmask) { 1133 1.220 pooka if ((error = copyin(lsigmask, &lsigmask0, sizeof(lsigmask0)))) 1134 1.220 pooka return error; 1135 1.220 pooka linux_to_native_sigset(&sigmask0, &lsigmask0); 1136 1.220 pooka sigmask = &sigmask0; 1137 1.220 pooka } 1138 1.220 pooka 1139 1.220 pooka return pollcommon(retval, SCARG(uap, fds), SCARG(uap, nfds), 1140 1.220 pooka ts, sigmask); 1141 1.220 pooka } 1142 1.220 pooka 1143 1.1 fvdl /* 1144 1.6 fvdl * Set the 'personality' (emulation mode) for the current process. Only 1145 1.6 fvdl * accept the Linux personality here (0). This call is needed because 1146 1.6 fvdl * the Linux ELF crt0 issues it in an ugly kludge to make sure that 1147 1.6 fvdl * ELF binaries run in Linux mode, not SVR4 mode. 1148 1.6 fvdl */ 1149 1.6 fvdl int 1150 1.190 dsl linux_sys_personality(struct lwp *l, const struct linux_sys_personality_args *uap, register_t *retval) 1151 1.20 thorpej { 1152 1.190 dsl /* { 1153 1.212 njoly syscallarg(unsigned long) per; 1154 1.190 dsl } */ 1155 1.218 chs struct linux_emuldata *led; 1156 1.218 chs int per; 1157 1.20 thorpej 1158 1.218 chs per = SCARG(uap, per); 1159 1.218 chs led = l->l_emuldata; 1160 1.218 chs if (per == LINUX_PER_QUERY) { 1161 1.218 chs retval[0] = led->led_personality; 1162 1.218 chs return 0; 1163 1.218 chs } 1164 1.267 riastrad 1165 1.218 chs switch (per & LINUX_PER_MASK) { 1166 1.205 njoly case LINUX_PER_LINUX: 1167 1.218 chs case LINUX_PER_LINUX32: 1168 1.218 chs led->led_personality = per; 1169 1.205 njoly break; 1170 1.218 chs 1171 1.205 njoly default: 1172 1.6 fvdl return EINVAL; 1173 1.205 njoly } 1174 1.205 njoly 1175 1.218 chs retval[0] = per; 1176 1.1 fvdl return 0; 1177 1.18 fvdl } 1178 1.81 fvdl 1179 1.63 abs /* 1180 1.64 abs * We have nonexistent fsuid equal to uid. 1181 1.64 abs * If modification is requested, refuse. 1182 1.63 abs */ 1183 1.63 abs int 1184 1.190 dsl linux_sys_setfsuid(struct lwp *l, const struct linux_sys_setfsuid_args *uap, register_t *retval) 1185 1.63 abs { 1186 1.190 dsl /* { 1187 1.63 abs syscallarg(uid_t) uid; 1188 1.190 dsl } */ 1189 1.63 abs uid_t uid; 1190 1.63 abs 1191 1.63 abs uid = SCARG(uap, uid); 1192 1.158 ad if (kauth_cred_getuid(l->l_cred) != uid) 1193 1.190 dsl return sys_nosys(l, uap, retval); 1194 1.191 njoly 1195 1.191 njoly *retval = uid; 1196 1.191 njoly return 0; 1197 1.63 abs } 1198 1.63 abs 1199 1.63 abs int 1200 1.191 njoly linux_sys_setfsgid(struct lwp *l, const struct linux_sys_setfsgid_args *uap, register_t *retval) 1201 1.63 abs { 1202 1.191 njoly /* { 1203 1.191 njoly syscallarg(gid_t) gid; 1204 1.191 njoly } */ 1205 1.191 njoly gid_t gid; 1206 1.191 njoly 1207 1.191 njoly gid = SCARG(uap, gid); 1208 1.191 njoly if (kauth_cred_getgid(l->l_cred) != gid) 1209 1.191 njoly return sys_nosys(l, uap, retval); 1210 1.191 njoly 1211 1.191 njoly *retval = gid; 1212 1.191 njoly return 0; 1213 1.27 fvdl } 1214 1.27 fvdl 1215 1.27 fvdl int 1216 1.190 dsl linux_sys_setresuid(struct lwp *l, const struct linux_sys_setresuid_args *uap, register_t *retval) 1217 1.57 thorpej { 1218 1.190 dsl /* { 1219 1.57 thorpej syscallarg(uid_t) ruid; 1220 1.57 thorpej syscallarg(uid_t) euid; 1221 1.57 thorpej syscallarg(uid_t) suid; 1222 1.190 dsl } */ 1223 1.57 thorpej 1224 1.57 thorpej /* 1225 1.57 thorpej * Note: These checks are a little different than the NetBSD 1226 1.57 thorpej * setreuid(2) call performs. This precisely follows the 1227 1.57 thorpej * behavior of the Linux kernel. 1228 1.57 thorpej */ 1229 1.57 thorpej 1230 1.117 dsl return do_setresuid(l, SCARG(uap, ruid), SCARG(uap, euid), 1231 1.117 dsl SCARG(uap, suid), 1232 1.117 dsl ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S | 1233 1.117 dsl ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 1234 1.117 dsl ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S ); 1235 1.57 thorpej } 1236 1.57 thorpej 1237 1.57 thorpej int 1238 1.190 dsl linux_sys_getresuid(struct lwp *l, const struct linux_sys_getresuid_args *uap, register_t *retval) 1239 1.57 thorpej { 1240 1.190 dsl /* { 1241 1.57 thorpej syscallarg(uid_t *) ruid; 1242 1.57 thorpej syscallarg(uid_t *) euid; 1243 1.57 thorpej syscallarg(uid_t *) suid; 1244 1.190 dsl } */ 1245 1.158 ad kauth_cred_t pc = l->l_cred; 1246 1.57 thorpej int error; 1247 1.154 elad uid_t uid; 1248 1.57 thorpej 1249 1.57 thorpej /* 1250 1.57 thorpej * Linux copies these values out to userspace like so: 1251 1.57 thorpej * 1252 1.57 thorpej * 1. Copy out ruid. 1253 1.57 thorpej * 2. If that succeeds, copy out euid. 1254 1.57 thorpej * 3. If both of those succeed, copy out suid. 1255 1.57 thorpej */ 1256 1.154 elad uid = kauth_cred_getuid(pc); 1257 1.154 elad if ((error = copyout(&uid, SCARG(uap, ruid), sizeof(uid_t))) != 0) 1258 1.57 thorpej return (error); 1259 1.57 thorpej 1260 1.154 elad uid = kauth_cred_geteuid(pc); 1261 1.154 elad if ((error = copyout(&uid, SCARG(uap, euid), sizeof(uid_t))) != 0) 1262 1.57 thorpej return (error); 1263 1.57 thorpej 1264 1.154 elad uid = kauth_cred_getsvuid(pc); 1265 1.154 elad 1266 1.154 elad return (copyout(&uid, SCARG(uap, suid), sizeof(uid_t))); 1267 1.78 fvdl } 1268 1.62 tron 1269 1.62 tron int 1270 1.190 dsl linux_sys_ptrace(struct lwp *l, const struct linux_sys_ptrace_args *uap, register_t *retval) 1271 1.62 tron { 1272 1.190 dsl /* { 1273 1.88 manu i386, m68k, powerpc: T=int 1274 1.137 manu alpha, amd64: T=long 1275 1.66 erh syscallarg(T) request; 1276 1.66 erh syscallarg(T) pid; 1277 1.66 erh syscallarg(T) addr; 1278 1.66 erh syscallarg(T) data; 1279 1.190 dsl } */ 1280 1.73 jdolecek const int *ptr; 1281 1.73 jdolecek int request; 1282 1.89 manu int error; 1283 1.62 tron 1284 1.62 tron ptr = linux_ptrace_request_map; 1285 1.62 tron request = SCARG(uap, request); 1286 1.62 tron while (*ptr != -1) 1287 1.62 tron if (*ptr++ == request) { 1288 1.62 tron struct sys_ptrace_args pta; 1289 1.62 tron 1290 1.62 tron SCARG(&pta, req) = *ptr; 1291 1.62 tron SCARG(&pta, pid) = SCARG(uap, pid); 1292 1.167 christos SCARG(&pta, addr) = (void *)SCARG(uap, addr); 1293 1.62 tron SCARG(&pta, data) = SCARG(uap, data); 1294 1.62 tron 1295 1.73 jdolecek /* 1296 1.73 jdolecek * Linux ptrace(PTRACE_CONT, pid, 0, 0) means actually 1297 1.90 jdolecek * to continue where the process left off previously. 1298 1.202 ad * The same thing is achieved by addr == (void *) 1 1299 1.90 jdolecek * on NetBSD, so rewrite 'addr' appropriately. 1300 1.73 jdolecek */ 1301 1.73 jdolecek if (request == LINUX_PTRACE_CONT && SCARG(uap, addr)==0) 1302 1.167 christos SCARG(&pta, addr) = (void *) 1; 1303 1.135 perry 1304 1.202 ad error = sysent[SYS_ptrace].sy_call(l, &pta, retval); 1305 1.135 perry if (error) 1306 1.92 manu return error; 1307 1.92 manu switch (request) { 1308 1.92 manu case LINUX_PTRACE_PEEKTEXT: 1309 1.92 manu case LINUX_PTRACE_PEEKDATA: 1310 1.135 perry error = copyout (retval, 1311 1.267 riastrad (void *)SCARG(uap, data), 1312 1.137 manu sizeof *retval); 1313 1.92 manu *retval = SCARG(uap, data); 1314 1.92 manu break; 1315 1.135 perry default: 1316 1.92 manu break; 1317 1.92 manu } 1318 1.89 manu return error; 1319 1.62 tron } 1320 1.62 tron else 1321 1.62 tron ptr++; 1322 1.62 tron 1323 1.116 thorpej return LINUX_SYS_PTRACE_ARCH(l, uap, retval); 1324 1.1 fvdl } 1325 1.67 erh 1326 1.67 erh int 1327 1.190 dsl linux_sys_reboot(struct lwp *l, const struct linux_sys_reboot_args *uap, register_t *retval) 1328 1.67 erh { 1329 1.190 dsl /* { 1330 1.67 erh syscallarg(int) magic1; 1331 1.67 erh syscallarg(int) magic2; 1332 1.67 erh syscallarg(int) cmd; 1333 1.67 erh syscallarg(void *) arg; 1334 1.190 dsl } */ 1335 1.67 erh struct sys_reboot_args /* { 1336 1.67 erh syscallarg(int) opt; 1337 1.67 erh syscallarg(char *) bootstr; 1338 1.67 erh } */ sra; 1339 1.67 erh int error; 1340 1.67 erh 1341 1.164 elad if ((error = kauth_authorize_system(l->l_cred, 1342 1.164 elad KAUTH_SYSTEM_REBOOT, 0, NULL, NULL, NULL)) != 0) 1343 1.67 erh return(error); 1344 1.67 erh 1345 1.67 erh if (SCARG(uap, magic1) != LINUX_REBOOT_MAGIC1) 1346 1.67 erh return(EINVAL); 1347 1.67 erh if (SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2 && 1348 1.67 erh SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2A && 1349 1.67 erh SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2B) 1350 1.67 erh return(EINVAL); 1351 1.67 erh 1352 1.200 gmcgarry switch ((unsigned long)SCARG(uap, cmd)) { 1353 1.67 erh case LINUX_REBOOT_CMD_RESTART: 1354 1.67 erh SCARG(&sra, opt) = RB_AUTOBOOT; 1355 1.67 erh break; 1356 1.67 erh case LINUX_REBOOT_CMD_HALT: 1357 1.67 erh SCARG(&sra, opt) = RB_HALT; 1358 1.67 erh break; 1359 1.67 erh case LINUX_REBOOT_CMD_POWER_OFF: 1360 1.67 erh SCARG(&sra, opt) = RB_HALT|RB_POWERDOWN; 1361 1.67 erh break; 1362 1.67 erh case LINUX_REBOOT_CMD_RESTART2: 1363 1.67 erh /* Reboot with an argument. */ 1364 1.67 erh SCARG(&sra, opt) = RB_AUTOBOOT|RB_STRING; 1365 1.67 erh SCARG(&sra, bootstr) = SCARG(uap, arg); 1366 1.67 erh break; 1367 1.67 erh case LINUX_REBOOT_CMD_CAD_ON: 1368 1.67 erh return(EINVAL); /* We don't implement ctrl-alt-delete */ 1369 1.67 erh case LINUX_REBOOT_CMD_CAD_OFF: 1370 1.67 erh return(0); 1371 1.67 erh default: 1372 1.67 erh return(EINVAL); 1373 1.67 erh } 1374 1.67 erh 1375 1.116 thorpej return(sys_reboot(l, &sra, retval)); 1376 1.75 jdolecek } 1377 1.75 jdolecek 1378 1.75 jdolecek /* 1379 1.75 jdolecek * Copy of compat_12_sys_swapon(). 1380 1.75 jdolecek */ 1381 1.75 jdolecek int 1382 1.190 dsl linux_sys_swapon(struct lwp *l, const struct linux_sys_swapon_args *uap, register_t *retval) 1383 1.75 jdolecek { 1384 1.190 dsl /* { 1385 1.190 dsl syscallarg(const char *) name; 1386 1.190 dsl } */ 1387 1.75 jdolecek struct sys_swapctl_args ua; 1388 1.75 jdolecek 1389 1.75 jdolecek SCARG(&ua, cmd) = SWAP_ON; 1390 1.139 drochner SCARG(&ua, arg) = (void *)__UNCONST(SCARG(uap, name)); 1391 1.75 jdolecek SCARG(&ua, misc) = 0; /* priority */ 1392 1.116 thorpej return (sys_swapctl(l, &ua, retval)); 1393 1.76 jdolecek } 1394 1.76 jdolecek 1395 1.76 jdolecek /* 1396 1.76 jdolecek * Stop swapping to the file or block device specified by path. 1397 1.76 jdolecek */ 1398 1.76 jdolecek int 1399 1.190 dsl linux_sys_swapoff(struct lwp *l, const struct linux_sys_swapoff_args *uap, register_t *retval) 1400 1.76 jdolecek { 1401 1.190 dsl /* { 1402 1.190 dsl syscallarg(const char *) path; 1403 1.190 dsl } */ 1404 1.76 jdolecek struct sys_swapctl_args ua; 1405 1.76 jdolecek 1406 1.76 jdolecek SCARG(&ua, cmd) = SWAP_OFF; 1407 1.138 christos SCARG(&ua, arg) = __UNCONST(SCARG(uap, path)); /*XXXUNCONST*/ 1408 1.116 thorpej return (sys_swapctl(l, &ua, retval)); 1409 1.75 jdolecek } 1410 1.75 jdolecek 1411 1.75 jdolecek /* 1412 1.75 jdolecek * Copy of compat_09_sys_setdomainname() 1413 1.75 jdolecek */ 1414 1.75 jdolecek /* ARGSUSED */ 1415 1.75 jdolecek int 1416 1.190 dsl linux_sys_setdomainname(struct lwp *l, const struct linux_sys_setdomainname_args *uap, register_t *retval) 1417 1.75 jdolecek { 1418 1.190 dsl /* { 1419 1.75 jdolecek syscallarg(char *) domainname; 1420 1.75 jdolecek syscallarg(int) len; 1421 1.190 dsl } */ 1422 1.122 atatat int name[2]; 1423 1.75 jdolecek 1424 1.122 atatat name[0] = CTL_KERN; 1425 1.122 atatat name[1] = KERN_DOMAINNAME; 1426 1.122 atatat return (old_sysctl(&name[0], 2, 0, 0, SCARG(uap, domainname), 1427 1.122 atatat SCARG(uap, len), l)); 1428 1.77 augustss } 1429 1.77 augustss 1430 1.77 augustss /* 1431 1.77 augustss * sysinfo() 1432 1.77 augustss */ 1433 1.77 augustss /* ARGSUSED */ 1434 1.77 augustss int 1435 1.190 dsl linux_sys_sysinfo(struct lwp *l, const struct linux_sys_sysinfo_args *uap, register_t *retval) 1436 1.77 augustss { 1437 1.190 dsl /* { 1438 1.77 augustss syscallarg(struct linux_sysinfo *) arg; 1439 1.190 dsl } */ 1440 1.77 augustss struct linux_sysinfo si; 1441 1.77 augustss struct loadavg *la; 1442 1.251 ad int64_t filepg; 1443 1.77 augustss 1444 1.243 maxv memset(&si, 0, sizeof(si)); 1445 1.155 kardel si.uptime = time_uptime; 1446 1.77 augustss la = &averunnable; 1447 1.77 augustss si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale; 1448 1.77 augustss si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale; 1449 1.77 augustss si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale; 1450 1.162 manu si.totalram = ctob((u_long)physmem); 1451 1.251 ad /* uvm_availmem() may sync the counters. */ 1452 1.250 ad si.freeram = (u_long)uvm_availmem(true) * uvmexp.pagesize; 1453 1.251 ad filepg = cpu_count_get(CPU_COUNT_FILECLEAN) + 1454 1.251 ad cpu_count_get(CPU_COUNT_FILEDIRTY) + 1455 1.251 ad cpu_count_get(CPU_COUNT_FILEUNKNOWN) - 1456 1.251 ad cpu_count_get(CPU_COUNT_EXECPAGES); 1457 1.77 augustss si.sharedram = 0; /* XXX */ 1458 1.251 ad si.bufferram = (u_long)(filepg * uvmexp.pagesize); 1459 1.162 manu si.totalswap = (u_long)uvmexp.swpages * uvmexp.pagesize; 1460 1.267 riastrad si.freeswap = 1461 1.162 manu (u_long)(uvmexp.swpages - uvmexp.swpginuse) * uvmexp.pagesize; 1462 1.248 thorpej si.procs = atomic_load_relaxed(&nprocs); 1463 1.77 augustss 1464 1.77 augustss /* The following are only present in newer Linux kernels. */ 1465 1.77 augustss si.totalbig = 0; 1466 1.77 augustss si.freebig = 0; 1467 1.77 augustss si.mem_unit = 1; 1468 1.77 augustss 1469 1.77 augustss return (copyout(&si, SCARG(uap, arg), sizeof si)); 1470 1.97 christos } 1471 1.97 christos 1472 1.97 christos int 1473 1.190 dsl linux_sys_getrlimit(struct lwp *l, const struct linux_sys_getrlimit_args *uap, register_t *retval) 1474 1.97 christos { 1475 1.190 dsl /* { 1476 1.97 christos syscallarg(int) which; 1477 1.150 manu # ifdef LINUX_LARGEFILE64 1478 1.144 manu syscallarg(struct rlimit *) rlp; 1479 1.150 manu # else 1480 1.97 christos syscallarg(struct orlimit *) rlp; 1481 1.150 manu # endif 1482 1.190 dsl } */ 1483 1.150 manu # ifdef LINUX_LARGEFILE64 1484 1.144 manu struct rlimit orl; 1485 1.150 manu # else 1486 1.97 christos struct orlimit orl; 1487 1.150 manu # endif 1488 1.176 dsl int which; 1489 1.176 dsl 1490 1.176 dsl which = linux_to_bsd_limit(SCARG(uap, which)); 1491 1.176 dsl if (which < 0) 1492 1.176 dsl return -which; 1493 1.97 christos 1494 1.252 riastrad memset(&orl, 0, sizeof(orl)); 1495 1.176 dsl bsd_to_linux_rlimit(&orl, &l->l_proc->p_rlimit[which]); 1496 1.146 rpaulo 1497 1.97 christos return copyout(&orl, SCARG(uap, rlp), sizeof(orl)); 1498 1.97 christos } 1499 1.97 christos 1500 1.97 christos int 1501 1.190 dsl linux_sys_setrlimit(struct lwp *l, const struct linux_sys_setrlimit_args *uap, register_t *retval) 1502 1.97 christos { 1503 1.190 dsl /* { 1504 1.97 christos syscallarg(int) which; 1505 1.150 manu # ifdef LINUX_LARGEFILE64 1506 1.144 manu syscallarg(struct rlimit *) rlp; 1507 1.150 manu # else 1508 1.97 christos syscallarg(struct orlimit *) rlp; 1509 1.150 manu # endif 1510 1.190 dsl } */ 1511 1.97 christos struct rlimit rl; 1512 1.150 manu # ifdef LINUX_LARGEFILE64 1513 1.144 manu struct rlimit orl; 1514 1.150 manu # else 1515 1.97 christos struct orlimit orl; 1516 1.150 manu # endif 1517 1.97 christos int error; 1518 1.176 dsl int which; 1519 1.97 christos 1520 1.97 christos if ((error = copyin(SCARG(uap, rlp), &orl, sizeof(orl))) != 0) 1521 1.97 christos return error; 1522 1.176 dsl 1523 1.176 dsl which = linux_to_bsd_limit(SCARG(uap, which)); 1524 1.176 dsl if (which < 0) 1525 1.176 dsl return -which; 1526 1.176 dsl 1527 1.97 christos linux_to_bsd_rlimit(&rl, &orl); 1528 1.176 dsl return dosetrlimit(l, l->l_proc, which, &rl); 1529 1.97 christos } 1530 1.97 christos 1531 1.254 ryo # if !defined(__aarch64__) && !defined(__mips__) && !defined(__amd64__) 1532 1.98 rafal /* XXX: this doesn't look 100% common, at least mips doesn't have it */ 1533 1.97 christos int 1534 1.190 dsl linux_sys_ugetrlimit(struct lwp *l, const struct linux_sys_ugetrlimit_args *uap, register_t *retval) 1535 1.97 christos { 1536 1.190 dsl return linux_sys_getrlimit(l, (const void *)uap, retval); 1537 1.87 jdolecek } 1538 1.150 manu # endif 1539 1.87 jdolecek 1540 1.256 ryo int 1541 1.256 ryo linux_sys_prlimit64(struct lwp *l, const struct linux_sys_prlimit64_args *uap, register_t *retval) 1542 1.256 ryo { 1543 1.256 ryo /* { 1544 1.256 ryo syscallarg(pid_t) pid; 1545 1.256 ryo syscallarg(int) witch; 1546 1.256 ryo syscallarg(struct rlimit *) new_rlp; 1547 1.256 ryo syscallarg(struct rlimit *) old_rlp; 1548 1.256 ryo }; */ 1549 1.256 ryo struct rlimit rl, nrl, orl; 1550 1.256 ryo struct rlimit *p; 1551 1.256 ryo int which; 1552 1.256 ryo int error; 1553 1.256 ryo 1554 1.256 ryo /* XXX: Cannot operate any process other than its own */ 1555 1.256 ryo if (SCARG(uap, pid) != 0) 1556 1.256 ryo return EPERM; 1557 1.256 ryo 1558 1.256 ryo which = linux_to_bsd_limit(SCARG(uap, which)); 1559 1.256 ryo if (which < 0) 1560 1.256 ryo return -which; 1561 1.256 ryo 1562 1.256 ryo p = SCARG(uap, old_rlp); 1563 1.256 ryo if (p != NULL) { 1564 1.256 ryo memset(&orl, 0, sizeof(orl)); 1565 1.256 ryo bsd_to_linux_rlimit64(&orl, &l->l_proc->p_rlimit[which]); 1566 1.256 ryo if ((error = copyout(&orl, p, sizeof(orl))) != 0) 1567 1.256 ryo return error; 1568 1.256 ryo } 1569 1.256 ryo 1570 1.256 ryo p = SCARG(uap, new_rlp); 1571 1.256 ryo if (p != NULL) { 1572 1.256 ryo if ((error = copyin(p, &nrl, sizeof(nrl))) != 0) 1573 1.256 ryo return error; 1574 1.256 ryo 1575 1.256 ryo linux_to_bsd_rlimit(&rl, &nrl); 1576 1.256 ryo return dosetrlimit(l, l->l_proc, which, &rl); 1577 1.256 ryo } 1578 1.256 ryo 1579 1.256 ryo return 0; 1580 1.256 ryo } 1581 1.256 ryo 1582 1.87 jdolecek /* 1583 1.87 jdolecek * This gets called for unsupported syscalls. The difference to sys_nosys() 1584 1.87 jdolecek * is that process does not get SIGSYS, the call just returns with ENOSYS. 1585 1.87 jdolecek * This is the way Linux does it and glibc depends on this behaviour. 1586 1.87 jdolecek */ 1587 1.87 jdolecek int 1588 1.190 dsl linux_sys_nosys(struct lwp *l, const void *v, register_t *retval) 1589 1.87 jdolecek { 1590 1.87 jdolecek return (ENOSYS); 1591 1.67 erh } 1592 1.150 manu 1593 1.156 christos int 1594 1.190 dsl linux_sys_getpriority(struct lwp *l, const struct linux_sys_getpriority_args *uap, register_t *retval) 1595 1.156 christos { 1596 1.190 dsl /* { 1597 1.156 christos syscallarg(int) which; 1598 1.156 christos syscallarg(int) who; 1599 1.190 dsl } */ 1600 1.156 christos struct sys_getpriority_args bsa; 1601 1.156 christos int error; 1602 1.156 christos 1603 1.156 christos SCARG(&bsa, which) = SCARG(uap, which); 1604 1.156 christos SCARG(&bsa, who) = SCARG(uap, who); 1605 1.156 christos 1606 1.156 christos if ((error = sys_getpriority(l, &bsa, retval))) 1607 1.156 christos return error; 1608 1.156 christos 1609 1.157 christos *retval = NZERO - *retval; 1610 1.156 christos 1611 1.156 christos return 0; 1612 1.156 christos } 1613 1.221 pooka 1614 1.221 pooka int 1615 1.228 chs linux_do_sys_utimensat(struct lwp *l, int fd, const char *path, struct timespec *tsp, int flags, register_t *retval) 1616 1.226 njoly { 1617 1.226 njoly int follow, error; 1618 1.226 njoly 1619 1.228 chs follow = (flags & LINUX_AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 1620 1.226 njoly 1621 1.228 chs if (path == NULL && fd != AT_FDCWD) { 1622 1.226 njoly file_t *fp; 1623 1.226 njoly 1624 1.226 njoly /* fd_getvnode() will use the descriptor for us */ 1625 1.228 chs if ((error = fd_getvnode(fd, &fp)) != 0) 1626 1.226 njoly return error; 1627 1.226 njoly error = do_sys_utimensat(l, AT_FDCWD, fp->f_data, NULL, 0, 1628 1.226 njoly tsp, UIO_SYSSPACE); 1629 1.228 chs fd_putfile(fd); 1630 1.226 njoly return error; 1631 1.226 njoly } 1632 1.226 njoly 1633 1.228 chs return do_sys_utimensat(l, fd, NULL, path, follow, tsp, UIO_SYSSPACE); 1634 1.226 njoly } 1635 1.226 njoly 1636 1.221 pooka int 1637 1.228 chs linux_sys_utimensat(struct lwp *l, const struct linux_sys_utimensat_args *uap, 1638 1.228 chs register_t *retval) 1639 1.221 pooka { 1640 1.221 pooka /* { 1641 1.228 chs syscallarg(int) fd; 1642 1.221 pooka syscallarg(const char *) path; 1643 1.228 chs syscallarg(const struct linux_timespec *) times; 1644 1.228 chs syscallarg(int) flag; 1645 1.221 pooka } */ 1646 1.221 pooka int error; 1647 1.228 chs struct linux_timespec lts[2]; 1648 1.228 chs struct timespec *tsp = NULL, ts[2]; 1649 1.221 pooka 1650 1.221 pooka if (SCARG(uap, times)) { 1651 1.228 chs error = copyin(SCARG(uap, times), <s, sizeof(lts)); 1652 1.228 chs if (error != 0) 1653 1.221 pooka return error; 1654 1.228 chs linux_to_native_timespec(&ts[0], <s[0]); 1655 1.228 chs linux_to_native_timespec(&ts[1], <s[1]); 1656 1.228 chs tsp = ts; 1657 1.221 pooka } 1658 1.221 pooka 1659 1.228 chs return linux_do_sys_utimensat(l, SCARG(uap, fd), SCARG(uap, path), 1660 1.228 chs tsp, SCARG(uap, flag), retval); 1661 1.221 pooka } 1662 1.249 thorpej 1663 1.249 thorpej int 1664 1.249 thorpej linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, 1665 1.249 thorpej register_t *retval) 1666 1.249 thorpej { 1667 1.249 thorpej /* { 1668 1.249 thorpej syscallarg(int *) uaddr; 1669 1.249 thorpej syscallarg(int) op; 1670 1.249 thorpej syscallarg(int) val; 1671 1.249 thorpej syscallarg(const struct linux_timespec *) timeout; 1672 1.249 thorpej syscallarg(int *) uaddr2; 1673 1.249 thorpej syscallarg(int) val3; 1674 1.249 thorpej } */ 1675 1.249 thorpej struct linux_timespec lts; 1676 1.249 thorpej struct timespec ts, *tsp = NULL; 1677 1.249 thorpej int val2 = 0; 1678 1.249 thorpej int error; 1679 1.249 thorpej 1680 1.249 thorpej /* 1681 1.249 thorpej * Linux overlays the "timeout" field and the "val2" field. 1682 1.249 thorpej * "timeout" is only valid for FUTEX_WAIT and FUTEX_WAIT_BITSET 1683 1.249 thorpej * on Linux. 1684 1.249 thorpej */ 1685 1.249 thorpej const int op = (SCARG(uap, op) & FUTEX_CMD_MASK); 1686 1.249 thorpej if ((op == FUTEX_WAIT || op == FUTEX_WAIT_BITSET) && 1687 1.249 thorpej SCARG(uap, timeout) != NULL) { 1688 1.267 riastrad if ((error = copyin(SCARG(uap, timeout), 1689 1.249 thorpej <s, sizeof(lts))) != 0) { 1690 1.249 thorpej return error; 1691 1.249 thorpej } 1692 1.249 thorpej linux_to_native_timespec(&ts, <s); 1693 1.249 thorpej tsp = &ts; 1694 1.249 thorpej } else { 1695 1.249 thorpej val2 = (int)(uintptr_t)SCARG(uap, timeout); 1696 1.249 thorpej } 1697 1.249 thorpej 1698 1.249 thorpej return linux_do_futex(SCARG(uap, uaddr), SCARG(uap, op), 1699 1.249 thorpej SCARG(uap, val), tsp, SCARG(uap, uaddr2), val2, 1700 1.249 thorpej SCARG(uap, val3), retval); 1701 1.249 thorpej } 1702 1.249 thorpej 1703 1.249 thorpej int 1704 1.249 thorpej linux_do_futex(int *uaddr, int op, int val, struct timespec *timeout, 1705 1.249 thorpej int *uaddr2, int val2, int val3, register_t *retval) 1706 1.249 thorpej { 1707 1.249 thorpej /* 1708 1.249 thorpej * Always clear FUTEX_PRIVATE_FLAG for Linux processes. 1709 1.249 thorpej * NetBSD-native futexes exist in different namespace 1710 1.249 thorpej * depending on FUTEX_PRIVATE_FLAG. This appears not 1711 1.249 thorpej * to be the case in Linux, and some futex users will 1712 1.249 thorpej * mix private and non-private ops on the same futex 1713 1.249 thorpej * object. 1714 1.249 thorpej */ 1715 1.249 thorpej return do_futex(uaddr, op & ~FUTEX_PRIVATE_FLAG, 1716 1.249 thorpej val, timeout, uaddr2, val2, val3, retval); 1717 1.249 thorpej } 1718 1.253 thorpej 1719 1.253 thorpej #define LINUX_EFD_SEMAPHORE 0x0001 1720 1.253 thorpej #define LINUX_EFD_CLOEXEC LINUX_O_CLOEXEC 1721 1.253 thorpej #define LINUX_EFD_NONBLOCK LINUX_O_NONBLOCK 1722 1.253 thorpej 1723 1.253 thorpej static int 1724 1.253 thorpej linux_do_eventfd2(struct lwp *l, unsigned int initval, int flags, 1725 1.253 thorpej register_t *retval) 1726 1.253 thorpej { 1727 1.253 thorpej int nflags = 0; 1728 1.253 thorpej 1729 1.253 thorpej if (flags & ~(LINUX_EFD_SEMAPHORE | LINUX_EFD_CLOEXEC | 1730 1.253 thorpej LINUX_EFD_NONBLOCK)) { 1731 1.253 thorpej return EINVAL; 1732 1.253 thorpej } 1733 1.253 thorpej if (flags & LINUX_EFD_SEMAPHORE) { 1734 1.253 thorpej nflags |= EFD_SEMAPHORE; 1735 1.253 thorpej } 1736 1.253 thorpej if (flags & LINUX_EFD_CLOEXEC) { 1737 1.253 thorpej nflags |= EFD_CLOEXEC; 1738 1.253 thorpej } 1739 1.253 thorpej if (flags & LINUX_EFD_NONBLOCK) { 1740 1.253 thorpej nflags |= EFD_NONBLOCK; 1741 1.253 thorpej } 1742 1.253 thorpej 1743 1.253 thorpej return do_eventfd(l, initval, nflags, retval); 1744 1.253 thorpej } 1745 1.253 thorpej 1746 1.253 thorpej int 1747 1.253 thorpej linux_sys_eventfd(struct lwp *l, const struct linux_sys_eventfd_args *uap, 1748 1.253 thorpej register_t *retval) 1749 1.253 thorpej { 1750 1.253 thorpej /* { 1751 1.253 thorpej syscallarg(unsigned int) initval; 1752 1.253 thorpej } */ 1753 1.253 thorpej 1754 1.253 thorpej return linux_do_eventfd2(l, SCARG(uap, initval), 0, retval); 1755 1.253 thorpej } 1756 1.253 thorpej 1757 1.253 thorpej int 1758 1.253 thorpej linux_sys_eventfd2(struct lwp *l, const struct linux_sys_eventfd2_args *uap, 1759 1.253 thorpej register_t *retval) 1760 1.253 thorpej { 1761 1.253 thorpej /* { 1762 1.253 thorpej syscallarg(unsigned int) initval; 1763 1.253 thorpej syscallarg(int) flags; 1764 1.253 thorpej } */ 1765 1.253 thorpej 1766 1.253 thorpej return linux_do_eventfd2(l, SCARG(uap, initval), SCARG(uap, flags), 1767 1.253 thorpej retval); 1768 1.253 thorpej } 1769 1.257 christos 1770 1.259 rin #ifndef __aarch64__ 1771 1.258 christos /* 1772 1.258 christos * epoll_create(2). Check size and call sys_epoll_create1. 1773 1.258 christos */ 1774 1.258 christos int 1775 1.258 christos linux_sys_epoll_create(struct lwp *l, 1776 1.258 christos const struct linux_sys_epoll_create_args *uap, register_t *retval) 1777 1.258 christos { 1778 1.258 christos /* { 1779 1.258 christos syscallarg(int) size; 1780 1.258 christos } */ 1781 1.258 christos struct sys_epoll_create1_args ca; 1782 1.258 christos 1783 1.258 christos /* 1784 1.258 christos * SCARG(uap, size) is unused. Linux just tests it and then 1785 1.258 christos * forgets it as well. 1786 1.258 christos */ 1787 1.258 christos if (SCARG(uap, size) <= 0) 1788 1.258 christos return EINVAL; 1789 1.258 christos 1790 1.258 christos SCARG(&ca, flags) = 0; 1791 1.258 christos return sys_epoll_create1(l, &ca, retval); 1792 1.258 christos } 1793 1.259 rin #endif /* !__aarch64__ */ 1794 1.258 christos 1795 1.258 christos /* 1796 1.258 christos * epoll_create1(2). Translate the flags and call sys_epoll_create1. 1797 1.258 christos */ 1798 1.258 christos int 1799 1.258 christos linux_sys_epoll_create1(struct lwp *l, 1800 1.258 christos const struct linux_sys_epoll_create1_args *uap, register_t *retval) 1801 1.258 christos { 1802 1.258 christos /* { 1803 1.258 christos syscallarg(int) flags; 1804 1.258 christos } */ 1805 1.258 christos struct sys_epoll_create1_args ca; 1806 1.258 christos 1807 1.258 christos if ((SCARG(uap, flags) & ~(LINUX_O_CLOEXEC)) != 0) 1808 1.258 christos return EINVAL; 1809 1.258 christos 1810 1.258 christos SCARG(&ca, flags) = 0; 1811 1.258 christos if ((SCARG(uap, flags) & LINUX_O_CLOEXEC) != 0) 1812 1.261 christos SCARG(&ca, flags) |= EPOLL_CLOEXEC; 1813 1.258 christos 1814 1.258 christos return sys_epoll_create1(l, &ca, retval); 1815 1.258 christos } 1816 1.258 christos 1817 1.258 christos /* 1818 1.258 christos * epoll_ctl(2). Copyin event and translate it if necessary and then 1819 1.258 christos * call epoll_ctl_common(). 1820 1.258 christos */ 1821 1.258 christos int 1822 1.258 christos linux_sys_epoll_ctl(struct lwp *l, const struct linux_sys_epoll_ctl_args *uap, 1823 1.258 christos register_t *retval) 1824 1.258 christos { 1825 1.258 christos /* { 1826 1.258 christos syscallarg(int) epfd; 1827 1.258 christos syscallarg(int) op; 1828 1.258 christos syscallarg(int) fd; 1829 1.258 christos syscallarg(struct linux_epoll_event *) event; 1830 1.258 christos } */ 1831 1.258 christos struct linux_epoll_event lee; 1832 1.258 christos struct epoll_event ee; 1833 1.258 christos struct epoll_event *eep; 1834 1.258 christos int error; 1835 1.258 christos 1836 1.258 christos if (SCARG(uap, op) != EPOLL_CTL_DEL) { 1837 1.258 christos error = copyin(SCARG(uap, event), &lee, sizeof(lee)); 1838 1.258 christos if (error != 0) 1839 1.258 christos return error; 1840 1.258 christos 1841 1.258 christos /* 1842 1.258 christos * On some architectures, struct linux_epoll_event and 1843 1.258 christos * struct epoll_event are packed differently... but otherwise 1844 1.258 christos * the contents are the same. 1845 1.258 christos */ 1846 1.258 christos ee.events = lee.events; 1847 1.258 christos ee.data = lee.data; 1848 1.258 christos 1849 1.258 christos eep = ⅇ 1850 1.258 christos } else 1851 1.258 christos eep = NULL; 1852 1.258 christos 1853 1.258 christos return epoll_ctl_common(l, retval, SCARG(uap, epfd), SCARG(uap, op), 1854 1.258 christos SCARG(uap, fd), eep); 1855 1.258 christos } 1856 1.258 christos 1857 1.259 rin #ifndef __aarch64__ 1858 1.258 christos /* 1859 1.258 christos * epoll_wait(2). Call sys_epoll_pwait(). 1860 1.258 christos */ 1861 1.258 christos int 1862 1.258 christos linux_sys_epoll_wait(struct lwp *l, 1863 1.258 christos const struct linux_sys_epoll_wait_args *uap, register_t *retval) 1864 1.258 christos { 1865 1.258 christos /* { 1866 1.258 christos syscallarg(int) epfd; 1867 1.258 christos syscallarg(struct linux_epoll_event *) events; 1868 1.258 christos syscallarg(int) maxevents; 1869 1.258 christos syscallarg(int) timeout; 1870 1.258 christos } */ 1871 1.258 christos struct linux_sys_epoll_pwait_args ea; 1872 1.258 christos 1873 1.258 christos SCARG(&ea, epfd) = SCARG(uap, epfd); 1874 1.258 christos SCARG(&ea, events) = SCARG(uap, events); 1875 1.258 christos SCARG(&ea, maxevents) = SCARG(uap, maxevents); 1876 1.258 christos SCARG(&ea, timeout) = SCARG(uap, timeout); 1877 1.258 christos SCARG(&ea, sigmask) = NULL; 1878 1.258 christos 1879 1.258 christos return linux_sys_epoll_pwait(l, &ea, retval); 1880 1.258 christos } 1881 1.259 rin #endif /* !__aarch64__ */ 1882 1.258 christos 1883 1.258 christos /* 1884 1.258 christos * Main body of epoll_pwait2(2). Translate timeout and sigmask and 1885 1.258 christos * call epoll_wait_common. 1886 1.258 christos */ 1887 1.258 christos static int 1888 1.258 christos linux_epoll_pwait2_common(struct lwp *l, register_t *retval, int epfd, 1889 1.258 christos struct linux_epoll_event *events, int maxevents, 1890 1.258 christos struct linux_timespec *timeout, const linux_sigset_t *sigmask) 1891 1.258 christos { 1892 1.258 christos struct timespec ts, *tsp; 1893 1.258 christos linux_sigset_t lss; 1894 1.258 christos sigset_t ss, *ssp; 1895 1.258 christos struct epoll_event *eep; 1896 1.258 christos struct linux_epoll_event *leep; 1897 1.258 christos int i, error; 1898 1.258 christos 1899 1.258 christos if (maxevents <= 0 || maxevents > EPOLL_MAX_EVENTS) 1900 1.258 christos return EINVAL; 1901 1.258 christos 1902 1.258 christos if (timeout != NULL) { 1903 1.258 christos linux_to_native_timespec(&ts, timeout); 1904 1.258 christos tsp = &ts; 1905 1.258 christos } else 1906 1.258 christos tsp = NULL; 1907 1.258 christos 1908 1.258 christos if (sigmask != NULL) { 1909 1.258 christos error = copyin(sigmask, &lss, sizeof(lss)); 1910 1.258 christos if (error != 0) 1911 1.258 christos return error; 1912 1.258 christos 1913 1.258 christos linux_to_native_sigset(&ss, &lss); 1914 1.258 christos ssp = &ss; 1915 1.258 christos } else 1916 1.258 christos ssp = NULL; 1917 1.258 christos 1918 1.258 christos eep = kmem_alloc(maxevents * sizeof(*eep), KM_SLEEP); 1919 1.258 christos 1920 1.258 christos error = epoll_wait_common(l, retval, epfd, eep, maxevents, tsp, 1921 1.258 christos ssp); 1922 1.258 christos if (error == 0 && *retval > 0) { 1923 1.258 christos leep = kmem_alloc((*retval) * sizeof(*leep), KM_SLEEP); 1924 1.258 christos 1925 1.258 christos /* Translate the events (because of packing). */ 1926 1.258 christos for (i = 0; i < *retval; i++) { 1927 1.258 christos leep[i].events = eep[i].events; 1928 1.258 christos leep[i].data = eep[i].data; 1929 1.258 christos } 1930 1.258 christos 1931 1.258 christos error = copyout(leep, events, (*retval) * sizeof(*leep)); 1932 1.258 christos kmem_free(leep, (*retval) * sizeof(*leep)); 1933 1.258 christos } 1934 1.258 christos 1935 1.258 christos kmem_free(eep, maxevents * sizeof(*eep)); 1936 1.258 christos return error; 1937 1.258 christos } 1938 1.258 christos 1939 1.258 christos /* 1940 1.258 christos * epoll_pwait(2). Translate timeout and call sys_epoll_pwait2. 1941 1.258 christos */ 1942 1.258 christos int 1943 1.258 christos linux_sys_epoll_pwait(struct lwp *l, 1944 1.258 christos const struct linux_sys_epoll_pwait_args *uap, register_t *retval) 1945 1.258 christos { 1946 1.258 christos /* { 1947 1.258 christos syscallarg(int) epfd; 1948 1.258 christos syscallarg(struct linux_epoll_event *) events; 1949 1.258 christos syscallarg(int) maxevents; 1950 1.258 christos syscallarg(int) timeout; 1951 1.258 christos syscallarg(linux_sigset_t *) sigmask; 1952 1.258 christos } */ 1953 1.258 christos struct linux_timespec lts, *ltsp; 1954 1.258 christos const int timeout = SCARG(uap, timeout); 1955 1.258 christos 1956 1.258 christos if (timeout >= 0) { 1957 1.258 christos /* Convert from milliseconds to timespec. */ 1958 1.258 christos lts.tv_sec = timeout / 1000; 1959 1.258 christos lts.tv_nsec = (timeout % 1000) * 1000000; 1960 1.258 christos 1961 1.258 christos ltsp = <s; 1962 1.258 christos } else 1963 1.258 christos ltsp = NULL; 1964 1.258 christos 1965 1.258 christos return linux_epoll_pwait2_common(l, retval, SCARG(uap, epfd), 1966 1.258 christos SCARG(uap, events), SCARG(uap, maxevents), ltsp, 1967 1.258 christos SCARG(uap, sigmask)); 1968 1.258 christos } 1969 1.258 christos 1970 1.258 christos 1971 1.258 christos /* 1972 1.258 christos * epoll_pwait2(2). Copyin timeout and call linux_epoll_pwait2_common(). 1973 1.258 christos */ 1974 1.258 christos int 1975 1.258 christos linux_sys_epoll_pwait2(struct lwp *l, 1976 1.258 christos const struct linux_sys_epoll_pwait2_args *uap, register_t *retval) 1977 1.258 christos { 1978 1.258 christos /* { 1979 1.258 christos syscallarg(int) epfd; 1980 1.258 christos syscallarg(struct linux_epoll_event *) events; 1981 1.258 christos syscallarg(int) maxevents; 1982 1.258 christos syscallarg(struct linux_timespec *) timeout; 1983 1.258 christos syscallarg(linux_sigset_t *) sigmask; 1984 1.258 christos } */ 1985 1.258 christos struct linux_timespec lts, *ltsp; 1986 1.258 christos int error; 1987 1.258 christos 1988 1.258 christos if (SCARG(uap, timeout) != NULL) { 1989 1.258 christos error = copyin(SCARG(uap, timeout), <s, sizeof(lts)); 1990 1.258 christos if (error != 0) 1991 1.258 christos return error; 1992 1.258 christos 1993 1.258 christos ltsp = <s; 1994 1.258 christos } else 1995 1.258 christos ltsp = NULL; 1996 1.258 christos 1997 1.258 christos return linux_epoll_pwait2_common(l, retval, SCARG(uap, epfd), 1998 1.258 christos SCARG(uap, events), SCARG(uap, maxevents), ltsp, 1999 1.258 christos SCARG(uap, sigmask)); 2000 1.258 christos } 2001 1.258 christos 2002 1.257 christos #define LINUX_MFD_CLOEXEC 0x0001U 2003 1.257 christos #define LINUX_MFD_ALLOW_SEALING 0x0002U 2004 1.257 christos #define LINUX_MFD_HUGETLB 0x0004U 2005 1.257 christos #define LINUX_MFD_NOEXEC_SEAL 0x0008U 2006 1.257 christos #define LINUX_MFD_EXEC 0x0010U 2007 1.257 christos #define LINUX_MFD_HUGE_FLAGS (0x3f << 26) 2008 1.257 christos 2009 1.257 christos #define LINUX_MFD_ALL_FLAGS (LINUX_MFD_CLOEXEC|LINUX_MFD_ALLOW_SEALING \ 2010 1.257 christos |LINUX_MFD_HUGETLB|LINUX_MFD_NOEXEC_SEAL \ 2011 1.257 christos |LINUX_MFD_EXEC|LINUX_MFD_HUGE_FLAGS) 2012 1.257 christos #define LINUX_MFD_KNOWN_FLAGS (LINUX_MFD_CLOEXEC|LINUX_MFD_ALLOW_SEALING) 2013 1.257 christos 2014 1.257 christos #define LINUX_MFD_NAME_MAX 249 2015 1.257 christos 2016 1.257 christos /* 2017 1.257 christos * memfd_create(2). Do some error checking and then call NetBSD's 2018 1.257 christos * version. 2019 1.257 christos */ 2020 1.257 christos int 2021 1.257 christos linux_sys_memfd_create(struct lwp *l, 2022 1.257 christos const struct linux_sys_memfd_create_args *uap, register_t *retval) 2023 1.257 christos { 2024 1.257 christos /* { 2025 1.257 christos syscallarg(const char *) name; 2026 1.257 christos syscallarg(unsigned int) flags; 2027 1.257 christos } */ 2028 1.257 christos int error; 2029 1.257 christos char *pbuf; 2030 1.257 christos struct sys_memfd_create_args muap; 2031 1.257 christos const unsigned int lflags = SCARG(uap, flags); 2032 1.257 christos 2033 1.257 christos KASSERT(LINUX_MFD_NAME_MAX < NAME_MAX); /* sanity check */ 2034 1.257 christos 2035 1.257 christos if (lflags & ~LINUX_MFD_ALL_FLAGS) 2036 1.257 christos return EINVAL; 2037 1.257 christos if ((lflags & LINUX_MFD_HUGE_FLAGS) != 0 && 2038 1.257 christos (lflags & LINUX_MFD_HUGETLB) == 0) 2039 1.257 christos return EINVAL; 2040 1.257 christos if ((lflags & LINUX_MFD_HUGETLB) && (lflags & LINUX_MFD_ALLOW_SEALING)) 2041 1.257 christos return EINVAL; 2042 1.257 christos 2043 1.257 christos /* Linux has a stricter limit for name size */ 2044 1.257 christos pbuf = PNBUF_GET(); 2045 1.257 christos error = copyinstr(SCARG(uap, name), pbuf, LINUX_MFD_NAME_MAX+1, NULL); 2046 1.257 christos PNBUF_PUT(pbuf); 2047 1.257 christos pbuf = NULL; 2048 1.257 christos if (error != 0) { 2049 1.257 christos if (error == ENAMETOOLONG) 2050 1.257 christos error = EINVAL; 2051 1.257 christos return error; 2052 1.257 christos } 2053 1.257 christos 2054 1.257 christos if (lflags & ~LINUX_MFD_KNOWN_FLAGS) { 2055 1.265 christos DPRINTF("%s: ignored flags %#x\n", __func__, 2056 1.265 christos lflags & ~LINUX_MFD_KNOWN_FLAGS); 2057 1.257 christos } 2058 1.257 christos 2059 1.257 christos SCARG(&muap, name) = SCARG(uap, name); 2060 1.257 christos SCARG(&muap, flags) = lflags & LINUX_MFD_KNOWN_FLAGS; 2061 1.257 christos 2062 1.257 christos return sys_memfd_create(l, &muap, retval); 2063 1.257 christos } 2064 1.260 christos 2065 1.260 christos #define LINUX_CLOSE_RANGE_UNSHARE 0x02U 2066 1.260 christos #define LINUX_CLOSE_RANGE_CLOEXEC 0x04U 2067 1.260 christos 2068 1.260 christos /* 2069 1.260 christos * close_range(2). 2070 1.260 christos */ 2071 1.260 christos int 2072 1.260 christos linux_sys_close_range(struct lwp *l, 2073 1.260 christos const struct linux_sys_close_range_args *uap, register_t *retval) 2074 1.260 christos { 2075 1.260 christos /* { 2076 1.260 christos syscallarg(unsigned int) first; 2077 1.260 christos syscallarg(unsigned int) last; 2078 1.260 christos syscallarg(unsigned int) flags; 2079 1.260 christos } */ 2080 1.260 christos unsigned int fd, last; 2081 1.260 christos file_t *fp; 2082 1.260 christos filedesc_t *fdp; 2083 1.260 christos const unsigned int flags = SCARG(uap, flags); 2084 1.260 christos 2085 1.260 christos if (flags & ~(LINUX_CLOSE_RANGE_CLOEXEC|LINUX_CLOSE_RANGE_UNSHARE)) 2086 1.260 christos return EINVAL; 2087 1.260 christos if (SCARG(uap, first) > SCARG(uap, last)) 2088 1.260 christos return EINVAL; 2089 1.260 christos 2090 1.260 christos if (flags & LINUX_CLOSE_RANGE_UNSHARE) { 2091 1.260 christos fdp = fd_copy(); 2092 1.260 christos fd_free(); 2093 1.260 christos l->l_proc->p_fd = fdp; 2094 1.260 christos l->l_fd = fdp; 2095 1.260 christos } 2096 1.260 christos 2097 1.260 christos last = MIN(SCARG(uap, last), l->l_proc->p_fd->fd_lastfile); 2098 1.260 christos for (fd = SCARG(uap, first); fd <= last; fd++) { 2099 1.260 christos fp = fd_getfile(fd); 2100 1.260 christos if (fp == NULL) 2101 1.260 christos continue; 2102 1.260 christos 2103 1.260 christos if (flags & LINUX_CLOSE_RANGE_CLOEXEC) { 2104 1.260 christos fd_set_exclose(l, fd, true); 2105 1.260 christos fd_putfile(fd); 2106 1.260 christos } else 2107 1.260 christos fd_close(fd); 2108 1.260 christos } 2109 1.260 christos 2110 1.260 christos return 0; 2111 1.260 christos } 2112 1.260 christos 2113 1.260 christos /* 2114 1.260 christos * readahead(2). Call posix_fadvise with POSIX_FADV_WILLNEED with some extra 2115 1.260 christos * error checking. 2116 1.260 christos */ 2117 1.260 christos int 2118 1.260 christos linux_sys_readahead(struct lwp *l, const struct linux_sys_readahead_args *uap, 2119 1.260 christos register_t *retval) 2120 1.260 christos { 2121 1.260 christos /* { 2122 1.260 christos syscallarg(int) fd; 2123 1.260 christos syscallarg(off_t) offset; 2124 1.260 christos syscallarg(size_t) count; 2125 1.260 christos } */ 2126 1.260 christos file_t *fp; 2127 1.260 christos int error = 0; 2128 1.260 christos const int fd = SCARG(uap, fd); 2129 1.260 christos 2130 1.260 christos fp = fd_getfile(fd); 2131 1.260 christos if (fp == NULL) 2132 1.260 christos return EBADF; 2133 1.260 christos if ((fp->f_flag & FREAD) == 0) 2134 1.260 christos error = EBADF; 2135 1.260 christos else if (fp->f_type != DTYPE_VNODE || fp->f_vnode->v_type != VREG) 2136 1.260 christos error = EINVAL; 2137 1.260 christos fd_putfile(fd); 2138 1.260 christos if (error != 0) 2139 1.260 christos return error; 2140 1.260 christos 2141 1.260 christos return do_posix_fadvise(fd, SCARG(uap, offset), SCARG(uap, count), 2142 1.260 christos POSIX_FADV_WILLNEED); 2143 1.260 christos } 2144 1.264 christos 2145 1.264 christos int 2146 1.264 christos linux_sys_getcpu(lwp_t *l, const struct linux_sys_getcpu_args *uap, 2147 1.264 christos register_t *retval) 2148 1.264 christos { 2149 1.264 christos /* { 2150 1.264 christos syscallarg(unsigned int *) cpu; 2151 1.264 christos syscallarg(unsigned int *) node; 2152 1.264 christos syscallarg(struct linux_getcpu_cache *) tcache; 2153 1.264 christos }*/ 2154 1.264 christos int error; 2155 1.264 christos 2156 1.264 christos if (SCARG(uap, cpu)) { 2157 1.264 christos u_int cpu_id = l->l_cpu->ci_data.cpu_index; 2158 1.264 christos error = copyout(&cpu_id, SCARG(uap, cpu), sizeof(cpu_id)); 2159 1.264 christos if (error) 2160 1.264 christos return error; 2161 1.264 christos 2162 1.264 christos } 2163 1.267 riastrad 2164 1.264 christos // TO-DO: Test on a NUMA machine if the node_id returned is correct 2165 1.264 christos if (SCARG(uap, node)) { 2166 1.264 christos u_int node_id = l->l_cpu->ci_data.cpu_numa_id; 2167 1.264 christos error = copyout(&node_id, SCARG(uap, node), sizeof(node_id)); 2168 1.264 christos if (error) 2169 1.264 christos return error; 2170 1.264 christos } 2171 1.264 christos 2172 1.264 christos return 0; 2173 1.264 christos } 2174