1*a9643ea8Slogwang /*- 2*a9643ea8Slogwang * Copyright (c) 2013 Dmitry Chagin 3*a9643ea8Slogwang * Copyright (c) 2004 Tim J. Robbins 4*a9643ea8Slogwang * Copyright (c) 2002 Doug Rabson 5*a9643ea8Slogwang * Copyright (c) 2000 Marcel Moolenaar 6*a9643ea8Slogwang * All rights reserved. 7*a9643ea8Slogwang * 8*a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 9*a9643ea8Slogwang * modification, are permitted provided that the following conditions 10*a9643ea8Slogwang * are met: 11*a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright 12*a9643ea8Slogwang * notice, this list of conditions and the following disclaimer 13*a9643ea8Slogwang * in this position and unchanged. 14*a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright 15*a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the 16*a9643ea8Slogwang * documentation and/or other materials provided with the distribution. 17*a9643ea8Slogwang * 3. The name of the author may not be used to endorse or promote products 18*a9643ea8Slogwang * derived from this software without specific prior written permission. 19*a9643ea8Slogwang * 20*a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21*a9643ea8Slogwang * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22*a9643ea8Slogwang * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23*a9643ea8Slogwang * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24*a9643ea8Slogwang * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25*a9643ea8Slogwang * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*a9643ea8Slogwang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*a9643ea8Slogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*a9643ea8Slogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29*a9643ea8Slogwang * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*a9643ea8Slogwang */ 31*a9643ea8Slogwang 32*a9643ea8Slogwang #include <sys/cdefs.h> 33*a9643ea8Slogwang __FBSDID("$FreeBSD$"); 34*a9643ea8Slogwang 35*a9643ea8Slogwang #include <sys/param.h> 36*a9643ea8Slogwang #include <sys/kernel.h> 37*a9643ea8Slogwang #include <sys/systm.h> 38*a9643ea8Slogwang #include <sys/capability.h> 39*a9643ea8Slogwang #include <sys/dirent.h> 40*a9643ea8Slogwang #include <sys/file.h> 41*a9643ea8Slogwang #include <sys/fcntl.h> 42*a9643ea8Slogwang #include <sys/filedesc.h> 43*a9643ea8Slogwang #include <sys/clock.h> 44*a9643ea8Slogwang #include <sys/imgact.h> 45*a9643ea8Slogwang #include <sys/ktr.h> 46*a9643ea8Slogwang #include <sys/limits.h> 47*a9643ea8Slogwang #include <sys/lock.h> 48*a9643ea8Slogwang #include <sys/malloc.h> 49*a9643ea8Slogwang #include <sys/mman.h> 50*a9643ea8Slogwang #include <sys/mutex.h> 51*a9643ea8Slogwang #include <sys/priv.h> 52*a9643ea8Slogwang #include <sys/proc.h> 53*a9643ea8Slogwang #include <sys/resource.h> 54*a9643ea8Slogwang #include <sys/resourcevar.h> 55*a9643ea8Slogwang #include <sys/sched.h> 56*a9643ea8Slogwang #include <sys/syscallsubr.h> 57*a9643ea8Slogwang #include <sys/sysproto.h> 58*a9643ea8Slogwang #include <sys/vnode.h> 59*a9643ea8Slogwang #include <sys/unistd.h> 60*a9643ea8Slogwang #include <sys/wait.h> 61*a9643ea8Slogwang 62*a9643ea8Slogwang #include <security/mac/mac_framework.h> 63*a9643ea8Slogwang 64*a9643ea8Slogwang #include <ufs/ufs/extattr.h> 65*a9643ea8Slogwang #include <ufs/ufs/quota.h> 66*a9643ea8Slogwang #include <ufs/ufs/ufsmount.h> 67*a9643ea8Slogwang 68*a9643ea8Slogwang #include <machine/frame.h> 69*a9643ea8Slogwang #include <machine/md_var.h> 70*a9643ea8Slogwang #include <machine/pcb.h> 71*a9643ea8Slogwang #include <machine/psl.h> 72*a9643ea8Slogwang #include <machine/segments.h> 73*a9643ea8Slogwang #include <machine/specialreg.h> 74*a9643ea8Slogwang 75*a9643ea8Slogwang #include <vm/vm.h> 76*a9643ea8Slogwang #include <vm/pmap.h> 77*a9643ea8Slogwang #include <vm/vm_extern.h> 78*a9643ea8Slogwang #include <vm/vm_kern.h> 79*a9643ea8Slogwang #include <vm/vm_map.h> 80*a9643ea8Slogwang 81*a9643ea8Slogwang #include <amd64/linux/linux.h> 82*a9643ea8Slogwang #include <amd64/linux/linux_proto.h> 83*a9643ea8Slogwang #include <compat/linux/linux_ipc.h> 84*a9643ea8Slogwang #include <compat/linux/linux_file.h> 85*a9643ea8Slogwang #include <compat/linux/linux_misc.h> 86*a9643ea8Slogwang #include <compat/linux/linux_mmap.h> 87*a9643ea8Slogwang #include <compat/linux/linux_signal.h> 88*a9643ea8Slogwang #include <compat/linux/linux_util.h> 89*a9643ea8Slogwang #include <compat/linux/linux_emul.h> 90*a9643ea8Slogwang 91*a9643ea8Slogwang 92*a9643ea8Slogwang int 93*a9643ea8Slogwang linux_execve(struct thread *td, struct linux_execve_args *args) 94*a9643ea8Slogwang { 95*a9643ea8Slogwang struct image_args eargs; 96*a9643ea8Slogwang char *path; 97*a9643ea8Slogwang int error; 98*a9643ea8Slogwang 99*a9643ea8Slogwang LCONVPATHEXIST(td, args->path, &path); 100*a9643ea8Slogwang 101*a9643ea8Slogwang LINUX_CTR(execve); 102*a9643ea8Slogwang 103*a9643ea8Slogwang error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp, 104*a9643ea8Slogwang args->envp); 105*a9643ea8Slogwang free(path, M_TEMP); 106*a9643ea8Slogwang if (error == 0) 107*a9643ea8Slogwang error = linux_common_execve(td, &eargs); 108*a9643ea8Slogwang return (error); 109*a9643ea8Slogwang } 110*a9643ea8Slogwang 111*a9643ea8Slogwang int 112*a9643ea8Slogwang linux_set_upcall_kse(struct thread *td, register_t stack) 113*a9643ea8Slogwang { 114*a9643ea8Slogwang 115*a9643ea8Slogwang if (stack) 116*a9643ea8Slogwang td->td_frame->tf_rsp = stack; 117*a9643ea8Slogwang 118*a9643ea8Slogwang /* 119*a9643ea8Slogwang * The newly created Linux thread returns 120*a9643ea8Slogwang * to the user space by the same path that a parent do. 121*a9643ea8Slogwang */ 122*a9643ea8Slogwang td->td_frame->tf_rax = 0; 123*a9643ea8Slogwang return (0); 124*a9643ea8Slogwang } 125*a9643ea8Slogwang 126*a9643ea8Slogwang int 127*a9643ea8Slogwang linux_mmap2(struct thread *td, struct linux_mmap2_args *args) 128*a9643ea8Slogwang { 129*a9643ea8Slogwang 130*a9643ea8Slogwang return (linux_mmap_common(td, PTROUT(args->addr), args->len, args->prot, 131*a9643ea8Slogwang args->flags, args->fd, args->pgoff)); 132*a9643ea8Slogwang } 133*a9643ea8Slogwang 134*a9643ea8Slogwang int 135*a9643ea8Slogwang linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) 136*a9643ea8Slogwang { 137*a9643ea8Slogwang 138*a9643ea8Slogwang return (linux_mprotect_common(td, PTROUT(uap->addr), uap->len, uap->prot)); 139*a9643ea8Slogwang } 140*a9643ea8Slogwang 141*a9643ea8Slogwang int 142*a9643ea8Slogwang linux_iopl(struct thread *td, struct linux_iopl_args *args) 143*a9643ea8Slogwang { 144*a9643ea8Slogwang int error; 145*a9643ea8Slogwang 146*a9643ea8Slogwang LINUX_CTR(iopl); 147*a9643ea8Slogwang 148*a9643ea8Slogwang if (args->level > 3) 149*a9643ea8Slogwang return (EINVAL); 150*a9643ea8Slogwang if ((error = priv_check(td, PRIV_IO)) != 0) 151*a9643ea8Slogwang return (error); 152*a9643ea8Slogwang if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 153*a9643ea8Slogwang return (error); 154*a9643ea8Slogwang td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) | 155*a9643ea8Slogwang (args->level * (PSL_IOPL / 3)); 156*a9643ea8Slogwang 157*a9643ea8Slogwang return (0); 158*a9643ea8Slogwang } 159*a9643ea8Slogwang 160*a9643ea8Slogwang int 161*a9643ea8Slogwang linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) 162*a9643ea8Slogwang { 163*a9643ea8Slogwang l_sigset_t lmask; 164*a9643ea8Slogwang sigset_t sigmask; 165*a9643ea8Slogwang int error; 166*a9643ea8Slogwang 167*a9643ea8Slogwang LINUX_CTR2(rt_sigsuspend, "%p, %ld", 168*a9643ea8Slogwang uap->newset, uap->sigsetsize); 169*a9643ea8Slogwang 170*a9643ea8Slogwang if (uap->sigsetsize != sizeof(l_sigset_t)) 171*a9643ea8Slogwang return (EINVAL); 172*a9643ea8Slogwang 173*a9643ea8Slogwang error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); 174*a9643ea8Slogwang if (error) 175*a9643ea8Slogwang return (error); 176*a9643ea8Slogwang 177*a9643ea8Slogwang linux_to_bsd_sigset(&lmask, &sigmask); 178*a9643ea8Slogwang return (kern_sigsuspend(td, sigmask)); 179*a9643ea8Slogwang } 180*a9643ea8Slogwang 181*a9643ea8Slogwang int 182*a9643ea8Slogwang linux_pause(struct thread *td, struct linux_pause_args *args) 183*a9643ea8Slogwang { 184*a9643ea8Slogwang struct proc *p = td->td_proc; 185*a9643ea8Slogwang sigset_t sigmask; 186*a9643ea8Slogwang 187*a9643ea8Slogwang LINUX_CTR(pause); 188*a9643ea8Slogwang 189*a9643ea8Slogwang PROC_LOCK(p); 190*a9643ea8Slogwang sigmask = td->td_sigmask; 191*a9643ea8Slogwang PROC_UNLOCK(p); 192*a9643ea8Slogwang return (kern_sigsuspend(td, sigmask)); 193*a9643ea8Slogwang } 194*a9643ea8Slogwang 195*a9643ea8Slogwang int 196*a9643ea8Slogwang linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) 197*a9643ea8Slogwang { 198*a9643ea8Slogwang stack_t ss, oss; 199*a9643ea8Slogwang l_stack_t lss; 200*a9643ea8Slogwang int error; 201*a9643ea8Slogwang 202*a9643ea8Slogwang LINUX_CTR2(sigaltstack, "%p, %p", uap->uss, uap->uoss); 203*a9643ea8Slogwang 204*a9643ea8Slogwang if (uap->uss != NULL) { 205*a9643ea8Slogwang error = copyin(uap->uss, &lss, sizeof(l_stack_t)); 206*a9643ea8Slogwang if (error) 207*a9643ea8Slogwang return (error); 208*a9643ea8Slogwang 209*a9643ea8Slogwang ss.ss_sp = PTRIN(lss.ss_sp); 210*a9643ea8Slogwang ss.ss_size = lss.ss_size; 211*a9643ea8Slogwang ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); 212*a9643ea8Slogwang } 213*a9643ea8Slogwang error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, 214*a9643ea8Slogwang (uap->uoss != NULL) ? &oss : NULL); 215*a9643ea8Slogwang if (!error && uap->uoss != NULL) { 216*a9643ea8Slogwang lss.ss_sp = PTROUT(oss.ss_sp); 217*a9643ea8Slogwang lss.ss_size = oss.ss_size; 218*a9643ea8Slogwang lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); 219*a9643ea8Slogwang error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); 220*a9643ea8Slogwang } 221*a9643ea8Slogwang 222*a9643ea8Slogwang return (error); 223*a9643ea8Slogwang } 224*a9643ea8Slogwang 225*a9643ea8Slogwang int 226*a9643ea8Slogwang linux_arch_prctl(struct thread *td, struct linux_arch_prctl_args *args) 227*a9643ea8Slogwang { 228*a9643ea8Slogwang int error; 229*a9643ea8Slogwang struct pcb *pcb; 230*a9643ea8Slogwang 231*a9643ea8Slogwang LINUX_CTR2(arch_prctl, "0x%x, %p", args->code, args->addr); 232*a9643ea8Slogwang 233*a9643ea8Slogwang error = ENOTSUP; 234*a9643ea8Slogwang pcb = td->td_pcb; 235*a9643ea8Slogwang 236*a9643ea8Slogwang switch (args->code) { 237*a9643ea8Slogwang case LINUX_ARCH_GET_GS: 238*a9643ea8Slogwang error = copyout(&pcb->pcb_gsbase, (unsigned long *)args->addr, 239*a9643ea8Slogwang sizeof(args->addr)); 240*a9643ea8Slogwang break; 241*a9643ea8Slogwang case LINUX_ARCH_SET_GS: 242*a9643ea8Slogwang if (args->addr >= VM_MAXUSER_ADDRESS) 243*a9643ea8Slogwang return(EPERM); 244*a9643ea8Slogwang break; 245*a9643ea8Slogwang case LINUX_ARCH_GET_FS: 246*a9643ea8Slogwang error = copyout(&pcb->pcb_fsbase, (unsigned long *)args->addr, 247*a9643ea8Slogwang sizeof(args->addr)); 248*a9643ea8Slogwang break; 249*a9643ea8Slogwang case LINUX_ARCH_SET_FS: 250*a9643ea8Slogwang error = linux_set_cloned_tls(td, (void *)args->addr); 251*a9643ea8Slogwang break; 252*a9643ea8Slogwang default: 253*a9643ea8Slogwang error = EINVAL; 254*a9643ea8Slogwang } 255*a9643ea8Slogwang return (error); 256*a9643ea8Slogwang } 257*a9643ea8Slogwang 258*a9643ea8Slogwang int 259*a9643ea8Slogwang linux_set_cloned_tls(struct thread *td, void *desc) 260*a9643ea8Slogwang { 261*a9643ea8Slogwang struct pcb *pcb; 262*a9643ea8Slogwang 263*a9643ea8Slogwang if ((uint64_t)desc >= VM_MAXUSER_ADDRESS) 264*a9643ea8Slogwang return (EPERM); 265*a9643ea8Slogwang 266*a9643ea8Slogwang pcb = td->td_pcb; 267*a9643ea8Slogwang pcb->pcb_fsbase = (register_t)desc; 268*a9643ea8Slogwang td->td_frame->tf_fs = _ufssel; 269*a9643ea8Slogwang 270*a9643ea8Slogwang return (0); 271*a9643ea8Slogwang } 272