diff options
author | Richard Weinberger <richard@nod.at> | 2015-03-18 16:31:27 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2015-04-13 15:00:53 -0400 |
commit | d0b5e15f0c0fdd759dd3dd48dc2dc2e7199e0da0 (patch) | |
tree | 7b833b85c0e2eabf6b38d8b94875b430554afae7 /arch | |
parent | aaeac66b1a02d399ec8ee63e8d617c1d601ea353 (diff) |
um: Remove SKAS3/4 support
Before we had SKAS0 UML had two modes of operation
TT (tracing thread) and SKAS3/4 (separated kernel address space).
TT was known to be insecure and got removed a long time ago.
SKAS3/4 required a few (3 or 4) patches on the host side which never went
mainline. The last host patch is 10 years old.
With SKAS0 mode (separated kernel address space using 0 host patches),
default since 2005, SKAS3/4 is obsolete and can be removed.
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/um/include/shared/os.h | 2 | ||||
-rw-r--r-- | arch/um/include/shared/skas/proc_mm.h | 44 | ||||
-rw-r--r-- | arch/um/include/shared/skas/skas.h | 3 | ||||
-rw-r--r-- | arch/um/include/shared/skas_ptrace.h | 14 | ||||
-rw-r--r-- | arch/um/kernel/ptrace.c | 32 | ||||
-rw-r--r-- | arch/um/kernel/reboot.c | 35 | ||||
-rw-r--r-- | arch/um/kernel/skas/mmu.c | 68 | ||||
-rw-r--r-- | arch/um/kernel/skas/process.c | 27 | ||||
-rw-r--r-- | arch/um/kernel/trap.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/um_arch.c | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/process.c | 16 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/mem.c | 100 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 200 | ||||
-rw-r--r-- | arch/um/os-Linux/start_up.c | 154 | ||||
-rw-r--r-- | arch/x86/um/ldt.c | 227 | ||||
-rw-r--r-- | arch/x86/um/shared/sysdep/faultinfo_32.h | 3 | ||||
-rw-r--r-- | arch/x86/um/shared/sysdep/faultinfo_64.h | 3 | ||||
-rw-r--r-- | arch/x86/um/shared/sysdep/skas_ptrace.h | 22 |
18 files changed, 148 insertions, 814 deletions
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 08eec0b691b0..d824528f6f62 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h | |||
@@ -174,7 +174,6 @@ extern unsigned long long os_makedev(unsigned major, unsigned minor); | |||
174 | 174 | ||
175 | /* start_up.c */ | 175 | /* start_up.c */ |
176 | extern void os_early_checks(void); | 176 | extern void os_early_checks(void); |
177 | extern void can_do_skas(void); | ||
178 | extern void os_check_bugs(void); | 177 | extern void os_check_bugs(void); |
179 | extern void check_host_supports_tls(int *supports_tls, int *tls_min); | 178 | extern void check_host_supports_tls(int *supports_tls, int *tls_min); |
180 | 179 | ||
@@ -187,7 +186,6 @@ extern int os_process_parent(int pid); | |||
187 | extern void os_stop_process(int pid); | 186 | extern void os_stop_process(int pid); |
188 | extern void os_kill_process(int pid, int reap_child); | 187 | extern void os_kill_process(int pid, int reap_child); |
189 | extern void os_kill_ptraced_process(int pid, int reap_child); | 188 | extern void os_kill_ptraced_process(int pid, int reap_child); |
190 | extern long os_ptrace_ldt(long pid, long addr, long data); | ||
191 | 189 | ||
192 | extern int os_getpid(void); | 190 | extern int os_getpid(void); |
193 | extern int os_getpgrp(void); | 191 | extern int os_getpgrp(void); |
diff --git a/arch/um/include/shared/skas/proc_mm.h b/arch/um/include/shared/skas/proc_mm.h deleted file mode 100644 index 902809209603..000000000000 --- a/arch/um/include/shared/skas/proc_mm.h +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __SKAS_PROC_MM_H | ||
7 | #define __SKAS_PROC_MM_H | ||
8 | |||
9 | #define MM_MMAP 54 | ||
10 | #define MM_MUNMAP 55 | ||
11 | #define MM_MPROTECT 56 | ||
12 | #define MM_COPY_SEGMENTS 57 | ||
13 | |||
14 | struct mm_mmap { | ||
15 | unsigned long addr; | ||
16 | unsigned long len; | ||
17 | unsigned long prot; | ||
18 | unsigned long flags; | ||
19 | unsigned long fd; | ||
20 | unsigned long offset; | ||
21 | }; | ||
22 | |||
23 | struct mm_munmap { | ||
24 | unsigned long addr; | ||
25 | unsigned long len; | ||
26 | }; | ||
27 | |||
28 | struct mm_mprotect { | ||
29 | unsigned long addr; | ||
30 | unsigned long len; | ||
31 | unsigned int prot; | ||
32 | }; | ||
33 | |||
34 | struct proc_mm_op { | ||
35 | int op; | ||
36 | union { | ||
37 | struct mm_mmap mmap; | ||
38 | struct mm_munmap munmap; | ||
39 | struct mm_mprotect mprotect; | ||
40 | int copy_segments; | ||
41 | } u; | ||
42 | }; | ||
43 | |||
44 | #endif | ||
diff --git a/arch/um/include/shared/skas/skas.h b/arch/um/include/shared/skas/skas.h index c45df961c874..911f3c45ad1f 100644 --- a/arch/um/include/shared/skas/skas.h +++ b/arch/um/include/shared/skas/skas.h | |||
@@ -9,13 +9,10 @@ | |||
9 | #include <sysdep/ptrace.h> | 9 | #include <sysdep/ptrace.h> |
10 | 10 | ||
11 | extern int userspace_pid[]; | 11 | extern int userspace_pid[]; |
12 | extern int proc_mm, ptrace_faultinfo, ptrace_ldt; | ||
13 | extern int skas_needs_stub; | ||
14 | 12 | ||
15 | extern int user_thread(unsigned long stack, int flags); | 13 | extern int user_thread(unsigned long stack, int flags); |
16 | extern void new_thread_handler(void); | 14 | extern void new_thread_handler(void); |
17 | extern void handle_syscall(struct uml_pt_regs *regs); | 15 | extern void handle_syscall(struct uml_pt_regs *regs); |
18 | extern int new_mm(unsigned long stack); | ||
19 | extern long execute_syscall_skas(void *r); | 16 | extern long execute_syscall_skas(void *r); |
20 | extern unsigned long current_stub_stack(void); | 17 | extern unsigned long current_stub_stack(void); |
21 | 18 | ||
diff --git a/arch/um/include/shared/skas_ptrace.h b/arch/um/include/shared/skas_ptrace.h deleted file mode 100644 index 630a9c92b93c..000000000000 --- a/arch/um/include/shared/skas_ptrace.h +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __SKAS_PTRACE_H | ||
7 | #define __SKAS_PTRACE_H | ||
8 | |||
9 | #define PTRACE_FAULTINFO 52 | ||
10 | #define PTRACE_SWITCH_MM 55 | ||
11 | |||
12 | #include <sysdep/skas_ptrace.h> | ||
13 | |||
14 | #endif | ||
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 62435ef003d9..174ee5017264 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
@@ -8,9 +8,6 @@ | |||
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include <linux/tracehook.h> | 9 | #include <linux/tracehook.h> |
10 | #include <asm/uaccess.h> | 10 | #include <asm/uaccess.h> |
11 | #include <skas_ptrace.h> | ||
12 | |||
13 | |||
14 | 11 | ||
15 | void user_enable_single_step(struct task_struct *child) | 12 | void user_enable_single_step(struct task_struct *child) |
16 | { | 13 | { |
@@ -104,35 +101,6 @@ long arch_ptrace(struct task_struct *child, long request, | |||
104 | ret = ptrace_set_thread_area(child, addr, vp); | 101 | ret = ptrace_set_thread_area(child, addr, vp); |
105 | break; | 102 | break; |
106 | 103 | ||
107 | case PTRACE_FAULTINFO: { | ||
108 | /* | ||
109 | * Take the info from thread->arch->faultinfo, | ||
110 | * but transfer max. sizeof(struct ptrace_faultinfo). | ||
111 | * On i386, ptrace_faultinfo is smaller! | ||
112 | */ | ||
113 | ret = copy_to_user(p, &child->thread.arch.faultinfo, | ||
114 | sizeof(struct ptrace_faultinfo)) ? | ||
115 | -EIO : 0; | ||
116 | break; | ||
117 | } | ||
118 | |||
119 | #ifdef PTRACE_LDT | ||
120 | case PTRACE_LDT: { | ||
121 | struct ptrace_ldt ldt; | ||
122 | |||
123 | if (copy_from_user(&ldt, p, sizeof(ldt))) { | ||
124 | ret = -EIO; | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * This one is confusing, so just punt and return -EIO for | ||
130 | * now | ||
131 | */ | ||
132 | ret = -EIO; | ||
133 | break; | ||
134 | } | ||
135 | #endif | ||
136 | default: | 104 | default: |
137 | ret = ptrace_request(child, request, addr, data); | 105 | ret = ptrace_request(child, request, addr, data); |
138 | if (ret == -EIO) | 106 | if (ret == -EIO) |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index ced8903921ae..9bdf67a092a5 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
@@ -15,28 +15,21 @@ void (*pm_power_off)(void); | |||
15 | 15 | ||
16 | static void kill_off_processes(void) | 16 | static void kill_off_processes(void) |
17 | { | 17 | { |
18 | if (proc_mm) | 18 | struct task_struct *p; |
19 | /* | 19 | int pid; |
20 | * FIXME: need to loop over userspace_pids | 20 | |
21 | */ | 21 | read_lock(&tasklist_lock); |
22 | os_kill_ptraced_process(userspace_pid[0], 1); | 22 | for_each_process(p) { |
23 | else { | 23 | struct task_struct *t; |
24 | struct task_struct *p; | 24 | |
25 | int pid; | 25 | t = find_lock_task_mm(p); |
26 | 26 | if (!t) | |
27 | read_lock(&tasklist_lock); | 27 | continue; |
28 | for_each_process(p) { | 28 | pid = t->mm->context.id.u.pid; |
29 | struct task_struct *t; | 29 | task_unlock(t); |
30 | 30 | os_kill_ptraced_process(pid, 1); | |
31 | t = find_lock_task_mm(p); | ||
32 | if (!t) | ||
33 | continue; | ||
34 | pid = t->mm->context.id.u.pid; | ||
35 | task_unlock(t); | ||
36 | os_kill_ptraced_process(pid, 1); | ||
37 | } | ||
38 | read_unlock(&tasklist_lock); | ||
39 | } | 31 | } |
32 | read_unlock(&tasklist_lock); | ||
40 | } | 33 | } |
41 | 34 | ||
42 | void uml_cleanup(void) | 35 | void uml_cleanup(void) |
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 007d5503f49b..94abdcc1d6ad 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c | |||
@@ -54,35 +54,22 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) | |||
54 | unsigned long stack = 0; | 54 | unsigned long stack = 0; |
55 | int ret = -ENOMEM; | 55 | int ret = -ENOMEM; |
56 | 56 | ||
57 | if (skas_needs_stub) { | 57 | stack = get_zeroed_page(GFP_KERNEL); |
58 | stack = get_zeroed_page(GFP_KERNEL); | 58 | if (stack == 0) |
59 | if (stack == 0) | 59 | goto out; |
60 | goto out; | ||
61 | } | ||
62 | 60 | ||
63 | to_mm->id.stack = stack; | 61 | to_mm->id.stack = stack; |
64 | if (current->mm != NULL && current->mm != &init_mm) | 62 | if (current->mm != NULL && current->mm != &init_mm) |
65 | from_mm = ¤t->mm->context; | 63 | from_mm = ¤t->mm->context; |
66 | 64 | ||
67 | if (proc_mm) { | 65 | if (from_mm) |
68 | ret = new_mm(stack); | 66 | to_mm->id.u.pid = copy_context_skas0(stack, |
69 | if (ret < 0) { | 67 | from_mm->id.u.pid); |
70 | printk(KERN_ERR "init_new_context_skas - " | 68 | else to_mm->id.u.pid = start_userspace(stack); |
71 | "new_mm failed, errno = %d\n", ret); | 69 | |
72 | goto out_free; | 70 | if (to_mm->id.u.pid < 0) { |
73 | } | 71 | ret = to_mm->id.u.pid; |
74 | to_mm->id.u.mm_fd = ret; | 72 | goto out_free; |
75 | } | ||
76 | else { | ||
77 | if (from_mm) | ||
78 | to_mm->id.u.pid = copy_context_skas0(stack, | ||
79 | from_mm->id.u.pid); | ||
80 | else to_mm->id.u.pid = start_userspace(stack); | ||
81 | |||
82 | if (to_mm->id.u.pid < 0) { | ||
83 | ret = to_mm->id.u.pid; | ||
84 | goto out_free; | ||
85 | } | ||
86 | } | 73 | } |
87 | 74 | ||
88 | ret = init_new_ldt(to_mm, from_mm); | 75 | ret = init_new_ldt(to_mm, from_mm); |
@@ -105,9 +92,6 @@ void uml_setup_stubs(struct mm_struct *mm) | |||
105 | { | 92 | { |
106 | int err, ret; | 93 | int err, ret; |
107 | 94 | ||
108 | if (!skas_needs_stub) | ||
109 | return; | ||
110 | |||
111 | ret = init_stub_pte(mm, STUB_CODE, | 95 | ret = init_stub_pte(mm, STUB_CODE, |
112 | (unsigned long) &__syscall_stub_start); | 96 | (unsigned long) &__syscall_stub_start); |
113 | if (ret) | 97 | if (ret) |
@@ -154,25 +138,19 @@ void destroy_context(struct mm_struct *mm) | |||
154 | { | 138 | { |
155 | struct mm_context *mmu = &mm->context; | 139 | struct mm_context *mmu = &mm->context; |
156 | 140 | ||
157 | if (proc_mm) | 141 | /* |
158 | os_close_file(mmu->id.u.mm_fd); | 142 | * If init_new_context wasn't called, this will be |
159 | else { | 143 | * zero, resulting in a kill(0), which will result in the |
160 | /* | 144 | * whole UML suddenly dying. Also, cover negative and |
161 | * If init_new_context wasn't called, this will be | 145 | * 1 cases, since they shouldn't happen either. |
162 | * zero, resulting in a kill(0), which will result in the | 146 | */ |
163 | * whole UML suddenly dying. Also, cover negative and | 147 | if (mmu->id.u.pid < 2) { |
164 | * 1 cases, since they shouldn't happen either. | 148 | printk(KERN_ERR "corrupt mm_context - pid = %d\n", |
165 | */ | 149 | mmu->id.u.pid); |
166 | if (mmu->id.u.pid < 2) { | 150 | return; |
167 | printk(KERN_ERR "corrupt mm_context - pid = %d\n", | ||
168 | mmu->id.u.pid); | ||
169 | return; | ||
170 | } | ||
171 | os_kill_ptraced_process(mmu->id.u.pid, 1); | ||
172 | } | 151 | } |
152 | os_kill_ptraced_process(mmu->id.u.pid, 1); | ||
173 | 153 | ||
174 | if (skas_needs_stub) | 154 | free_page(mmu->id.stack); |
175 | free_page(mmu->id.stack); | ||
176 | |||
177 | free_ldt(mmu); | 155 | free_ldt(mmu); |
178 | } | 156 | } |
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 4da11b3c8ddb..082955d694f3 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c | |||
@@ -10,25 +10,6 @@ | |||
10 | #include <os.h> | 10 | #include <os.h> |
11 | #include <skas.h> | 11 | #include <skas.h> |
12 | 12 | ||
13 | int new_mm(unsigned long stack) | ||
14 | { | ||
15 | int fd, err; | ||
16 | |||
17 | fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); | ||
18 | if (fd < 0) | ||
19 | return fd; | ||
20 | |||
21 | if (skas_needs_stub) { | ||
22 | err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack); | ||
23 | if (err) { | ||
24 | os_close_file(fd); | ||
25 | return err; | ||
26 | } | ||
27 | } | ||
28 | |||
29 | return fd; | ||
30 | } | ||
31 | |||
32 | extern void start_kernel(void); | 13 | extern void start_kernel(void); |
33 | 14 | ||
34 | static int __init start_kernel_proc(void *unused) | 15 | static int __init start_kernel_proc(void *unused) |
@@ -55,14 +36,6 @@ int __init start_uml(void) | |||
55 | { | 36 | { |
56 | stack_protections((unsigned long) &cpu0_irqstack); | 37 | stack_protections((unsigned long) &cpu0_irqstack); |
57 | set_sigstack(cpu0_irqstack, THREAD_SIZE); | 38 | set_sigstack(cpu0_irqstack, THREAD_SIZE); |
58 | if (proc_mm) { | ||
59 | userspace_pid[0] = start_userspace(0); | ||
60 | if (userspace_pid[0] < 0) { | ||
61 | printf("start_uml - start_userspace returned %d\n", | ||
62 | userspace_pid[0]); | ||
63 | exit(1); | ||
64 | } | ||
65 | } | ||
66 | 39 | ||
67 | init_new_thread_signals(); | 40 | init_new_thread_signals(); |
68 | 41 | ||
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 209617302df8..8e4daf44e980 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -220,7 +220,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, | |||
220 | panic("Segfault with no mm"); | 220 | panic("Segfault with no mm"); |
221 | } | 221 | } |
222 | 222 | ||
223 | if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) | 223 | if (SEGV_IS_FIXABLE(&fi)) |
224 | err = handle_page_fault(address, ip, is_write, is_user, | 224 | err = handle_page_fault(address, ip, is_write, is_user, |
225 | &si.si_code); | 225 | &si.si_code); |
226 | else { | 226 | else { |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 9274eae6ae7b..dbd5bda1f184 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
@@ -268,7 +268,6 @@ int __init linux_main(int argc, char **argv) | |||
268 | unsigned long stack; | 268 | unsigned long stack; |
269 | unsigned int i; | 269 | unsigned int i; |
270 | int add; | 270 | int add; |
271 | char * mode; | ||
272 | 271 | ||
273 | for (i = 1; i < argc; i++) { | 272 | for (i = 1; i < argc; i++) { |
274 | if ((i == 1) && (argv[i][0] == ' ')) | 273 | if ((i == 1) && (argv[i][0] == ' ')) |
@@ -291,15 +290,6 @@ int __init linux_main(int argc, char **argv) | |||
291 | /* OS sanity checks that need to happen before the kernel runs */ | 290 | /* OS sanity checks that need to happen before the kernel runs */ |
292 | os_early_checks(); | 291 | os_early_checks(); |
293 | 292 | ||
294 | can_do_skas(); | ||
295 | |||
296 | if (proc_mm && ptrace_faultinfo) | ||
297 | mode = "SKAS3"; | ||
298 | else | ||
299 | mode = "SKAS0"; | ||
300 | |||
301 | printf("UML running in %s mode\n", mode); | ||
302 | |||
303 | brk_start = (unsigned long) sbrk(0); | 293 | brk_start = (unsigned long) sbrk(0); |
304 | 294 | ||
305 | /* | 295 | /* |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 33496fe2bb52..8408aba915b2 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <init.h> | 16 | #include <init.h> |
17 | #include <longjmp.h> | 17 | #include <longjmp.h> |
18 | #include <os.h> | 18 | #include <os.h> |
19 | #include <skas_ptrace.h> | ||
20 | 19 | ||
21 | #define ARBITRARY_ADDR -1 | 20 | #define ARBITRARY_ADDR -1 |
22 | #define FAILURE_PID -1 | 21 | #define FAILURE_PID -1 |
@@ -102,21 +101,6 @@ void os_kill_process(int pid, int reap_child) | |||
102 | CATCH_EINTR(waitpid(pid, NULL, __WALL)); | 101 | CATCH_EINTR(waitpid(pid, NULL, __WALL)); |
103 | } | 102 | } |
104 | 103 | ||
105 | /* This is here uniquely to have access to the userspace errno, i.e. the one | ||
106 | * used by ptrace in case of error. | ||
107 | */ | ||
108 | |||
109 | long os_ptrace_ldt(long pid, long addr, long data) | ||
110 | { | ||
111 | int ret; | ||
112 | |||
113 | ret = ptrace(PTRACE_LDT, pid, addr, data); | ||
114 | |||
115 | if (ret < 0) | ||
116 | return -errno; | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | /* Kill off a ptraced child by all means available. kill it normally first, | 104 | /* Kill off a ptraced child by all means available. kill it normally first, |
121 | * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from | 105 | * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from |
122 | * which it can't exit directly. | 106 | * which it can't exit directly. |
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 689b18db798f..e7f8c945a573 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <as-layout.h> | 12 | #include <as-layout.h> |
13 | #include <mm_id.h> | 13 | #include <mm_id.h> |
14 | #include <os.h> | 14 | #include <os.h> |
15 | #include <proc_mm.h> | ||
16 | #include <ptrace_user.h> | 15 | #include <ptrace_user.h> |
17 | #include <registers.h> | 16 | #include <registers.h> |
18 | #include <skas.h> | 17 | #include <skas.h> |
@@ -46,8 +45,6 @@ static int __init init_syscall_regs(void) | |||
46 | 45 | ||
47 | __initcall(init_syscall_regs); | 46 | __initcall(init_syscall_regs); |
48 | 47 | ||
49 | extern int proc_mm; | ||
50 | |||
51 | static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | 48 | static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) |
52 | { | 49 | { |
53 | int n, i; | 50 | int n, i; |
@@ -56,10 +53,6 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | |||
56 | unsigned long * syscall; | 53 | unsigned long * syscall; |
57 | int err, pid = mm_idp->u.pid; | 54 | int err, pid = mm_idp->u.pid; |
58 | 55 | ||
59 | if (proc_mm) | ||
60 | /* FIXME: Need to look up userspace_pid by cpu */ | ||
61 | pid = userspace_pid[0]; | ||
62 | |||
63 | n = ptrace_setregs(pid, syscall_regs); | 56 | n = ptrace_setregs(pid, syscall_regs); |
64 | if (n < 0) { | 57 | if (n < 0) { |
65 | printk(UM_KERN_ERR "Registers - \n"); | 58 | printk(UM_KERN_ERR "Registers - \n"); |
@@ -178,38 +171,12 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, | |||
178 | int phys_fd, unsigned long long offset, int done, void **data) | 171 | int phys_fd, unsigned long long offset, int done, void **data) |
179 | { | 172 | { |
180 | int ret; | 173 | int ret; |
174 | unsigned long args[] = { virt, len, prot, | ||
175 | MAP_SHARED | MAP_FIXED, phys_fd, | ||
176 | MMAP_OFFSET(offset) }; | ||
181 | 177 | ||
182 | if (proc_mm) { | 178 | ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, |
183 | struct proc_mm_op map; | 179 | data, done); |
184 | int fd = mm_idp->u.mm_fd; | ||
185 | |||
186 | map = ((struct proc_mm_op) { .op = MM_MMAP, | ||
187 | .u = | ||
188 | { .mmap = | ||
189 | { .addr = virt, | ||
190 | .len = len, | ||
191 | .prot = prot, | ||
192 | .flags = MAP_SHARED | | ||
193 | MAP_FIXED, | ||
194 | .fd = phys_fd, | ||
195 | .offset= offset | ||
196 | } } } ); | ||
197 | CATCH_EINTR(ret = write(fd, &map, sizeof(map))); | ||
198 | if (ret != sizeof(map)) { | ||
199 | ret = -errno; | ||
200 | printk(UM_KERN_ERR "map : /proc/mm map failed, " | ||
201 | "err = %d\n", -ret); | ||
202 | } | ||
203 | else ret = 0; | ||
204 | } | ||
205 | else { | ||
206 | unsigned long args[] = { virt, len, prot, | ||
207 | MAP_SHARED | MAP_FIXED, phys_fd, | ||
208 | MMAP_OFFSET(offset) }; | ||
209 | |||
210 | ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, | ||
211 | data, done); | ||
212 | } | ||
213 | 180 | ||
214 | return ret; | 181 | return ret; |
215 | } | 182 | } |
@@ -218,32 +185,11 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
218 | int done, void **data) | 185 | int done, void **data) |
219 | { | 186 | { |
220 | int ret; | 187 | int ret; |
188 | unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, | ||
189 | 0 }; | ||
221 | 190 | ||
222 | if (proc_mm) { | 191 | ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, |
223 | struct proc_mm_op unmap; | 192 | data, done); |
224 | int fd = mm_idp->u.mm_fd; | ||
225 | |||
226 | unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, | ||
227 | .u = | ||
228 | { .munmap = | ||
229 | { .addr = | ||
230 | (unsigned long) addr, | ||
231 | .len = len } } } ); | ||
232 | CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); | ||
233 | if (ret != sizeof(unmap)) { | ||
234 | ret = -errno; | ||
235 | printk(UM_KERN_ERR "unmap - proc_mm write returned " | ||
236 | "%d\n", ret); | ||
237 | } | ||
238 | else ret = 0; | ||
239 | } | ||
240 | else { | ||
241 | unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, | ||
242 | 0 }; | ||
243 | |||
244 | ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, | ||
245 | data, done); | ||
246 | } | ||
247 | 193 | ||
248 | return ret; | 194 | return ret; |
249 | } | 195 | } |
@@ -251,33 +197,11 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
251 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | 197 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, |
252 | unsigned int prot, int done, void **data) | 198 | unsigned int prot, int done, void **data) |
253 | { | 199 | { |
254 | struct proc_mm_op protect; | ||
255 | int ret; | 200 | int ret; |
201 | unsigned long args[] = { addr, len, prot, 0, 0, 0 }; | ||
256 | 202 | ||
257 | if (proc_mm) { | 203 | ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, |
258 | int fd = mm_idp->u.mm_fd; | 204 | data, done); |
259 | |||
260 | protect = ((struct proc_mm_op) { .op = MM_MPROTECT, | ||
261 | .u = | ||
262 | { .mprotect = | ||
263 | { .addr = | ||
264 | (unsigned long) addr, | ||
265 | .len = len, | ||
266 | .prot = prot } } } ); | ||
267 | |||
268 | CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); | ||
269 | if (ret != sizeof(protect)) { | ||
270 | ret = -errno; | ||
271 | printk(UM_KERN_ERR "protect failed, err = %d", -ret); | ||
272 | } | ||
273 | else ret = 0; | ||
274 | } | ||
275 | else { | ||
276 | unsigned long args[] = { addr, len, prot, 0, 0, 0 }; | ||
277 | |||
278 | ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, | ||
279 | data, done); | ||
280 | } | ||
281 | 205 | ||
282 | return ret; | 206 | return ret; |
283 | } | 207 | } |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 908579f2b0ab..50ebeae5cbb3 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -16,11 +16,9 @@ | |||
16 | #include <kern_util.h> | 16 | #include <kern_util.h> |
17 | #include <mem.h> | 17 | #include <mem.h> |
18 | #include <os.h> | 18 | #include <os.h> |
19 | #include <proc_mm.h> | ||
20 | #include <ptrace_user.h> | 19 | #include <ptrace_user.h> |
21 | #include <registers.h> | 20 | #include <registers.h> |
22 | #include <skas.h> | 21 | #include <skas.h> |
23 | #include <skas_ptrace.h> | ||
24 | #include <sysdep/stub.h> | 22 | #include <sysdep/stub.h> |
25 | 23 | ||
26 | int is_skas_winch(int pid, int fd, void *data) | 24 | int is_skas_winch(int pid, int fd, void *data) |
@@ -91,50 +89,33 @@ extern unsigned long current_stub_stack(void); | |||
91 | static void get_skas_faultinfo(int pid, struct faultinfo *fi) | 89 | static void get_skas_faultinfo(int pid, struct faultinfo *fi) |
92 | { | 90 | { |
93 | int err; | 91 | int err; |
92 | unsigned long fpregs[FP_SIZE]; | ||
94 | 93 | ||
95 | if (ptrace_faultinfo) { | 94 | err = get_fp_registers(pid, fpregs); |
96 | err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); | 95 | if (err < 0) { |
97 | if (err) { | 96 | printk(UM_KERN_ERR "save_fp_registers returned %d\n", |
98 | printk(UM_KERN_ERR "get_skas_faultinfo - " | 97 | err); |
99 | "PTRACE_FAULTINFO failed, errno = %d\n", errno); | 98 | fatal_sigsegv(); |
100 | fatal_sigsegv(); | ||
101 | } | ||
102 | |||
103 | /* Special handling for i386, which has different structs */ | ||
104 | if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) | ||
105 | memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, | ||
106 | sizeof(struct faultinfo) - | ||
107 | sizeof(struct ptrace_faultinfo)); | ||
108 | } | 99 | } |
109 | else { | 100 | err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); |
110 | unsigned long fpregs[FP_SIZE]; | 101 | if (err) { |
111 | 102 | printk(UM_KERN_ERR "Failed to continue stub, pid = %d, " | |
112 | err = get_fp_registers(pid, fpregs); | 103 | "errno = %d\n", pid, errno); |
113 | if (err < 0) { | 104 | fatal_sigsegv(); |
114 | printk(UM_KERN_ERR "save_fp_registers returned %d\n", | 105 | } |
115 | err); | 106 | wait_stub_done(pid); |
116 | fatal_sigsegv(); | ||
117 | } | ||
118 | err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); | ||
119 | if (err) { | ||
120 | printk(UM_KERN_ERR "Failed to continue stub, pid = %d, " | ||
121 | "errno = %d\n", pid, errno); | ||
122 | fatal_sigsegv(); | ||
123 | } | ||
124 | wait_stub_done(pid); | ||
125 | 107 | ||
126 | /* | 108 | /* |
127 | * faultinfo is prepared by the stub-segv-handler at start of | 109 | * faultinfo is prepared by the stub-segv-handler at start of |
128 | * the stub stack page. We just have to copy it. | 110 | * the stub stack page. We just have to copy it. |
129 | */ | 111 | */ |
130 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); | 112 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); |
131 | 113 | ||
132 | err = put_fp_registers(pid, fpregs); | 114 | err = put_fp_registers(pid, fpregs); |
133 | if (err < 0) { | 115 | if (err < 0) { |
134 | printk(UM_KERN_ERR "put_fp_registers returned %d\n", | 116 | printk(UM_KERN_ERR "put_fp_registers returned %d\n", |
135 | err); | 117 | err); |
136 | fatal_sigsegv(); | 118 | fatal_sigsegv(); |
137 | } | ||
138 | } | 119 | } |
139 | } | 120 | } |
140 | 121 | ||
@@ -198,7 +179,8 @@ extern int __syscall_stub_start; | |||
198 | static int userspace_tramp(void *stack) | 179 | static int userspace_tramp(void *stack) |
199 | { | 180 | { |
200 | void *addr; | 181 | void *addr; |
201 | int err; | 182 | int err, fd; |
183 | unsigned long long offset; | ||
202 | 184 | ||
203 | ptrace(PTRACE_TRACEME, 0, 0, 0); | 185 | ptrace(PTRACE_TRACEME, 0, 0, 0); |
204 | 186 | ||
@@ -211,36 +193,32 @@ static int userspace_tramp(void *stack) | |||
211 | exit(1); | 193 | exit(1); |
212 | } | 194 | } |
213 | 195 | ||
214 | if (!proc_mm) { | 196 | /* |
215 | /* | 197 | * This has a pte, but it can't be mapped in with the usual |
216 | * This has a pte, but it can't be mapped in with the usual | 198 | * tlb_flush mechanism because this is part of that mechanism |
217 | * tlb_flush mechanism because this is part of that mechanism | 199 | */ |
218 | */ | 200 | fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); |
219 | int fd; | 201 | addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, |
220 | unsigned long long offset; | 202 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); |
221 | fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); | 203 | if (addr == MAP_FAILED) { |
222 | addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, | 204 | printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, " |
223 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); | 205 | "errno = %d\n", STUB_CODE, errno); |
206 | exit(1); | ||
207 | } | ||
208 | |||
209 | if (stack != NULL) { | ||
210 | fd = phys_mapping(to_phys(stack), &offset); | ||
211 | addr = mmap((void *) STUB_DATA, | ||
212 | UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, | ||
213 | MAP_FIXED | MAP_SHARED, fd, offset); | ||
224 | if (addr == MAP_FAILED) { | 214 | if (addr == MAP_FAILED) { |
225 | printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, " | 215 | printk(UM_KERN_ERR "mapping segfault stack " |
226 | "errno = %d\n", STUB_CODE, errno); | 216 | "at 0x%lx failed, errno = %d\n", |
217 | STUB_DATA, errno); | ||
227 | exit(1); | 218 | exit(1); |
228 | } | 219 | } |
229 | |||
230 | if (stack != NULL) { | ||
231 | fd = phys_mapping(to_phys(stack), &offset); | ||
232 | addr = mmap((void *) STUB_DATA, | ||
233 | UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, | ||
234 | MAP_FIXED | MAP_SHARED, fd, offset); | ||
235 | if (addr == MAP_FAILED) { | ||
236 | printk(UM_KERN_ERR "mapping segfault stack " | ||
237 | "at 0x%lx failed, errno = %d\n", | ||
238 | STUB_DATA, errno); | ||
239 | exit(1); | ||
240 | } | ||
241 | } | ||
242 | } | 220 | } |
243 | if (!ptrace_faultinfo && (stack != NULL)) { | 221 | if (stack != NULL) { |
244 | struct sigaction sa; | 222 | struct sigaction sa; |
245 | 223 | ||
246 | unsigned long v = STUB_CODE + | 224 | unsigned long v = STUB_CODE + |
@@ -286,11 +264,7 @@ int start_userspace(unsigned long stub_stack) | |||
286 | 264 | ||
287 | sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); | 265 | sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); |
288 | 266 | ||
289 | flags = CLONE_FILES; | 267 | flags = CLONE_FILES | SIGCHLD; |
290 | if (proc_mm) | ||
291 | flags |= CLONE_VM; | ||
292 | else | ||
293 | flags |= SIGCHLD; | ||
294 | 268 | ||
295 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); | 269 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); |
296 | if (pid < 0) { | 270 | if (pid < 0) { |
@@ -413,8 +387,7 @@ void userspace(struct uml_pt_regs *regs) | |||
413 | 387 | ||
414 | switch (sig) { | 388 | switch (sig) { |
415 | case SIGSEGV: | 389 | case SIGSEGV: |
416 | if (PTRACE_FULL_FAULTINFO || | 390 | if (PTRACE_FULL_FAULTINFO) { |
417 | !ptrace_faultinfo) { | ||
418 | get_skas_faultinfo(pid, | 391 | get_skas_faultinfo(pid, |
419 | ®s->faultinfo); | 392 | ®s->faultinfo); |
420 | (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, | 393 | (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, |
@@ -571,67 +544,6 @@ int copy_context_skas0(unsigned long new_stack, int pid) | |||
571 | return err; | 544 | return err; |
572 | } | 545 | } |
573 | 546 | ||
574 | /* | ||
575 | * This is used only, if stub pages are needed, while proc_mm is | ||
576 | * available. Opening /proc/mm creates a new mm_context, which lacks | ||
577 | * the stub-pages. Thus, we map them using /proc/mm-fd | ||
578 | */ | ||
579 | int map_stub_pages(int fd, unsigned long code, unsigned long data, | ||
580 | unsigned long stack) | ||
581 | { | ||
582 | struct proc_mm_op mmop; | ||
583 | int n; | ||
584 | unsigned long long code_offset; | ||
585 | int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), | ||
586 | &code_offset); | ||
587 | |||
588 | mmop = ((struct proc_mm_op) { .op = MM_MMAP, | ||
589 | .u = | ||
590 | { .mmap = | ||
591 | { .addr = code, | ||
592 | .len = UM_KERN_PAGE_SIZE, | ||
593 | .prot = PROT_EXEC, | ||
594 | .flags = MAP_FIXED | MAP_PRIVATE, | ||
595 | .fd = code_fd, | ||
596 | .offset = code_offset | ||
597 | } } }); | ||
598 | CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); | ||
599 | if (n != sizeof(mmop)) { | ||
600 | n = errno; | ||
601 | printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " | ||
602 | "offset = %llx\n", code, code_fd, | ||
603 | (unsigned long long) code_offset); | ||
604 | printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code " | ||
605 | "failed, err = %d\n", n); | ||
606 | return -n; | ||
607 | } | ||
608 | |||
609 | if (stack) { | ||
610 | unsigned long long map_offset; | ||
611 | int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); | ||
612 | mmop = ((struct proc_mm_op) | ||
613 | { .op = MM_MMAP, | ||
614 | .u = | ||
615 | { .mmap = | ||
616 | { .addr = data, | ||
617 | .len = UM_KERN_PAGE_SIZE, | ||
618 | .prot = PROT_READ | PROT_WRITE, | ||
619 | .flags = MAP_FIXED | MAP_SHARED, | ||
620 | .fd = map_fd, | ||
621 | .offset = map_offset | ||
622 | } } }); | ||
623 | CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); | ||
624 | if (n != sizeof(mmop)) { | ||
625 | n = errno; | ||
626 | printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for " | ||
627 | "data failed, err = %d\n", n); | ||
628 | return -n; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) | 547 | void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) |
636 | { | 548 | { |
637 | (*buf)[0].JB_IP = (unsigned long) handler; | 549 | (*buf)[0].JB_IP = (unsigned long) handler; |
@@ -728,17 +640,5 @@ void reboot_skas(void) | |||
728 | 640 | ||
729 | void __switch_mm(struct mm_id *mm_idp) | 641 | void __switch_mm(struct mm_id *mm_idp) |
730 | { | 642 | { |
731 | int err; | 643 | userspace_pid[0] = mm_idp->u.pid; |
732 | |||
733 | /* FIXME: need cpu pid in __switch_mm */ | ||
734 | if (proc_mm) { | ||
735 | err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, | ||
736 | mm_idp->u.mm_fd); | ||
737 | if (err) { | ||
738 | printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM " | ||
739 | "failed, errno = %d\n", errno); | ||
740 | fatal_sigsegv(); | ||
741 | } | ||
742 | } | ||
743 | else userspace_pid[0] = mm_idp->u.pid; | ||
744 | } | 644 | } |
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 337518c5042a..47f1ff056a54 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <ptrace_user.h> | 24 | #include <ptrace_user.h> |
25 | #include <registers.h> | 25 | #include <registers.h> |
26 | #include <skas.h> | 26 | #include <skas.h> |
27 | #include <skas_ptrace.h> | ||
28 | 27 | ||
29 | static void ptrace_child(void) | 28 | static void ptrace_child(void) |
30 | { | 29 | { |
@@ -143,44 +142,6 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) | |||
143 | } | 142 | } |
144 | 143 | ||
145 | /* Changed only during early boot */ | 144 | /* Changed only during early boot */ |
146 | int ptrace_faultinfo; | ||
147 | static int disable_ptrace_faultinfo; | ||
148 | |||
149 | int ptrace_ldt; | ||
150 | static int disable_ptrace_ldt; | ||
151 | |||
152 | int proc_mm; | ||
153 | static int disable_proc_mm; | ||
154 | |||
155 | int have_switch_mm; | ||
156 | static int disable_switch_mm; | ||
157 | |||
158 | int skas_needs_stub; | ||
159 | |||
160 | static int __init skas0_cmd_param(char *str, int* add) | ||
161 | { | ||
162 | disable_ptrace_faultinfo = 1; | ||
163 | disable_ptrace_ldt = 1; | ||
164 | disable_proc_mm = 1; | ||
165 | disable_switch_mm = 1; | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | /* The two __uml_setup would conflict, without this stupid alias. */ | ||
171 | |||
172 | static int __init mode_skas0_cmd_param(char *str, int* add) | ||
173 | __attribute__((alias("skas0_cmd_param"))); | ||
174 | |||
175 | __uml_setup("skas0", skas0_cmd_param, | ||
176 | "skas0\n" | ||
177 | " Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n"); | ||
178 | |||
179 | __uml_setup("mode=skas0", mode_skas0_cmd_param, | ||
180 | "mode=skas0\n" | ||
181 | " Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n"); | ||
182 | |||
183 | /* Changed only during early boot */ | ||
184 | static int force_sysemu_disabled = 0; | 145 | static int force_sysemu_disabled = 0; |
185 | 146 | ||
186 | static int __init nosysemu_cmd_param(char *str, int* add) | 147 | static int __init nosysemu_cmd_param(char *str, int* add) |
@@ -376,121 +337,6 @@ void __init os_early_checks(void) | |||
376 | stop_ptraced_child(pid, 1, 1); | 337 | stop_ptraced_child(pid, 1, 1); |
377 | } | 338 | } |
378 | 339 | ||
379 | static int __init noprocmm_cmd_param(char *str, int* add) | ||
380 | { | ||
381 | disable_proc_mm = 1; | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | __uml_setup("noprocmm", noprocmm_cmd_param, | ||
386 | "noprocmm\n" | ||
387 | " Turns off usage of /proc/mm, even if host supports it.\n" | ||
388 | " To support /proc/mm, the host needs to be patched using\n" | ||
389 | " the current skas3 patch.\n\n"); | ||
390 | |||
391 | static int __init noptracefaultinfo_cmd_param(char *str, int* add) | ||
392 | { | ||
393 | disable_ptrace_faultinfo = 1; | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, | ||
398 | "noptracefaultinfo\n" | ||
399 | " Turns off usage of PTRACE_FAULTINFO, even if host supports\n" | ||
400 | " it. To support PTRACE_FAULTINFO, the host needs to be patched\n" | ||
401 | " using the current skas3 patch.\n\n"); | ||
402 | |||
403 | static int __init noptraceldt_cmd_param(char *str, int* add) | ||
404 | { | ||
405 | disable_ptrace_ldt = 1; | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | __uml_setup("noptraceldt", noptraceldt_cmd_param, | ||
410 | "noptraceldt\n" | ||
411 | " Turns off usage of PTRACE_LDT, even if host supports it.\n" | ||
412 | " To support PTRACE_LDT, the host needs to be patched using\n" | ||
413 | " the current skas3 patch.\n\n"); | ||
414 | |||
415 | static inline void check_skas3_ptrace_faultinfo(void) | ||
416 | { | ||
417 | struct ptrace_faultinfo fi; | ||
418 | int pid, n; | ||
419 | |||
420 | non_fatal(" - PTRACE_FAULTINFO..."); | ||
421 | pid = start_ptraced_child(); | ||
422 | |||
423 | n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); | ||
424 | if (n < 0) { | ||
425 | if (errno == EIO) | ||
426 | non_fatal("not found\n"); | ||
427 | else | ||
428 | perror("not found"); | ||
429 | } else if (disable_ptrace_faultinfo) | ||
430 | non_fatal("found but disabled on command line\n"); | ||
431 | else { | ||
432 | ptrace_faultinfo = 1; | ||
433 | non_fatal("found\n"); | ||
434 | } | ||
435 | |||
436 | stop_ptraced_child(pid, 1, 1); | ||
437 | } | ||
438 | |||
439 | static inline void check_skas3_ptrace_ldt(void) | ||
440 | { | ||
441 | #ifdef PTRACE_LDT | ||
442 | int pid, n; | ||
443 | unsigned char ldtbuf[40]; | ||
444 | struct ptrace_ldt ldt_op = (struct ptrace_ldt) { | ||
445 | .func = 2, /* read default ldt */ | ||
446 | .ptr = ldtbuf, | ||
447 | .bytecount = sizeof(ldtbuf)}; | ||
448 | |||
449 | non_fatal(" - PTRACE_LDT..."); | ||
450 | pid = start_ptraced_child(); | ||
451 | |||
452 | n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); | ||
453 | if (n < 0) { | ||
454 | if (errno == EIO) | ||
455 | non_fatal("not found\n"); | ||
456 | else | ||
457 | perror("not found"); | ||
458 | } else if (disable_ptrace_ldt) | ||
459 | non_fatal("found, but use is disabled\n"); | ||
460 | else { | ||
461 | ptrace_ldt = 1; | ||
462 | non_fatal("found\n"); | ||
463 | } | ||
464 | |||
465 | stop_ptraced_child(pid, 1, 1); | ||
466 | #endif | ||
467 | } | ||
468 | |||
469 | static inline void check_skas3_proc_mm(void) | ||
470 | { | ||
471 | non_fatal(" - /proc/mm..."); | ||
472 | if (access("/proc/mm", W_OK) < 0) | ||
473 | perror("not found"); | ||
474 | else if (disable_proc_mm) | ||
475 | non_fatal("found but disabled on command line\n"); | ||
476 | else { | ||
477 | proc_mm = 1; | ||
478 | non_fatal("found\n"); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | void can_do_skas(void) | ||
483 | { | ||
484 | non_fatal("Checking for the skas3 patch in the host:\n"); | ||
485 | |||
486 | check_skas3_proc_mm(); | ||
487 | check_skas3_ptrace_faultinfo(); | ||
488 | check_skas3_ptrace_ldt(); | ||
489 | |||
490 | if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) | ||
491 | skas_needs_stub = 1; | ||
492 | } | ||
493 | |||
494 | int __init parse_iomem(char *str, int *add) | 340 | int __init parse_iomem(char *str, int *add) |
495 | { | 341 | { |
496 | struct iomem_region *new; | 342 | struct iomem_region *new; |
diff --git a/arch/x86/um/ldt.c b/arch/x86/um/ldt.c index 8e08176f0bcb..5c0b711d2433 100644 --- a/arch/x86/um/ldt.c +++ b/arch/x86/um/ldt.c | |||
@@ -8,9 +8,7 @@ | |||
8 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
9 | #include <asm/unistd.h> | 9 | #include <asm/unistd.h> |
10 | #include <os.h> | 10 | #include <os.h> |
11 | #include <proc_mm.h> | ||
12 | #include <skas.h> | 11 | #include <skas.h> |
13 | #include <skas_ptrace.h> | ||
14 | #include <sysdep/tls.h> | 12 | #include <sysdep/tls.h> |
15 | 13 | ||
16 | extern int modify_ldt(int func, void *ptr, unsigned long bytecount); | 14 | extern int modify_ldt(int func, void *ptr, unsigned long bytecount); |
@@ -19,105 +17,20 @@ static long write_ldt_entry(struct mm_id *mm_idp, int func, | |||
19 | struct user_desc *desc, void **addr, int done) | 17 | struct user_desc *desc, void **addr, int done) |
20 | { | 18 | { |
21 | long res; | 19 | long res; |
22 | 20 | void *stub_addr; | |
23 | if (proc_mm) { | 21 | res = syscall_stub_data(mm_idp, (unsigned long *)desc, |
24 | /* | 22 | (sizeof(*desc) + sizeof(long) - 1) & |
25 | * This is a special handling for the case, that the mm to | 23 | ~(sizeof(long) - 1), |
26 | * modify isn't current->active_mm. | 24 | addr, &stub_addr); |
27 | * If this is called directly by modify_ldt, | 25 | if (!res) { |
28 | * (current->active_mm->context.skas.u == mm_idp) | 26 | unsigned long args[] = { func, |
29 | * will be true. So no call to __switch_mm(mm_idp) is done. | 27 | (unsigned long)stub_addr, |
30 | * If this is called in case of init_new_ldt or PTRACE_LDT, | 28 | sizeof(*desc), |
31 | * mm_idp won't belong to current->active_mm, but child->mm. | 29 | 0, 0, 0 }; |
32 | * So we need to switch child's mm into our userspace, then | 30 | res = run_syscall_stub(mm_idp, __NR_modify_ldt, args, |
33 | * later switch back. | 31 | 0, addr, done); |
34 | * | ||
35 | * Note: I'm unsure: should interrupts be disabled here? | ||
36 | */ | ||
37 | if (!current->active_mm || current->active_mm == &init_mm || | ||
38 | mm_idp != ¤t->active_mm->context.id) | ||
39 | __switch_mm(mm_idp); | ||
40 | } | ||
41 | |||
42 | if (ptrace_ldt) { | ||
43 | struct ptrace_ldt ldt_op = (struct ptrace_ldt) { | ||
44 | .func = func, | ||
45 | .ptr = desc, | ||
46 | .bytecount = sizeof(*desc)}; | ||
47 | u32 cpu; | ||
48 | int pid; | ||
49 | |||
50 | if (!proc_mm) | ||
51 | pid = mm_idp->u.pid; | ||
52 | else { | ||
53 | cpu = get_cpu(); | ||
54 | pid = userspace_pid[cpu]; | ||
55 | } | ||
56 | |||
57 | res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); | ||
58 | |||
59 | if (proc_mm) | ||
60 | put_cpu(); | ||
61 | } | ||
62 | else { | ||
63 | void *stub_addr; | ||
64 | res = syscall_stub_data(mm_idp, (unsigned long *)desc, | ||
65 | (sizeof(*desc) + sizeof(long) - 1) & | ||
66 | ~(sizeof(long) - 1), | ||
67 | addr, &stub_addr); | ||
68 | if (!res) { | ||
69 | unsigned long args[] = { func, | ||
70 | (unsigned long)stub_addr, | ||
71 | sizeof(*desc), | ||
72 | 0, 0, 0 }; | ||
73 | res = run_syscall_stub(mm_idp, __NR_modify_ldt, args, | ||
74 | 0, addr, done); | ||
75 | } | ||
76 | } | 32 | } |
77 | 33 | ||
78 | if (proc_mm) { | ||
79 | /* | ||
80 | * This is the second part of special handling, that makes | ||
81 | * PTRACE_LDT possible to implement. | ||
82 | */ | ||
83 | if (current->active_mm && current->active_mm != &init_mm && | ||
84 | mm_idp != ¤t->active_mm->context.id) | ||
85 | __switch_mm(¤t->active_mm->context.id); | ||
86 | } | ||
87 | |||
88 | return res; | ||
89 | } | ||
90 | |||
91 | static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) | ||
92 | { | ||
93 | int res, n; | ||
94 | struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) { | ||
95 | .func = 0, | ||
96 | .bytecount = bytecount, | ||
97 | .ptr = kmalloc(bytecount, GFP_KERNEL)}; | ||
98 | u32 cpu; | ||
99 | |||
100 | if (ptrace_ldt.ptr == NULL) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | /* | ||
104 | * This is called from sys_modify_ldt only, so userspace_pid gives | ||
105 | * us the right number | ||
106 | */ | ||
107 | |||
108 | cpu = get_cpu(); | ||
109 | res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); | ||
110 | put_cpu(); | ||
111 | if (res < 0) | ||
112 | goto out; | ||
113 | |||
114 | n = copy_to_user(ptr, ptrace_ldt.ptr, res); | ||
115 | if (n != 0) | ||
116 | res = -EFAULT; | ||
117 | |||
118 | out: | ||
119 | kfree(ptrace_ldt.ptr); | ||
120 | |||
121 | return res; | 34 | return res; |
122 | } | 35 | } |
123 | 36 | ||
@@ -145,9 +58,6 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) | |||
145 | bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; | 58 | bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; |
146 | err = bytecount; | 59 | err = bytecount; |
147 | 60 | ||
148 | if (ptrace_ldt) | ||
149 | return read_ldt_from_host(ptr, bytecount); | ||
150 | |||
151 | mutex_lock(&ldt->lock); | 61 | mutex_lock(&ldt->lock); |
152 | if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { | 62 | if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { |
153 | size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; | 63 | size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; |
@@ -229,17 +139,11 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) | |||
229 | goto out; | 139 | goto out; |
230 | } | 140 | } |
231 | 141 | ||
232 | if (!ptrace_ldt) | 142 | mutex_lock(&ldt->lock); |
233 | mutex_lock(&ldt->lock); | ||
234 | 143 | ||
235 | err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); | 144 | err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); |
236 | if (err) | 145 | if (err) |
237 | goto out_unlock; | 146 | goto out_unlock; |
238 | else if (ptrace_ldt) { | ||
239 | /* With PTRACE_LDT available, this is used as a flag only */ | ||
240 | ldt->entry_count = 1; | ||
241 | goto out; | ||
242 | } | ||
243 | 147 | ||
244 | if (ldt_info.entry_number >= ldt->entry_count && | 148 | if (ldt_info.entry_number >= ldt->entry_count && |
245 | ldt_info.entry_number >= LDT_DIRECT_ENTRIES) { | 149 | ldt_info.entry_number >= LDT_DIRECT_ENTRIES) { |
@@ -393,91 +297,56 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) | |||
393 | int i; | 297 | int i; |
394 | long page, err=0; | 298 | long page, err=0; |
395 | void *addr = NULL; | 299 | void *addr = NULL; |
396 | struct proc_mm_op copy; | ||
397 | 300 | ||
398 | 301 | ||
399 | if (!ptrace_ldt) | 302 | mutex_init(&new_mm->arch.ldt.lock); |
400 | mutex_init(&new_mm->arch.ldt.lock); | ||
401 | 303 | ||
402 | if (!from_mm) { | 304 | if (!from_mm) { |
403 | memset(&desc, 0, sizeof(desc)); | 305 | memset(&desc, 0, sizeof(desc)); |
404 | /* | 306 | /* |
405 | * We have to initialize a clean ldt. | 307 | * Now we try to retrieve info about the ldt, we |
308 | * inherited from the host. All ldt-entries found | ||
309 | * will be reset in the following loop | ||
406 | */ | 310 | */ |
407 | if (proc_mm) { | 311 | ldt_get_host_info(); |
408 | /* | 312 | for (num_p=host_ldt_entries; *num_p != -1; num_p++) { |
409 | * If the new mm was created using proc_mm, host's | 313 | desc.entry_number = *num_p; |
410 | * default-ldt currently is assigned, which normally | 314 | err = write_ldt_entry(&new_mm->id, 1, &desc, |
411 | * contains the call-gates for lcall7 and lcall27. | 315 | &addr, *(num_p + 1) == -1); |
412 | * To remove these gates, we simply write an empty | 316 | if (err) |
413 | * entry as number 0 to the host. | 317 | break; |
414 | */ | ||
415 | err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1); | ||
416 | } | ||
417 | else{ | ||
418 | /* | ||
419 | * Now we try to retrieve info about the ldt, we | ||
420 | * inherited from the host. All ldt-entries found | ||
421 | * will be reset in the following loop | ||
422 | */ | ||
423 | ldt_get_host_info(); | ||
424 | for (num_p=host_ldt_entries; *num_p != -1; num_p++) { | ||
425 | desc.entry_number = *num_p; | ||
426 | err = write_ldt_entry(&new_mm->id, 1, &desc, | ||
427 | &addr, *(num_p + 1) == -1); | ||
428 | if (err) | ||
429 | break; | ||
430 | } | ||
431 | } | 318 | } |
432 | new_mm->arch.ldt.entry_count = 0; | 319 | new_mm->arch.ldt.entry_count = 0; |
433 | 320 | ||
434 | goto out; | 321 | goto out; |
435 | } | 322 | } |
436 | 323 | ||
437 | if (proc_mm) { | 324 | /* |
438 | /* | 325 | * Our local LDT is used to supply the data for |
439 | * We have a valid from_mm, so we now have to copy the LDT of | 326 | * modify_ldt(READLDT), if PTRACE_LDT isn't available, |
440 | * from_mm to new_mm, because using proc_mm an new mm with | 327 | * i.e., we have to use the stub for modify_ldt, which |
441 | * an empty/default LDT was created in new_mm() | 328 | * can't handle the big read buffer of up to 64kB. |
442 | */ | 329 | */ |
443 | copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, | 330 | mutex_lock(&from_mm->arch.ldt.lock); |
444 | .u = | 331 | if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES) |
445 | { .copy_segments = | 332 | memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries, |
446 | from_mm->id.u.mm_fd } } ); | 333 | sizeof(new_mm->arch.ldt.u.entries)); |
447 | i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); | 334 | else { |
448 | if (i != sizeof(copy)) | 335 | i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE; |
449 | printk(KERN_ERR "new_mm : /proc/mm copy_segments " | 336 | while (i-->0) { |
450 | "failed, err = %d\n", -i); | 337 | page = __get_free_page(GFP_KERNEL|__GFP_ZERO); |
451 | } | 338 | if (!page) { |
452 | 339 | err = -ENOMEM; | |
453 | if (!ptrace_ldt) { | 340 | break; |
454 | /* | ||
455 | * Our local LDT is used to supply the data for | ||
456 | * modify_ldt(READLDT), if PTRACE_LDT isn't available, | ||
457 | * i.e., we have to use the stub for modify_ldt, which | ||
458 | * can't handle the big read buffer of up to 64kB. | ||
459 | */ | ||
460 | mutex_lock(&from_mm->arch.ldt.lock); | ||
461 | if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES) | ||
462 | memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries, | ||
463 | sizeof(new_mm->arch.ldt.u.entries)); | ||
464 | else { | ||
465 | i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE; | ||
466 | while (i-->0) { | ||
467 | page = __get_free_page(GFP_KERNEL|__GFP_ZERO); | ||
468 | if (!page) { | ||
469 | err = -ENOMEM; | ||
470 | break; | ||
471 | } | ||
472 | new_mm->arch.ldt.u.pages[i] = | ||
473 | (struct ldt_entry *) page; | ||
474 | memcpy(new_mm->arch.ldt.u.pages[i], | ||
475 | from_mm->arch.ldt.u.pages[i], PAGE_SIZE); | ||
476 | } | 341 | } |
342 | new_mm->arch.ldt.u.pages[i] = | ||
343 | (struct ldt_entry *) page; | ||
344 | memcpy(new_mm->arch.ldt.u.pages[i], | ||
345 | from_mm->arch.ldt.u.pages[i], PAGE_SIZE); | ||
477 | } | 346 | } |
478 | new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count; | ||
479 | mutex_unlock(&from_mm->arch.ldt.lock); | ||
480 | } | 347 | } |
348 | new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count; | ||
349 | mutex_unlock(&from_mm->arch.ldt.lock); | ||
481 | 350 | ||
482 | out: | 351 | out: |
483 | return err; | 352 | return err; |
@@ -488,7 +357,7 @@ void free_ldt(struct mm_context *mm) | |||
488 | { | 357 | { |
489 | int i; | 358 | int i; |
490 | 359 | ||
491 | if (!ptrace_ldt && mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) { | 360 | if (mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) { |
492 | i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE; | 361 | i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE; |
493 | while (i-- > 0) | 362 | while (i-- > 0) |
494 | free_page((long) mm->arch.ldt.u.pages[i]); | 363 | free_page((long) mm->arch.ldt.u.pages[i]); |
diff --git a/arch/x86/um/shared/sysdep/faultinfo_32.h b/arch/x86/um/shared/sysdep/faultinfo_32.h index a26086b8a800..b6f2437ec29c 100644 --- a/arch/x86/um/shared/sysdep/faultinfo_32.h +++ b/arch/x86/um/shared/sysdep/faultinfo_32.h | |||
@@ -27,9 +27,6 @@ struct faultinfo { | |||
27 | /* This is Page Fault */ | 27 | /* This is Page Fault */ |
28 | #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) | 28 | #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) |
29 | 29 | ||
30 | /* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */ | ||
31 | #define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo) | ||
32 | |||
33 | #define PTRACE_FULL_FAULTINFO 0 | 30 | #define PTRACE_FULL_FAULTINFO 0 |
34 | 31 | ||
35 | #endif | 32 | #endif |
diff --git a/arch/x86/um/shared/sysdep/faultinfo_64.h b/arch/x86/um/shared/sysdep/faultinfo_64.h index f811cbe15d62..ee88f88974ea 100644 --- a/arch/x86/um/shared/sysdep/faultinfo_64.h +++ b/arch/x86/um/shared/sysdep/faultinfo_64.h | |||
@@ -27,9 +27,6 @@ struct faultinfo { | |||
27 | /* This is Page Fault */ | 27 | /* This is Page Fault */ |
28 | #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) | 28 | #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) |
29 | 29 | ||
30 | /* No broken SKAS API, which doesn't pass trap_no, here. */ | ||
31 | #define SEGV_MAYBE_FIXABLE(fi) 0 | ||
32 | |||
33 | #define PTRACE_FULL_FAULTINFO 1 | 30 | #define PTRACE_FULL_FAULTINFO 1 |
34 | 31 | ||
35 | #endif | 32 | #endif |
diff --git a/arch/x86/um/shared/sysdep/skas_ptrace.h b/arch/x86/um/shared/sysdep/skas_ptrace.h deleted file mode 100644 index 453febe98993..000000000000 --- a/arch/x86/um/shared/sysdep/skas_ptrace.h +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __SYSDEP_X86_SKAS_PTRACE_H | ||
7 | #define __SYSDEP_X86_SKAS_PTRACE_H | ||
8 | |||
9 | struct ptrace_faultinfo { | ||
10 | int is_write; | ||
11 | unsigned long addr; | ||
12 | }; | ||
13 | |||
14 | struct ptrace_ldt { | ||
15 | int func; | ||
16 | void *ptr; | ||
17 | unsigned long bytecount; | ||
18 | }; | ||
19 | |||
20 | #define PTRACE_LDT 54 | ||
21 | |||
22 | #endif | ||