diff options
author | Bodo Stroesser <bstroesser@fujitsu-siemens.com> | 2006-03-27 04:14:34 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-27 11:44:38 -0500 |
commit | 81efcd3300754462537ffac60336158b2f773b4e (patch) | |
tree | f957ccb8cacabcecf5cfd67c1feda5b1908cac0c /arch | |
parent | f206aabb035318ac4bafbf0b87798335de3634df (diff) |
[PATCH] uml: more carefully test whether we are in a system call
For security reasons, UML in is_syscall() needs to have access to code in
vsyscall-page. The current implementation grants this access by explicitly
allowing access to vsyscall in access_ok_skas(). With this change,
copy_from_user() may be used to read the code. Ptrace access to vsyscall-page
for debugging already was implemented in get_user_pages() by mainline. In
i386, copy_from_user can't access vsyscall-page, but returns EFAULT.
To make UML behave as i386 does, I changed is_syscall to use
access_process_vm(current) to read the code from vsyscall-page. This doesn't
hurt security, but simplifies the code and prepares implementation of
stub-vmas.
Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/um/sys-i386/ptrace.c | 15 | ||||
-rw-r--r-- | arch/um/sys-x86_64/ptrace.c | 22 |
2 files changed, 33 insertions, 4 deletions
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index e839ce65ad28..8032a105949a 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/config.h> | 6 | #include <linux/config.h> |
7 | #include <linux/compiler.h> | 7 | #include <linux/compiler.h> |
8 | #include "linux/sched.h" | 8 | #include "linux/sched.h" |
9 | #include "linux/mm.h" | ||
9 | #include "asm/elf.h" | 10 | #include "asm/elf.h" |
10 | #include "asm/ptrace.h" | 11 | #include "asm/ptrace.h" |
11 | #include "asm/uaccess.h" | 12 | #include "asm/uaccess.h" |
@@ -26,9 +27,17 @@ int is_syscall(unsigned long addr) | |||
26 | 27 | ||
27 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); | 28 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); |
28 | if(n){ | 29 | if(n){ |
29 | printk("is_syscall : failed to read instruction from 0x%lx\n", | 30 | /* access_process_vm() grants access to vsyscall and stub, |
30 | addr); | 31 | * while copy_from_user doesn't. Maybe access_process_vm is |
31 | return(0); | 32 | * slow, but that doesn't matter, since it will be called only |
33 | * in case of singlestepping, if copy_from_user failed. | ||
34 | */ | ||
35 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); | ||
36 | if(n != sizeof(instr)) { | ||
37 | printk("is_syscall : failed to read instruction from " | ||
38 | "0x%lx\n", addr); | ||
39 | return(1); | ||
40 | } | ||
32 | } | 41 | } |
33 | /* int 0x80 or sysenter */ | 42 | /* int 0x80 or sysenter */ |
34 | return((instr == 0x80cd) || (instr == 0x340f)); | 43 | return((instr == 0x80cd) || (instr == 0x340f)); |
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index 74eee5c7c6dd..147bbf05cbc2 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <asm/ptrace.h> | 8 | #include <asm/ptrace.h> |
9 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/mm.h> | ||
11 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
12 | #include <asm/elf.h> | 13 | #include <asm/elf.h> |
13 | 14 | ||
@@ -136,9 +137,28 @@ void arch_switch(void) | |||
136 | */ | 137 | */ |
137 | } | 138 | } |
138 | 139 | ||
140 | /* XXX Mostly copied from sys-i386 */ | ||
139 | int is_syscall(unsigned long addr) | 141 | int is_syscall(unsigned long addr) |
140 | { | 142 | { |
141 | panic("is_syscall"); | 143 | unsigned short instr; |
144 | int n; | ||
145 | |||
146 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); | ||
147 | if(n){ | ||
148 | /* access_process_vm() grants access to vsyscall and stub, | ||
149 | * while copy_from_user doesn't. Maybe access_process_vm is | ||
150 | * slow, but that doesn't matter, since it will be called only | ||
151 | * in case of singlestepping, if copy_from_user failed. | ||
152 | */ | ||
153 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); | ||
154 | if(n != sizeof(instr)) { | ||
155 | printk("is_syscall : failed to read instruction from " | ||
156 | "0x%lx\n", addr); | ||
157 | return(1); | ||
158 | } | ||
159 | } | ||
160 | /* sysenter */ | ||
161 | return(instr == 0x050f); | ||
142 | } | 162 | } |
143 | 163 | ||
144 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) | 164 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) |