| File: | amd64/linux/linux_machdep.c | 
| Warning: | line 221, column 11 Copies out a struct with uncleared padding (>= 4 bytes) | 
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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$")__asm__(".ident\t\"" "$FreeBSD$" "\""); | |||
| 34 | ||||
| 35 | #include <sys/param.h> | |||
| 36 | #include <sys/capsicum.h> | |||
| 37 | #include <sys/clock.h> | |||
| 38 | #include <sys/dirent.h> | |||
| 39 | #include <sys/fcntl.h> | |||
| 40 | #include <sys/file.h> | |||
| 41 | #include <sys/filedesc.h> | |||
| 42 | #include <sys/imgact.h> | |||
| 43 | #include <sys/kernel.h> | |||
| 44 | #include <sys/ktr.h> | |||
| 45 | #include <sys/limits.h> | |||
| 46 | #include <sys/lock.h> | |||
| 47 | #include <sys/malloc.h> | |||
| 48 | #include <sys/mman.h> | |||
| 49 | #include <sys/mutex.h> | |||
| 50 | #include <sys/priv.h> | |||
| 51 | #include <sys/proc.h> | |||
| 52 | #include <sys/resource.h> | |||
| 53 | #include <sys/resourcevar.h> | |||
| 54 | #include <sys/sched.h> | |||
| 55 | #include <sys/syscallsubr.h> | |||
| 56 | #include <sys/sysproto.h> | |||
| 57 | #include <sys/systm.h> | |||
| 58 | #include <sys/unistd.h> | |||
| 59 | #include <sys/vnode.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/pmap.h> | |||
| 76 | #include <vm/vm.h> | |||
| 77 | #include <vm/vm_extern.h> | |||
| 78 | #include <vm/vm_kern.h> | |||
| 79 | #include <vm/vm_map.h> | |||
| 80 | ||||
| 81 | #include <x86/ifunc.h> | |||
| 82 | #include <x86/sysarch.h> | |||
| 83 | ||||
| 84 | #include <amd64/linux/linux.h> | |||
| 85 | #include <amd64/linux/linux_proto.h> | |||
| 86 | #include <compat/linux/linux_emul.h> | |||
| 87 | #include <compat/linux/linux_file.h> | |||
| 88 | #include <compat/linux/linux_ipc.h> | |||
| 89 | #include <compat/linux/linux_misc.h> | |||
| 90 | #include <compat/linux/linux_mmap.h> | |||
| 91 | #include <compat/linux/linux_signal.h> | |||
| 92 | #include <compat/linux/linux_util.h> | |||
| 93 | ||||
| 94 | int | |||
| 95 | linux_execve(struct thread *td, struct linux_execve_args *args) | |||
| 96 | { | |||
| 97 | struct image_args eargs; | |||
| 98 | char *path; | |||
| 99 | int error; | |||
| 100 | ||||
| 101 | 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); | |||
| 102 | ||||
| 103 | LINUX_CTR(execve); | |||
| 104 | ||||
| 105 | error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp, | |||
| 106 | args->envp); | |||
| 107 | free(path, M_TEMP); | |||
| 108 | if (error == 0) | |||
| 109 | error = linux_common_execve(td, &eargs); | |||
| 110 | return (error); | |||
| 111 | } | |||
| 112 | ||||
| 113 | int | |||
| 114 | linux_set_upcall_kse(struct thread *td, register_t stack) | |||
| 115 | { | |||
| 116 | ||||
| 117 | if (stack) | |||
| 118 | td->td_frame->tf_rsp = stack; | |||
| 119 | ||||
| 120 | /* | |||
| 121 | * The newly created Linux thread returns | |||
| 122 | * to the user space by the same path that a parent do. | |||
| 123 | */ | |||
| 124 | td->td_frame->tf_rax = 0; | |||
| 125 | return (0); | |||
| 126 | } | |||
| 127 | ||||
| 128 | int | |||
| 129 | linux_mmap2(struct thread *td, struct linux_mmap2_args *args) | |||
| 130 | { | |||
| 131 | ||||
| 132 | return (linux_mmap_common(td, PTROUT(args->addr)(uintptr_t)(args->addr), args->len, args->prot, | |||
| 133 | args->flags, args->fd, args->pgoff)); | |||
| 134 | } | |||
| 135 | ||||
| 136 | int | |||
| 137 | linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) | |||
| 138 | { | |||
| 139 | ||||
| 140 | return (linux_mprotect_common(td, PTROUT(uap->addr)(uintptr_t)(uap->addr), uap->len, uap->prot)); | |||
| 141 | } | |||
| 142 | ||||
| 143 | int | |||
| 144 | linux_iopl(struct thread *td, struct linux_iopl_args *args) | |||
| 145 | { | |||
| 146 | int error; | |||
| 147 | ||||
| 148 | LINUX_CTR(iopl); | |||
| 149 | ||||
| 150 | if (args->level > 3) | |||
| 151 | return (EINVAL22); | |||
| 152 | if ((error = priv_check(td, PRIV_IO12)) != 0) | |||
| 153 | return (error); | |||
| 154 | if ((error = securelevel_gt(td->td_ucred, 0)) != 0) | |||
| 155 | return (error); | |||
| 156 | td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL0x00003000) | | |||
| 157 | (args->level * (PSL_IOPL0x00003000 / 3)); | |||
| 158 | ||||
| 159 | return (0); | |||
| 160 | } | |||
| 161 | ||||
| 162 | int | |||
| 163 | linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) | |||
| 164 | { | |||
| 165 | l_sigset_t lmask; | |||
| 166 | sigset_t sigmask; | |||
| 167 | int error; | |||
| 168 | ||||
| 169 | LINUX_CTR2(rt_sigsuspend, "%p, %ld", | |||
| 170 | uap->newset, uap->sigsetsize); | |||
| 171 | ||||
| 172 | if (uap->sigsetsize != sizeof(l_sigset_t)) | |||
| 173 | return (EINVAL22); | |||
| 174 | ||||
| 175 | error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); | |||
| 176 | if (error) | |||
| 177 | return (error); | |||
| 178 | ||||
| 179 | linux_to_bsd_sigset(&lmask, &sigmask); | |||
| 180 | return (kern_sigsuspend(td, sigmask)); | |||
| 181 | } | |||
| 182 | ||||
| 183 | int | |||
| 184 | linux_pause(struct thread *td, struct linux_pause_args *args) | |||
| 185 | { | |||
| 186 | struct proc *p = td->td_proc; | |||
| 187 | sigset_t sigmask; | |||
| 188 | ||||
| 189 | LINUX_CTR(pause); | |||
| 190 | ||||
| 191 | PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/root/freebsd/sys/amd64/linux/linux_machdep.c"), ( 191)); | |||
| 192 | sigmask = td->td_sigmask; | |||
| 193 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/root/freebsd/sys/amd64/linux/linux_machdep.c"), ( 193)); | |||
| 194 | return (kern_sigsuspend(td, sigmask)); | |||
| 195 | } | |||
| 196 | ||||
| 197 | int | |||
| 198 | linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) | |||
| 199 | { | |||
| 200 | stack_t ss, oss; | |||
| 201 | l_stack_t lss; | |||
| 202 | int error; | |||
| 203 | ||||
| 204 | LINUX_CTR2(sigaltstack, "%p, %p", uap->uss, uap->uoss); | |||
| 205 | ||||
| 206 | if (uap->uss != NULL((void *)0)) { | |||
| 
 | ||||
| 207 | error = copyin(uap->uss, &lss, sizeof(l_stack_t)); | |||
| 208 | if (error) | |||
| 209 | return (error); | |||
| 210 | ||||
| 211 | ss.ss_sp = PTRIN(lss.ss_sp)(void *)(lss.ss_sp); | |||
| 212 | ss.ss_size = lss.ss_size; | |||
| 213 | ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); | |||
| 214 | } | |||
| 215 | error = kern_sigaltstack(td, (uap->uss != NULL((void *)0)) ? &ss : NULL((void *)0), | |||
| 216 | (uap->uoss != NULL((void *)0)) ? &oss : NULL((void *)0)); | |||
| 217 | if (!error && uap->uoss != NULL((void *)0)) { | |||
| 218 | lss.ss_sp = PTROUT(oss.ss_sp)(uintptr_t)(oss.ss_sp); | |||
| 219 | lss.ss_size = oss.ss_size; | |||
| 220 | lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); | |||
| 221 | error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); | |||
| 
 | ||||
| 222 | } | |||
| 223 | ||||
| 224 | return (error); | |||
| 225 | } | |||
| 226 | ||||
| 227 | int | |||
| 228 | linux_arch_prctl(struct thread *td, struct linux_arch_prctl_args *args) | |||
| 229 | { | |||
| 230 | int error; | |||
| 231 | struct sysarch_args bsd_args; | |||
| 232 | ||||
| 233 | LINUX_CTR2(arch_prctl, "0x%x, %p", args->code, args->addr); | |||
| 234 | ||||
| 235 | switch (args->code) { | |||
| 236 | case LINUX_ARCH_SET_GS0x1001: | |||
| 237 | bsd_args.op = AMD64_SET_GSBASE131; | |||
| 238 | bsd_args.parms = (void *)args->addr; | |||
| 239 | error = sysarch(td, &bsd_args); | |||
| 240 | if (error == EINVAL22) | |||
| 241 | error = EPERM1; | |||
| 242 | break; | |||
| 243 | case LINUX_ARCH_SET_FS0x1002: | |||
| 244 | bsd_args.op = AMD64_SET_FSBASE129; | |||
| 245 | bsd_args.parms = (void *)args->addr; | |||
| 246 | error = sysarch(td, &bsd_args); | |||
| 247 | if (error == EINVAL22) | |||
| 248 | error = EPERM1; | |||
| 249 | break; | |||
| 250 | case LINUX_ARCH_GET_FS0x1003: | |||
| 251 | bsd_args.op = AMD64_GET_FSBASE128; | |||
| 252 | bsd_args.parms = (void *)args->addr; | |||
| 253 | error = sysarch(td, &bsd_args); | |||
| 254 | break; | |||
| 255 | case LINUX_ARCH_GET_GS0x1004: | |||
| 256 | bsd_args.op = AMD64_GET_GSBASE130; | |||
| 257 | bsd_args.parms = (void *)args->addr; | |||
| 258 | error = sysarch(td, &bsd_args); | |||
| 259 | break; | |||
| 260 | default: | |||
| 261 | error = EINVAL22; | |||
| 262 | } | |||
| 263 | return (error); | |||
| 264 | } | |||
| 265 | ||||
| 266 | int | |||
| 267 | linux_set_cloned_tls(struct thread *td, void *desc) | |||
| 268 | { | |||
| 269 | struct pcb *pcb; | |||
| 270 | ||||
| 271 | 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))) | |||
| 272 | return (EPERM1); | |||
| 273 | ||||
| 274 | pcb = td->td_pcb; | |||
| 275 | pcb->pcb_fsbase = (register_t)desc; | |||
| 276 | td->td_frame->tf_fs = _ufssel; | |||
| 277 | ||||
| 278 | return (0); | |||
| 279 | } | |||
| 280 | ||||
| 281 | int futex_xchgl_nosmap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 282 | int futex_xchgl_smap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 283 | DEFINE_IFUNC(, int, futex_xchgl, (int, uint32_t *, int *), static)static int (*futex_xchgl_resolver(void))(int, uint32_t *, int *) __attribute__((__used__)); int futex_xchgl (int, uint32_t *, int *) __attribute__((ifunc("futex_xchgl" "_resolver"))); static int (*futex_xchgl_resolver(void))(int, uint32_t *, int *) | |||
| 284 | { | |||
| 285 | ||||
| 286 | return ((cpu_stdext_feature & CPUID_STDEXT_SMAP0x00100000) != 0 ? | |||
| 287 | futex_xchgl_smap : futex_xchgl_nosmap); | |||
| 288 | } | |||
| 289 | ||||
| 290 | int futex_addl_nosmap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 291 | int futex_addl_smap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 292 | DEFINE_IFUNC(, int, futex_addl, (int, uint32_t *, int *), static)static int (*futex_addl_resolver(void))(int, uint32_t *, int * ) __attribute__((__used__)); int futex_addl (int, uint32_t *, int *) __attribute__((ifunc("futex_addl" "_resolver"))); static int (*futex_addl_resolver(void))(int, uint32_t *, int *) | |||
| 293 | { | |||
| 294 | ||||
| 295 | return ((cpu_stdext_feature & CPUID_STDEXT_SMAP0x00100000) != 0 ? | |||
| 296 | futex_addl_smap : futex_addl_nosmap); | |||
| 297 | } | |||
| 298 | ||||
| 299 | int futex_orl_nosmap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 300 | int futex_orl_smap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 301 | DEFINE_IFUNC(, int, futex_orl, (int, uint32_t *, int *), static)static int (*futex_orl_resolver(void))(int, uint32_t *, int * ) __attribute__((__used__)); int futex_orl (int, uint32_t *, int *) __attribute__((ifunc("futex_orl" "_resolver"))); static int (*futex_orl_resolver(void))(int, uint32_t *, int *) | |||
| 302 | { | |||
| 303 | ||||
| 304 | return ((cpu_stdext_feature & CPUID_STDEXT_SMAP0x00100000) != 0 ? | |||
| 305 | futex_orl_smap : futex_orl_nosmap); | |||
| 306 | } | |||
| 307 | ||||
| 308 | int futex_andl_nosmap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 309 | int futex_andl_smap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 310 | DEFINE_IFUNC(, int, futex_andl, (int, uint32_t *, int *), static)static int (*futex_andl_resolver(void))(int, uint32_t *, int * ) __attribute__((__used__)); int futex_andl (int, uint32_t *, int *) __attribute__((ifunc("futex_andl" "_resolver"))); static int (*futex_andl_resolver(void))(int, uint32_t *, int *) | |||
| 311 | { | |||
| 312 | ||||
| 313 | return ((cpu_stdext_feature & CPUID_STDEXT_SMAP0x00100000) != 0 ? | |||
| 314 | futex_andl_smap : futex_andl_nosmap); | |||
| 315 | } | |||
| 316 | ||||
| 317 | int futex_xorl_nosmap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 318 | int futex_xorl_smap(int oparg, uint32_t *uaddr, int *oldval); | |||
| 319 | DEFINE_IFUNC(, int, futex_xorl, (int, uint32_t *, int *), static)static int (*futex_xorl_resolver(void))(int, uint32_t *, int * ) __attribute__((__used__)); int futex_xorl (int, uint32_t *, int *) __attribute__((ifunc("futex_xorl" "_resolver"))); static int (*futex_xorl_resolver(void))(int, uint32_t *, int *) | |||
| 320 | { | |||
| 321 | ||||
| 322 | return ((cpu_stdext_feature & CPUID_STDEXT_SMAP0x00100000) != 0 ? | |||
| 323 | futex_xorl_smap : futex_xorl_nosmap); | |||
| 324 | } |