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 | } |