Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+145 -811
-2
arch/um/include/shared/os.h
··· 174 174 175 175 /* start_up.c */ 176 176 extern void os_early_checks(void); 177 - extern void can_do_skas(void); 178 177 extern void os_check_bugs(void); 179 178 extern void check_host_supports_tls(int *supports_tls, int *tls_min); 180 179 ··· 186 187 extern void os_stop_process(int pid); 187 188 extern void os_kill_process(int pid, int reap_child); 188 189 extern void os_kill_ptraced_process(int pid, int reap_child); 189 - extern long os_ptrace_ldt(long pid, long addr, long data); 190 190 191 191 extern int os_getpid(void); 192 192 extern int os_getpgrp(void);
-44
arch/um/include/shared/skas/proc_mm.h
··· 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
-3
arch/um/include/shared/skas/skas.h
··· 9 9 #include <sysdep/ptrace.h> 10 10 11 11 extern int userspace_pid[]; 12 - extern int proc_mm, ptrace_faultinfo, ptrace_ldt; 13 - extern int skas_needs_stub; 14 12 15 13 extern int user_thread(unsigned long stack, int flags); 16 14 extern void new_thread_handler(void); 17 15 extern void handle_syscall(struct uml_pt_regs *regs); 18 - extern int new_mm(unsigned long stack); 19 16 extern long execute_syscall_skas(void *r); 20 17 extern unsigned long current_stub_stack(void); 21 18
-14
arch/um/include/shared/skas_ptrace.h
··· 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
-32
arch/um/kernel/ptrace.c
··· 8 8 #include <linux/sched.h> 9 9 #include <linux/tracehook.h> 10 10 #include <asm/uaccess.h> 11 - #include <skas_ptrace.h> 12 - 13 - 14 11 15 12 void user_enable_single_step(struct task_struct *child) 16 13 { ··· 101 104 ret = ptrace_set_thread_area(child, addr, vp); 102 105 break; 103 106 104 - case PTRACE_FAULTINFO: { 105 - /* 106 - * Take the info from thread->arch->faultinfo, 107 - * but transfer max. sizeof(struct ptrace_faultinfo). 108 - * On i386, ptrace_faultinfo is smaller! 109 - */ 110 - ret = copy_to_user(p, &child->thread.arch.faultinfo, 111 - sizeof(struct ptrace_faultinfo)) ? 112 - -EIO : 0; 113 - break; 114 - } 115 - 116 - #ifdef PTRACE_LDT 117 - case PTRACE_LDT: { 118 - struct ptrace_ldt ldt; 119 - 120 - if (copy_from_user(&ldt, p, sizeof(ldt))) { 121 - ret = -EIO; 122 - break; 123 - } 124 - 125 - /* 126 - * This one is confusing, so just punt and return -EIO for 127 - * now 128 - */ 129 - ret = -EIO; 130 - break; 131 - } 132 - #endif 133 107 default: 134 108 ret = ptrace_request(child, request, addr, data); 135 109 if (ret == -EIO)
+12 -19
arch/um/kernel/reboot.c
··· 15 15 16 16 static void kill_off_processes(void) 17 17 { 18 - if (proc_mm) 19 - /* 20 - * FIXME: need to loop over userspace_pids 21 - */ 22 - os_kill_ptraced_process(userspace_pid[0], 1); 23 - else { 24 - struct task_struct *p; 25 - int pid; 18 + struct task_struct *p; 19 + int pid; 26 20 27 - read_lock(&tasklist_lock); 28 - for_each_process(p) { 29 - struct task_struct *t; 21 + read_lock(&tasklist_lock); 22 + for_each_process(p) { 23 + struct task_struct *t; 30 24 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); 25 + t = find_lock_task_mm(p); 26 + if (!t) 27 + continue; 28 + pid = t->mm->context.id.u.pid; 29 + task_unlock(t); 30 + os_kill_ptraced_process(pid, 1); 39 31 } 32 + read_unlock(&tasklist_lock); 40 33 } 41 34 42 35 void uml_cleanup(void)
+22 -44
arch/um/kernel/skas/mmu.c
··· 54 54 unsigned long stack = 0; 55 55 int ret = -ENOMEM; 56 56 57 - if (skas_needs_stub) { 58 - stack = get_zeroed_page(GFP_KERNEL); 59 - if (stack == 0) 60 - goto out; 61 - } 57 + stack = get_zeroed_page(GFP_KERNEL); 58 + if (stack == 0) 59 + goto out; 62 60 63 61 to_mm->id.stack = stack; 64 62 if (current->mm != NULL && current->mm != &init_mm) 65 63 from_mm = &current->mm->context; 66 64 67 - if (proc_mm) { 68 - ret = new_mm(stack); 69 - if (ret < 0) { 70 - printk(KERN_ERR "init_new_context_skas - " 71 - "new_mm failed, errno = %d\n", ret); 72 - goto out_free; 73 - } 74 - to_mm->id.u.mm_fd = ret; 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); 65 + if (from_mm) 66 + to_mm->id.u.pid = copy_context_skas0(stack, 67 + from_mm->id.u.pid); 68 + else to_mm->id.u.pid = start_userspace(stack); 81 69 82 - if (to_mm->id.u.pid < 0) { 83 - ret = to_mm->id.u.pid; 84 - goto out_free; 85 - } 70 + if (to_mm->id.u.pid < 0) { 71 + ret = to_mm->id.u.pid; 72 + goto out_free; 86 73 } 87 74 88 75 ret = init_new_ldt(to_mm, from_mm); ··· 91 104 void uml_setup_stubs(struct mm_struct *mm) 92 105 { 93 106 int err, ret; 94 - 95 - if (!skas_needs_stub) 96 - return; 97 107 98 108 ret = init_stub_pte(mm, STUB_CODE, 99 109 (unsigned long) &__syscall_stub_start); ··· 138 154 { 139 155 struct mm_context *mmu = &mm->context; 140 156 141 - if (proc_mm) 142 - os_close_file(mmu->id.u.mm_fd); 143 - else { 144 - /* 145 - * If init_new_context wasn't called, this will be 146 - * zero, resulting in a kill(0), which will result in the 147 - * whole UML suddenly dying. Also, cover negative and 148 - * 1 cases, since they shouldn't happen either. 149 - */ 150 - if (mmu->id.u.pid < 2) { 151 - printk(KERN_ERR "corrupt mm_context - pid = %d\n", 152 - mmu->id.u.pid); 153 - return; 154 - } 155 - os_kill_ptraced_process(mmu->id.u.pid, 1); 157 + /* 158 + * If init_new_context wasn't called, this will be 159 + * zero, resulting in a kill(0), which will result in the 160 + * whole UML suddenly dying. Also, cover negative and 161 + * 1 cases, since they shouldn't happen either. 162 + */ 163 + if (mmu->id.u.pid < 2) { 164 + printk(KERN_ERR "corrupt mm_context - pid = %d\n", 165 + mmu->id.u.pid); 166 + return; 156 167 } 168 + os_kill_ptraced_process(mmu->id.u.pid, 1); 157 169 158 - if (skas_needs_stub) 159 - free_page(mmu->id.stack); 160 - 170 + free_page(mmu->id.stack); 161 171 free_ldt(mmu); 162 172 }
-27
arch/um/kernel/skas/process.c
··· 10 10 #include <os.h> 11 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 13 extern void start_kernel(void); 33 14 34 15 static int __init start_kernel_proc(void *unused) ··· 36 55 { 37 56 stack_protections((unsigned long) &cpu0_irqstack); 38 57 set_sigstack(cpu0_irqstack, THREAD_SIZE); 39 - if (proc_mm) { 40 - userspace_pid[0] = start_userspace(0); 41 - if (userspace_pid[0] < 0) { 42 - printf("start_uml - start_userspace returned %d\n", 43 - userspace_pid[0]); 44 - exit(1); 45 - } 46 - } 47 58 48 59 init_new_thread_signals(); 49 60
+1 -1
arch/um/kernel/trap.c
··· 220 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 224 err = handle_page_fault(address, ip, is_write, is_user, 225 225 &si.si_code); 226 226 else {
-10
arch/um/kernel/um_arch.c
··· 268 268 unsigned long stack; 269 269 unsigned int i; 270 270 int add; 271 - char * mode; 272 271 273 272 for (i = 1; i < argc; i++) { 274 273 if ((i == 1) && (argv[i][0] == ' ')) ··· 289 290 290 291 /* OS sanity checks that need to happen before the kernel runs */ 291 292 os_early_checks(); 292 - 293 - can_do_skas(); 294 - 295 - if (proc_mm && ptrace_faultinfo) 296 - mode = "SKAS3"; 297 - else 298 - mode = "SKAS0"; 299 - 300 - printf("UML running in %s mode\n", mode); 301 293 302 294 brk_start = (unsigned long) sbrk(0); 303 295
-16
arch/um/os-Linux/process.c
··· 16 16 #include <init.h> 17 17 #include <longjmp.h> 18 18 #include <os.h> 19 - #include <skas_ptrace.h> 20 19 21 20 #define ARBITRARY_ADDR -1 22 21 #define FAILURE_PID -1 ··· 99 100 kill(pid, SIGKILL); 100 101 if (reap_child) 101 102 CATCH_EINTR(waitpid(pid, NULL, __WALL)); 102 - } 103 - 104 - /* This is here uniquely to have access to the userspace errno, i.e. the one 105 - * used by ptrace in case of error. 106 - */ 107 - 108 - long os_ptrace_ldt(long pid, long addr, long data) 109 - { 110 - int ret; 111 - 112 - ret = ptrace(PTRACE_LDT, pid, addr, data); 113 - 114 - if (ret < 0) 115 - return -errno; 116 - return ret; 117 103 } 118 104 119 105 /* Kill off a ptraced child by all means available. kill it normally first,
+12 -88
arch/um/os-Linux/skas/mem.c
··· 12 12 #include <as-layout.h> 13 13 #include <mm_id.h> 14 14 #include <os.h> 15 - #include <proc_mm.h> 16 15 #include <ptrace_user.h> 17 16 #include <registers.h> 18 17 #include <skas.h> ··· 45 46 46 47 __initcall(init_syscall_regs); 47 48 48 - extern int proc_mm; 49 - 50 49 static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) 51 50 { 52 51 int n, i; ··· 52 55 unsigned long * data; 53 56 unsigned long * syscall; 54 57 int err, pid = mm_idp->u.pid; 55 - 56 - if (proc_mm) 57 - /* FIXME: Need to look up userspace_pid by cpu */ 58 - pid = userspace_pid[0]; 59 58 60 59 n = ptrace_setregs(pid, syscall_regs); 61 60 if (n < 0) { ··· 171 178 int phys_fd, unsigned long long offset, int done, void **data) 172 179 { 173 180 int ret; 181 + unsigned long args[] = { virt, len, prot, 182 + MAP_SHARED | MAP_FIXED, phys_fd, 183 + MMAP_OFFSET(offset) }; 174 184 175 - if (proc_mm) { 176 - struct proc_mm_op map; 177 - int fd = mm_idp->u.mm_fd; 178 - 179 - map = ((struct proc_mm_op) { .op = MM_MMAP, 180 - .u = 181 - { .mmap = 182 - { .addr = virt, 183 - .len = len, 184 - .prot = prot, 185 - .flags = MAP_SHARED | 186 - MAP_FIXED, 187 - .fd = phys_fd, 188 - .offset= offset 189 - } } } ); 190 - CATCH_EINTR(ret = write(fd, &map, sizeof(map))); 191 - if (ret != sizeof(map)) { 192 - ret = -errno; 193 - printk(UM_KERN_ERR "map : /proc/mm map failed, " 194 - "err = %d\n", -ret); 195 - } 196 - else ret = 0; 197 - } 198 - else { 199 - unsigned long args[] = { virt, len, prot, 200 - MAP_SHARED | MAP_FIXED, phys_fd, 201 - MMAP_OFFSET(offset) }; 202 - 203 - ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, 204 - data, done); 205 - } 185 + ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, 186 + data, done); 206 187 207 188 return ret; 208 189 } ··· 185 218 int done, void **data) 186 219 { 187 220 int ret; 221 + unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, 222 + 0 }; 188 223 189 - if (proc_mm) { 190 - struct proc_mm_op unmap; 191 - int fd = mm_idp->u.mm_fd; 192 - 193 - unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, 194 - .u = 195 - { .munmap = 196 - { .addr = 197 - (unsigned long) addr, 198 - .len = len } } } ); 199 - CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); 200 - if (ret != sizeof(unmap)) { 201 - ret = -errno; 202 - printk(UM_KERN_ERR "unmap - proc_mm write returned " 203 - "%d\n", ret); 204 - } 205 - else ret = 0; 206 - } 207 - else { 208 - unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, 209 - 0 }; 210 - 211 - ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, 212 - data, done); 213 - } 224 + ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, 225 + data, done); 214 226 215 227 return ret; 216 228 } ··· 197 251 int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, 198 252 unsigned int prot, int done, void **data) 199 253 { 200 - struct proc_mm_op protect; 201 254 int ret; 255 + unsigned long args[] = { addr, len, prot, 0, 0, 0 }; 202 256 203 - if (proc_mm) { 204 - int fd = mm_idp->u.mm_fd; 205 - 206 - protect = ((struct proc_mm_op) { .op = MM_MPROTECT, 207 - .u = 208 - { .mprotect = 209 - { .addr = 210 - (unsigned long) addr, 211 - .len = len, 212 - .prot = prot } } } ); 213 - 214 - CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); 215 - if (ret != sizeof(protect)) { 216 - ret = -errno; 217 - printk(UM_KERN_ERR "protect failed, err = %d", -ret); 218 - } 219 - else ret = 0; 220 - } 221 - else { 222 - unsigned long args[] = { addr, len, prot, 0, 0, 0 }; 223 - 224 - ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, 225 - data, done); 226 - } 257 + ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, 258 + data, done); 227 259 228 260 return ret; 229 261 }
+50 -150
arch/um/os-Linux/skas/process.c
··· 16 16 #include <kern_util.h> 17 17 #include <mem.h> 18 18 #include <os.h> 19 - #include <proc_mm.h> 20 19 #include <ptrace_user.h> 21 20 #include <registers.h> 22 21 #include <skas.h> 23 - #include <skas_ptrace.h> 24 22 #include <sysdep/stub.h> 25 23 26 24 int is_skas_winch(int pid, int fd, void *data) ··· 89 91 static void get_skas_faultinfo(int pid, struct faultinfo *fi) 90 92 { 91 93 int err; 94 + unsigned long fpregs[FP_SIZE]; 92 95 93 - if (ptrace_faultinfo) { 94 - err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); 95 - if (err) { 96 - printk(UM_KERN_ERR "get_skas_faultinfo - " 97 - "PTRACE_FAULTINFO failed, errno = %d\n", errno); 98 - fatal_sigsegv(); 99 - } 100 - 101 - /* Special handling for i386, which has different structs */ 102 - if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) 103 - memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, 104 - sizeof(struct faultinfo) - 105 - sizeof(struct ptrace_faultinfo)); 96 + err = get_fp_registers(pid, fpregs); 97 + if (err < 0) { 98 + printk(UM_KERN_ERR "save_fp_registers returned %d\n", 99 + err); 100 + fatal_sigsegv(); 106 101 } 107 - else { 108 - unsigned long fpregs[FP_SIZE]; 102 + err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); 103 + if (err) { 104 + printk(UM_KERN_ERR "Failed to continue stub, pid = %d, " 105 + "errno = %d\n", pid, errno); 106 + fatal_sigsegv(); 107 + } 108 + wait_stub_done(pid); 109 109 110 - err = get_fp_registers(pid, fpregs); 111 - if (err < 0) { 112 - printk(UM_KERN_ERR "save_fp_registers returned %d\n", 113 - err); 114 - fatal_sigsegv(); 115 - } 116 - err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); 117 - if (err) { 118 - printk(UM_KERN_ERR "Failed to continue stub, pid = %d, " 119 - "errno = %d\n", pid, errno); 120 - fatal_sigsegv(); 121 - } 122 - wait_stub_done(pid); 110 + /* 111 + * faultinfo is prepared by the stub-segv-handler at start of 112 + * the stub stack page. We just have to copy it. 113 + */ 114 + memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); 123 115 124 - /* 125 - * faultinfo is prepared by the stub-segv-handler at start of 126 - * the stub stack page. We just have to copy it. 127 - */ 128 - memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); 129 - 130 - err = put_fp_registers(pid, fpregs); 131 - if (err < 0) { 132 - printk(UM_KERN_ERR "put_fp_registers returned %d\n", 133 - err); 134 - fatal_sigsegv(); 135 - } 116 + err = put_fp_registers(pid, fpregs); 117 + if (err < 0) { 118 + printk(UM_KERN_ERR "put_fp_registers returned %d\n", 119 + err); 120 + fatal_sigsegv(); 136 121 } 137 122 } 138 123 ··· 179 198 static int userspace_tramp(void *stack) 180 199 { 181 200 void *addr; 182 - int err; 201 + int err, fd; 202 + unsigned long long offset; 183 203 184 204 ptrace(PTRACE_TRACEME, 0, 0, 0); 185 205 ··· 193 211 exit(1); 194 212 } 195 213 196 - if (!proc_mm) { 197 - /* 198 - * This has a pte, but it can't be mapped in with the usual 199 - * tlb_flush mechanism because this is part of that mechanism 200 - */ 201 - int fd; 202 - unsigned long long offset; 203 - fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); 204 - addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, 205 - PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); 214 + /* 215 + * This has a pte, but it can't be mapped in with the usual 216 + * tlb_flush mechanism because this is part of that mechanism 217 + */ 218 + fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); 219 + addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, 220 + PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); 221 + if (addr == MAP_FAILED) { 222 + printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, " 223 + "errno = %d\n", STUB_CODE, errno); 224 + exit(1); 225 + } 226 + 227 + if (stack != NULL) { 228 + fd = phys_mapping(to_phys(stack), &offset); 229 + addr = mmap((void *) STUB_DATA, 230 + UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, 231 + MAP_FIXED | MAP_SHARED, fd, offset); 206 232 if (addr == MAP_FAILED) { 207 - printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, " 208 - "errno = %d\n", STUB_CODE, errno); 233 + printk(UM_KERN_ERR "mapping segfault stack " 234 + "at 0x%lx failed, errno = %d\n", 235 + STUB_DATA, errno); 209 236 exit(1); 210 237 } 211 - 212 - if (stack != NULL) { 213 - fd = phys_mapping(to_phys(stack), &offset); 214 - addr = mmap((void *) STUB_DATA, 215 - UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, 216 - MAP_FIXED | MAP_SHARED, fd, offset); 217 - if (addr == MAP_FAILED) { 218 - printk(UM_KERN_ERR "mapping segfault stack " 219 - "at 0x%lx failed, errno = %d\n", 220 - STUB_DATA, errno); 221 - exit(1); 222 - } 223 - } 224 238 } 225 - if (!ptrace_faultinfo && (stack != NULL)) { 239 + if (stack != NULL) { 226 240 struct sigaction sa; 227 241 228 242 unsigned long v = STUB_CODE + ··· 264 286 265 287 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); 266 288 267 - flags = CLONE_FILES; 268 - if (proc_mm) 269 - flags |= CLONE_VM; 270 - else 271 - flags |= SIGCHLD; 289 + flags = CLONE_FILES | SIGCHLD; 272 290 273 291 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); 274 292 if (pid < 0) { ··· 387 413 388 414 switch (sig) { 389 415 case SIGSEGV: 390 - if (PTRACE_FULL_FAULTINFO || 391 - !ptrace_faultinfo) { 416 + if (PTRACE_FULL_FAULTINFO) { 392 417 get_skas_faultinfo(pid, 393 418 &regs->faultinfo); 394 419 (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, ··· 544 571 return err; 545 572 } 546 573 547 - /* 548 - * This is used only, if stub pages are needed, while proc_mm is 549 - * available. Opening /proc/mm creates a new mm_context, which lacks 550 - * the stub-pages. Thus, we map them using /proc/mm-fd 551 - */ 552 - int map_stub_pages(int fd, unsigned long code, unsigned long data, 553 - unsigned long stack) 554 - { 555 - struct proc_mm_op mmop; 556 - int n; 557 - unsigned long long code_offset; 558 - int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), 559 - &code_offset); 560 - 561 - mmop = ((struct proc_mm_op) { .op = MM_MMAP, 562 - .u = 563 - { .mmap = 564 - { .addr = code, 565 - .len = UM_KERN_PAGE_SIZE, 566 - .prot = PROT_EXEC, 567 - .flags = MAP_FIXED | MAP_PRIVATE, 568 - .fd = code_fd, 569 - .offset = code_offset 570 - } } }); 571 - CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); 572 - if (n != sizeof(mmop)) { 573 - n = errno; 574 - printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " 575 - "offset = %llx\n", code, code_fd, 576 - (unsigned long long) code_offset); 577 - printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code " 578 - "failed, err = %d\n", n); 579 - return -n; 580 - } 581 - 582 - if (stack) { 583 - unsigned long long map_offset; 584 - int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); 585 - mmop = ((struct proc_mm_op) 586 - { .op = MM_MMAP, 587 - .u = 588 - { .mmap = 589 - { .addr = data, 590 - .len = UM_KERN_PAGE_SIZE, 591 - .prot = PROT_READ | PROT_WRITE, 592 - .flags = MAP_FIXED | MAP_SHARED, 593 - .fd = map_fd, 594 - .offset = map_offset 595 - } } }); 596 - CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); 597 - if (n != sizeof(mmop)) { 598 - n = errno; 599 - printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for " 600 - "data failed, err = %d\n", n); 601 - return -n; 602 - } 603 - } 604 - 605 - return 0; 606 - } 607 - 608 574 void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) 609 575 { 610 576 (*buf)[0].JB_IP = (unsigned long) handler; ··· 640 728 641 729 void __switch_mm(struct mm_id *mm_idp) 642 730 { 643 - int err; 644 - 645 - /* FIXME: need cpu pid in __switch_mm */ 646 - if (proc_mm) { 647 - err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, 648 - mm_idp->u.mm_fd); 649 - if (err) { 650 - printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM " 651 - "failed, errno = %d\n", errno); 652 - fatal_sigsegv(); 653 - } 654 - } 655 - else userspace_pid[0] = mm_idp->u.pid; 731 + userspace_pid[0] = mm_idp->u.pid; 656 732 }
-154
arch/um/os-Linux/start_up.c
··· 24 24 #include <ptrace_user.h> 25 25 #include <registers.h> 26 26 #include <skas.h> 27 - #include <skas_ptrace.h> 28 27 29 28 static void ptrace_child(void) 30 29 { ··· 140 141 141 142 return ret; 142 143 } 143 - 144 - /* Changed only during early boot */ 145 - int ptrace_faultinfo; 146 - static int disable_ptrace_faultinfo; 147 - 148 - int ptrace_ldt; 149 - static int disable_ptrace_ldt; 150 - 151 - int proc_mm; 152 - static int disable_proc_mm; 153 - 154 - int have_switch_mm; 155 - static int disable_switch_mm; 156 - 157 - int skas_needs_stub; 158 - 159 - static int __init skas0_cmd_param(char *str, int* add) 160 - { 161 - disable_ptrace_faultinfo = 1; 162 - disable_ptrace_ldt = 1; 163 - disable_proc_mm = 1; 164 - disable_switch_mm = 1; 165 - 166 - return 0; 167 - } 168 - 169 - /* The two __uml_setup would conflict, without this stupid alias. */ 170 - 171 - static int __init mode_skas0_cmd_param(char *str, int* add) 172 - __attribute__((alias("skas0_cmd_param"))); 173 - 174 - __uml_setup("skas0", skas0_cmd_param, 175 - "skas0\n" 176 - " Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n"); 177 - 178 - __uml_setup("mode=skas0", mode_skas0_cmd_param, 179 - "mode=skas0\n" 180 - " Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n"); 181 144 182 145 /* Changed only during early boot */ 183 146 static int force_sysemu_disabled = 0; ··· 335 374 if (init_registers(pid)) 336 375 fatal("Failed to initialize default registers"); 337 376 stop_ptraced_child(pid, 1, 1); 338 - } 339 - 340 - static int __init noprocmm_cmd_param(char *str, int* add) 341 - { 342 - disable_proc_mm = 1; 343 - return 0; 344 - } 345 - 346 - __uml_setup("noprocmm", noprocmm_cmd_param, 347 - "noprocmm\n" 348 - " Turns off usage of /proc/mm, even if host supports it.\n" 349 - " To support /proc/mm, the host needs to be patched using\n" 350 - " the current skas3 patch.\n\n"); 351 - 352 - static int __init noptracefaultinfo_cmd_param(char *str, int* add) 353 - { 354 - disable_ptrace_faultinfo = 1; 355 - return 0; 356 - } 357 - 358 - __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, 359 - "noptracefaultinfo\n" 360 - " Turns off usage of PTRACE_FAULTINFO, even if host supports\n" 361 - " it. To support PTRACE_FAULTINFO, the host needs to be patched\n" 362 - " using the current skas3 patch.\n\n"); 363 - 364 - static int __init noptraceldt_cmd_param(char *str, int* add) 365 - { 366 - disable_ptrace_ldt = 1; 367 - return 0; 368 - } 369 - 370 - __uml_setup("noptraceldt", noptraceldt_cmd_param, 371 - "noptraceldt\n" 372 - " Turns off usage of PTRACE_LDT, even if host supports it.\n" 373 - " To support PTRACE_LDT, the host needs to be patched using\n" 374 - " the current skas3 patch.\n\n"); 375 - 376 - static inline void check_skas3_ptrace_faultinfo(void) 377 - { 378 - struct ptrace_faultinfo fi; 379 - int pid, n; 380 - 381 - non_fatal(" - PTRACE_FAULTINFO..."); 382 - pid = start_ptraced_child(); 383 - 384 - n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); 385 - if (n < 0) { 386 - if (errno == EIO) 387 - non_fatal("not found\n"); 388 - else 389 - perror("not found"); 390 - } else if (disable_ptrace_faultinfo) 391 - non_fatal("found but disabled on command line\n"); 392 - else { 393 - ptrace_faultinfo = 1; 394 - non_fatal("found\n"); 395 - } 396 - 397 - stop_ptraced_child(pid, 1, 1); 398 - } 399 - 400 - static inline void check_skas3_ptrace_ldt(void) 401 - { 402 - #ifdef PTRACE_LDT 403 - int pid, n; 404 - unsigned char ldtbuf[40]; 405 - struct ptrace_ldt ldt_op = (struct ptrace_ldt) { 406 - .func = 2, /* read default ldt */ 407 - .ptr = ldtbuf, 408 - .bytecount = sizeof(ldtbuf)}; 409 - 410 - non_fatal(" - PTRACE_LDT..."); 411 - pid = start_ptraced_child(); 412 - 413 - n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); 414 - if (n < 0) { 415 - if (errno == EIO) 416 - non_fatal("not found\n"); 417 - else 418 - perror("not found"); 419 - } else if (disable_ptrace_ldt) 420 - non_fatal("found, but use is disabled\n"); 421 - else { 422 - ptrace_ldt = 1; 423 - non_fatal("found\n"); 424 - } 425 - 426 - stop_ptraced_child(pid, 1, 1); 427 - #endif 428 - } 429 - 430 - static inline void check_skas3_proc_mm(void) 431 - { 432 - non_fatal(" - /proc/mm..."); 433 - if (access("/proc/mm", W_OK) < 0) 434 - perror("not found"); 435 - else if (disable_proc_mm) 436 - non_fatal("found but disabled on command line\n"); 437 - else { 438 - proc_mm = 1; 439 - non_fatal("found\n"); 440 - } 441 - } 442 - 443 - void can_do_skas(void) 444 - { 445 - non_fatal("Checking for the skas3 patch in the host:\n"); 446 - 447 - check_skas3_proc_mm(); 448 - check_skas3_ptrace_faultinfo(); 449 - check_skas3_ptrace_ldt(); 450 - 451 - if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) 452 - skas_needs_stub = 1; 453 377 } 454 378 455 379 int __init parse_iomem(char *str, int *add)
+48 -179
arch/x86/um/ldt.c
··· 8 8 #include <linux/slab.h> 9 9 #include <asm/unistd.h> 10 10 #include <os.h> 11 - #include <proc_mm.h> 12 11 #include <skas.h> 13 - #include <skas_ptrace.h> 14 12 #include <sysdep/tls.h> 15 13 16 14 extern int modify_ldt(int func, void *ptr, unsigned long bytecount); ··· 17 19 struct user_desc *desc, void **addr, int done) 18 20 { 19 21 long res; 20 - 21 - if (proc_mm) { 22 - /* 23 - * This is a special handling for the case, that the mm to 24 - * modify isn't current->active_mm. 25 - * If this is called directly by modify_ldt, 26 - * (current->active_mm->context.skas.u == mm_idp) 27 - * will be true. So no call to __switch_mm(mm_idp) is done. 28 - * If this is called in case of init_new_ldt or PTRACE_LDT, 29 - * mm_idp won't belong to current->active_mm, but child->mm. 30 - * So we need to switch child's mm into our userspace, then 31 - * later switch back. 32 - * 33 - * Note: I'm unsure: should interrupts be disabled here? 34 - */ 35 - if (!current->active_mm || current->active_mm == &init_mm || 36 - mm_idp != &current->active_mm->context.id) 37 - __switch_mm(mm_idp); 22 + void *stub_addr; 23 + res = syscall_stub_data(mm_idp, (unsigned long *)desc, 24 + (sizeof(*desc) + sizeof(long) - 1) & 25 + ~(sizeof(long) - 1), 26 + addr, &stub_addr); 27 + if (!res) { 28 + unsigned long args[] = { func, 29 + (unsigned long)stub_addr, 30 + sizeof(*desc), 31 + 0, 0, 0 }; 32 + res = run_syscall_stub(mm_idp, __NR_modify_ldt, args, 33 + 0, addr, done); 38 34 } 39 - 40 - if (ptrace_ldt) { 41 - struct ptrace_ldt ldt_op = (struct ptrace_ldt) { 42 - .func = func, 43 - .ptr = desc, 44 - .bytecount = sizeof(*desc)}; 45 - u32 cpu; 46 - int pid; 47 - 48 - if (!proc_mm) 49 - pid = mm_idp->u.pid; 50 - else { 51 - cpu = get_cpu(); 52 - pid = userspace_pid[cpu]; 53 - } 54 - 55 - res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); 56 - 57 - if (proc_mm) 58 - put_cpu(); 59 - } 60 - else { 61 - void *stub_addr; 62 - res = syscall_stub_data(mm_idp, (unsigned long *)desc, 63 - (sizeof(*desc) + sizeof(long) - 1) & 64 - ~(sizeof(long) - 1), 65 - addr, &stub_addr); 66 - if (!res) { 67 - unsigned long args[] = { func, 68 - (unsigned long)stub_addr, 69 - sizeof(*desc), 70 - 0, 0, 0 }; 71 - res = run_syscall_stub(mm_idp, __NR_modify_ldt, args, 72 - 0, addr, done); 73 - } 74 - } 75 - 76 - if (proc_mm) { 77 - /* 78 - * This is the second part of special handling, that makes 79 - * PTRACE_LDT possible to implement. 80 - */ 81 - if (current->active_mm && current->active_mm != &init_mm && 82 - mm_idp != &current->active_mm->context.id) 83 - __switch_mm(&current->active_mm->context.id); 84 - } 85 - 86 - return res; 87 - } 88 - 89 - static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) 90 - { 91 - int res, n; 92 - struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) { 93 - .func = 0, 94 - .bytecount = bytecount, 95 - .ptr = kmalloc(bytecount, GFP_KERNEL)}; 96 - u32 cpu; 97 - 98 - if (ptrace_ldt.ptr == NULL) 99 - return -ENOMEM; 100 - 101 - /* 102 - * This is called from sys_modify_ldt only, so userspace_pid gives 103 - * us the right number 104 - */ 105 - 106 - cpu = get_cpu(); 107 - res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); 108 - put_cpu(); 109 - if (res < 0) 110 - goto out; 111 - 112 - n = copy_to_user(ptr, ptrace_ldt.ptr, res); 113 - if (n != 0) 114 - res = -EFAULT; 115 - 116 - out: 117 - kfree(ptrace_ldt.ptr); 118 35 119 36 return res; 120 37 } ··· 57 144 if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) 58 145 bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; 59 146 err = bytecount; 60 - 61 - if (ptrace_ldt) 62 - return read_ldt_from_host(ptr, bytecount); 63 147 64 148 mutex_lock(&ldt->lock); 65 149 if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { ··· 139 229 goto out; 140 230 } 141 231 142 - if (!ptrace_ldt) 143 - mutex_lock(&ldt->lock); 232 + mutex_lock(&ldt->lock); 144 233 145 234 err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); 146 235 if (err) 147 236 goto out_unlock; 148 - else if (ptrace_ldt) { 149 - /* With PTRACE_LDT available, this is used as a flag only */ 150 - ldt->entry_count = 1; 151 - goto out; 152 - } 153 237 154 238 if (ldt_info.entry_number >= ldt->entry_count && 155 239 ldt_info.entry_number >= LDT_DIRECT_ENTRIES) { ··· 297 393 int i; 298 394 long page, err=0; 299 395 void *addr = NULL; 300 - struct proc_mm_op copy; 301 396 302 397 303 - if (!ptrace_ldt) 304 - mutex_init(&new_mm->arch.ldt.lock); 398 + mutex_init(&new_mm->arch.ldt.lock); 305 399 306 400 if (!from_mm) { 307 401 memset(&desc, 0, sizeof(desc)); 308 402 /* 309 - * We have to initialize a clean ldt. 403 + * Now we try to retrieve info about the ldt, we 404 + * inherited from the host. All ldt-entries found 405 + * will be reset in the following loop 310 406 */ 311 - if (proc_mm) { 312 - /* 313 - * If the new mm was created using proc_mm, host's 314 - * default-ldt currently is assigned, which normally 315 - * contains the call-gates for lcall7 and lcall27. 316 - * To remove these gates, we simply write an empty 317 - * entry as number 0 to the host. 318 - */ 319 - err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1); 320 - } 321 - else{ 322 - /* 323 - * Now we try to retrieve info about the ldt, we 324 - * inherited from the host. All ldt-entries found 325 - * will be reset in the following loop 326 - */ 327 - ldt_get_host_info(); 328 - for (num_p=host_ldt_entries; *num_p != -1; num_p++) { 329 - desc.entry_number = *num_p; 330 - err = write_ldt_entry(&new_mm->id, 1, &desc, 331 - &addr, *(num_p + 1) == -1); 332 - if (err) 333 - break; 334 - } 407 + ldt_get_host_info(); 408 + for (num_p=host_ldt_entries; *num_p != -1; num_p++) { 409 + desc.entry_number = *num_p; 410 + err = write_ldt_entry(&new_mm->id, 1, &desc, 411 + &addr, *(num_p + 1) == -1); 412 + if (err) 413 + break; 335 414 } 336 415 new_mm->arch.ldt.entry_count = 0; 337 416 338 417 goto out; 339 418 } 340 419 341 - if (proc_mm) { 342 - /* 343 - * We have a valid from_mm, so we now have to copy the LDT of 344 - * from_mm to new_mm, because using proc_mm an new mm with 345 - * an empty/default LDT was created in new_mm() 346 - */ 347 - copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, 348 - .u = 349 - { .copy_segments = 350 - from_mm->id.u.mm_fd } } ); 351 - i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy)); 352 - if (i != sizeof(copy)) 353 - printk(KERN_ERR "new_mm : /proc/mm copy_segments " 354 - "failed, err = %d\n", -i); 355 - } 356 - 357 - if (!ptrace_ldt) { 358 - /* 359 - * Our local LDT is used to supply the data for 360 - * modify_ldt(READLDT), if PTRACE_LDT isn't available, 361 - * i.e., we have to use the stub for modify_ldt, which 362 - * can't handle the big read buffer of up to 64kB. 363 - */ 364 - mutex_lock(&from_mm->arch.ldt.lock); 365 - if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES) 366 - memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries, 367 - sizeof(new_mm->arch.ldt.u.entries)); 368 - else { 369 - i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE; 370 - while (i-->0) { 371 - page = __get_free_page(GFP_KERNEL|__GFP_ZERO); 372 - if (!page) { 373 - err = -ENOMEM; 374 - break; 375 - } 376 - new_mm->arch.ldt.u.pages[i] = 377 - (struct ldt_entry *) page; 378 - memcpy(new_mm->arch.ldt.u.pages[i], 379 - from_mm->arch.ldt.u.pages[i], PAGE_SIZE); 420 + /* 421 + * Our local LDT is used to supply the data for 422 + * modify_ldt(READLDT), if PTRACE_LDT isn't available, 423 + * i.e., we have to use the stub for modify_ldt, which 424 + * can't handle the big read buffer of up to 64kB. 425 + */ 426 + mutex_lock(&from_mm->arch.ldt.lock); 427 + if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES) 428 + memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries, 429 + sizeof(new_mm->arch.ldt.u.entries)); 430 + else { 431 + i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE; 432 + while (i-->0) { 433 + page = __get_free_page(GFP_KERNEL|__GFP_ZERO); 434 + if (!page) { 435 + err = -ENOMEM; 436 + break; 380 437 } 438 + new_mm->arch.ldt.u.pages[i] = 439 + (struct ldt_entry *) page; 440 + memcpy(new_mm->arch.ldt.u.pages[i], 441 + from_mm->arch.ldt.u.pages[i], PAGE_SIZE); 381 442 } 382 - new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count; 383 - mutex_unlock(&from_mm->arch.ldt.lock); 384 443 } 444 + new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count; 445 + mutex_unlock(&from_mm->arch.ldt.lock); 385 446 386 447 out: 387 448 return err; ··· 357 488 { 358 489 int i; 359 490 360 - if (!ptrace_ldt && mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) { 491 + if (mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) { 361 492 i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE; 362 493 while (i-- > 0) 363 494 free_page((long) mm->arch.ldt.u.pages[i]);
-3
arch/x86/um/shared/sysdep/faultinfo_32.h
··· 27 27 /* This is Page Fault */ 28 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 30 #define PTRACE_FULL_FAULTINFO 0 34 31 35 32 #endif
-3
arch/x86/um/shared/sysdep/faultinfo_64.h
··· 27 27 /* This is Page Fault */ 28 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 30 #define PTRACE_FULL_FAULTINFO 1 34 31 35 32 #endif
-22
arch/x86/um/shared/sysdep/skas_ptrace.h
··· 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