aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2015-03-18 16:31:27 -0400
committerRichard Weinberger <richard@nod.at>2015-04-13 15:00:53 -0400
commitd0b5e15f0c0fdd759dd3dd48dc2dc2e7199e0da0 (patch)
tree7b833b85c0e2eabf6b38d8b94875b430554afae7 /arch
parentaaeac66b1a02d399ec8ee63e8d617c1d601ea353 (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.h2
-rw-r--r--arch/um/include/shared/skas/proc_mm.h44
-rw-r--r--arch/um/include/shared/skas/skas.h3
-rw-r--r--arch/um/include/shared/skas_ptrace.h14
-rw-r--r--arch/um/kernel/ptrace.c32
-rw-r--r--arch/um/kernel/reboot.c35
-rw-r--r--arch/um/kernel/skas/mmu.c68
-rw-r--r--arch/um/kernel/skas/process.c27
-rw-r--r--arch/um/kernel/trap.c2
-rw-r--r--arch/um/kernel/um_arch.c10
-rw-r--r--arch/um/os-Linux/process.c16
-rw-r--r--arch/um/os-Linux/skas/mem.c100
-rw-r--r--arch/um/os-Linux/skas/process.c200
-rw-r--r--arch/um/os-Linux/start_up.c154
-rw-r--r--arch/x86/um/ldt.c227
-rw-r--r--arch/x86/um/shared/sysdep/faultinfo_32.h3
-rw-r--r--arch/x86/um/shared/sysdep/faultinfo_64.h3
-rw-r--r--arch/x86/um/shared/sysdep/skas_ptrace.h22
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 */
176extern void os_early_checks(void); 176extern void os_early_checks(void);
177extern void can_do_skas(void);
178extern void os_check_bugs(void); 177extern void os_check_bugs(void);
179extern void check_host_supports_tls(int *supports_tls, int *tls_min); 178extern void check_host_supports_tls(int *supports_tls, int *tls_min);
180 179
@@ -187,7 +186,6 @@ extern int os_process_parent(int pid);
187extern void os_stop_process(int pid); 186extern void os_stop_process(int pid);
188extern void os_kill_process(int pid, int reap_child); 187extern void os_kill_process(int pid, int reap_child);
189extern void os_kill_ptraced_process(int pid, int reap_child); 188extern void os_kill_ptraced_process(int pid, int reap_child);
190extern long os_ptrace_ldt(long pid, long addr, long data);
191 189
192extern int os_getpid(void); 190extern int os_getpid(void);
193extern int os_getpgrp(void); 191extern 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
14struct 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
23struct mm_munmap {
24 unsigned long addr;
25 unsigned long len;
26};
27
28struct mm_mprotect {
29 unsigned long addr;
30 unsigned long len;
31 unsigned int prot;
32};
33
34struct 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
11extern int userspace_pid[]; 11extern int userspace_pid[];
12extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
13extern int skas_needs_stub;
14 12
15extern int user_thread(unsigned long stack, int flags); 13extern int user_thread(unsigned long stack, int flags);
16extern void new_thread_handler(void); 14extern void new_thread_handler(void);
17extern void handle_syscall(struct uml_pt_regs *regs); 15extern void handle_syscall(struct uml_pt_regs *regs);
18extern int new_mm(unsigned long stack);
19extern long execute_syscall_skas(void *r); 16extern long execute_syscall_skas(void *r);
20extern unsigned long current_stub_stack(void); 17extern 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
15void user_enable_single_step(struct task_struct *child) 12void 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
16static void kill_off_processes(void) 16static 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
42void uml_cleanup(void) 35void 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 = &current->mm->context; 63 from_mm = &current->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
13int 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
32extern void start_kernel(void); 13extern void start_kernel(void);
33 14
34static int __init start_kernel_proc(void *unused) 15static 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
109long 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
49extern int proc_mm;
50
51static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) 48static 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,
251int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, 197int 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
26int is_skas_winch(int pid, int fd, void *data) 24int is_skas_winch(int pid, int fd, void *data)
@@ -91,50 +89,33 @@ extern unsigned long current_stub_stack(void);
91static void get_skas_faultinfo(int pid, struct faultinfo *fi) 89static 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;
198static int userspace_tramp(void *stack) 179static 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 &regs->faultinfo); 392 &regs->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 */
579int 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
635void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) 547void 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
729void __switch_mm(struct mm_id *mm_idp) 641void __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
29static void ptrace_child(void) 28static 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 */
146int ptrace_faultinfo;
147static int disable_ptrace_faultinfo;
148
149int ptrace_ldt;
150static int disable_ptrace_ldt;
151
152int proc_mm;
153static int disable_proc_mm;
154
155int have_switch_mm;
156static int disable_switch_mm;
157
158int skas_needs_stub;
159
160static 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
172static 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 */
184static int force_sysemu_disabled = 0; 145static int force_sysemu_disabled = 0;
185 146
186static int __init nosysemu_cmd_param(char *str, int* add) 147static 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
379static 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
391static 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
403static 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
415static 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
439static 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
469static 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
482void 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
494int __init parse_iomem(char *str, int *add) 340int __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
16extern int modify_ldt(int func, void *ptr, unsigned long bytecount); 14extern 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 != &current->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 != &current->active_mm->context.id)
85 __switch_mm(&current->active_mm->context.id);
86 }
87
88 return res;
89}
90
91static 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, &copy, 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
9struct ptrace_faultinfo {
10 int is_write;
11 unsigned long addr;
12};
13
14struct ptrace_ldt {
15 int func;
16 void *ptr;
17 unsigned long bytecount;
18};
19
20#define PTRACE_LDT 54
21
22#endif