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