From b802244f5826d73d6d8b6a8135ba6de1fe134b4c Mon Sep 17 00:00:00 2001 From: ths Date: Fri, 2 Nov 2007 19:02:06 +0000 Subject: [PATCH] EFAULT - verify pages are in cache and are read/write, by Thayne Harbaugh. --- cpu-all.h | 1 + exec.c | 27 +++++++++++++++++++++++++++ linux-user/qemu.h | 3 ++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/cpu-all.h b/cpu-all.h index 4e200928fe..76daec9474 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -691,6 +691,7 @@ void page_dump(FILE *f); int page_get_flags(target_ulong address); void page_set_flags(target_ulong start, target_ulong end, int flags); void page_unprotect_range(target_ulong data, target_ulong data_size); +int page_check_range(target_ulong start, target_ulong len, int flags); CPUState *cpu_copy(CPUState *env); diff --git a/exec.c b/exec.c index 0daeaabe25..7c8864c8b7 100644 --- a/exec.c +++ b/exec.c @@ -1875,6 +1875,33 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) spin_unlock(&tb_lock); } +int page_check_range(target_ulong start, target_ulong len, int flags) +{ + PageDesc *p; + target_ulong end; + target_ulong addr; + + end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */ + start = start & TARGET_PAGE_MASK; + + if( end < start ) + /* we've wrapped around */ + return -1; + for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { + p = page_find(addr >> TARGET_PAGE_BITS); + if( !p ) + return -1; + if( !(p->flags & PAGE_VALID) ) + return -1; + + if (!(p->flags & PAGE_READ) && (flags & PAGE_READ) ) + return -1; + if (!(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE) ) + return -1; + } + return 0; +} + /* called from signal handler: invalidate the code and unprotect the page. Return TRUE if the fault was succesfully handled. */ int page_unprotect(target_ulong address, unsigned long pc, void *puc) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 22a4fec61d..bcc0b34f36 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -203,7 +203,8 @@ int target_msync(abi_ulong start, abi_ulong len, int flags); #define VERIFY_READ 0 #define VERIFY_WRITE 1 -#define access_ok(type,addr,size) (1) +#define access_ok(type,addr,size) \ + (page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0) /* NOTE get_user and put_user use host addresses. */ #define __put_user(x,ptr)\ -- 2.11.4.GIT