Index: qemu/exec.c =================================================================== --- qemu.orig/exec.c 2007-08-07 21:44:10.000000000 -0400 +++ qemu/exec.c 2007-08-07 21:44:16.000000000 -0400 @@ -1862,6 +1862,29 @@ 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 ) return -1; /* we've wrapped around */ + 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) Index: qemu/cpu-all.h =================================================================== --- qemu.orig/cpu-all.h 2007-08-07 21:44:10.000000000 -0400 +++ qemu/cpu-all.h 2007-08-07 21:44:16.000000000 -0400 @@ -691,6 +691,7 @@ 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); Index: qemu/linux-user/qemu.h =================================================================== --- qemu.orig/linux-user/qemu.h 2007-08-07 21:44:10.000000000 -0400 +++ qemu/linux-user/qemu.h 2007-08-08 17:54:18.000000000 -0400 @@ -171,7 +171,8 @@ #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)\ @@ -238,6 +239,26 @@ __ret;\ }) +#define copy_from_user(hptr, gptr, len) \ +({ \ + int __cfu_ret=0;\ + if( access_ok(VERIFY_READ, gptr, (len) ) )\ + memcpy(hptr,gptr,(len)); \ + else \ + __cfu_ret=1;\ + __cfu_ret; \ +}) + +#define copy_to_user(gptr, hptr, len) \ +({ \ + int __ctu_ret=0;\ + if( access_ok(VERIFY_WRITE, gptr, (len)) )\ + memcpy(gptr,hptr,(len)); \ + else \ + __ctu_ret=1;\ + __ctu_ret; \ +}) + /* Functions for accessing guest memory. The tget and tput functions read/write single values, byteswapping as neccessary. The lock_user gets a pointer to a contiguous area of guest memory, but does not perform