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