Commit 81efcd33 authored by Bodo Stroesser's avatar Bodo Stroesser Committed by Linus Torvalds

[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: default avatarBodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f206aabb
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include "linux/sched.h" #include "linux/sched.h"
#include "linux/mm.h"
#include "asm/elf.h" #include "asm/elf.h"
#include "asm/ptrace.h" #include "asm/ptrace.h"
#include "asm/uaccess.h" #include "asm/uaccess.h"
...@@ -26,9 +27,17 @@ int is_syscall(unsigned long addr) ...@@ -26,9 +27,17 @@ int is_syscall(unsigned long addr)
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
if(n){ if(n){
printk("is_syscall : failed to read instruction from 0x%lx\n", /* access_process_vm() grants access to vsyscall and stub,
addr); * while copy_from_user doesn't. Maybe access_process_vm is
return(0); * slow, but that doesn't matter, since it will be called only
* in case of singlestepping, if copy_from_user failed.
*/
n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
if(n != sizeof(instr)) {
printk("is_syscall : failed to read instruction from "
"0x%lx\n", addr);
return(1);
}
} }
/* int 0x80 or sysenter */ /* int 0x80 or sysenter */
return((instr == 0x80cd) || (instr == 0x340f)); return((instr == 0x80cd) || (instr == 0x340f));
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/mm.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/elf.h> #include <asm/elf.h>
...@@ -136,9 +137,28 @@ void arch_switch(void) ...@@ -136,9 +137,28 @@ void arch_switch(void)
*/ */
} }
/* XXX Mostly copied from sys-i386 */
int is_syscall(unsigned long addr) int is_syscall(unsigned long addr)
{ {
panic("is_syscall"); unsigned short instr;
int n;
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
if(n){
/* access_process_vm() grants access to vsyscall and stub,
* while copy_from_user doesn't. Maybe access_process_vm is
* slow, but that doesn't matter, since it will be called only
* in case of singlestepping, if copy_from_user failed.
*/
n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
if(n != sizeof(instr)) {
printk("is_syscall : failed to read instruction from "
"0x%lx\n", addr);
return(1);
}
}
/* sysenter */
return(instr == 0x050f);
} }
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment