diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-11-14 10:51:00 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-11-14 10:51:00 +0000 |
commit | dae3270c6e25062b9085da0756b68fafedc9bb2c (patch) | |
tree | bbe89088ce3699c28271cb181bdbe1b54573d4e7 | |
parent | 9b0b82037a2ebfb3d38ed2ae23194eadd85b1440 (diff) |
suppressed page_unprotect_range() - fixed access_ok()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3641 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | cpu-all.h | 1 | ||||
-rw-r--r-- | exec.c | 30 | ||||
-rw-r--r-- | linux-user/qemu.h | 7 | ||||
-rw-r--r-- | linux-user/syscall.c | 2 |
4 files changed, 17 insertions, 23 deletions
@@ -690,7 +690,6 @@ extern unsigned long qemu_host_page_mask; 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); @@ -1894,10 +1894,19 @@ int page_check_range(target_ulong start, target_ulong len, int flags) 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) ) + if ((flags & PAGE_READ) && !(p->flags & PAGE_READ)) return -1; + if (flags & PAGE_WRITE) { + if (!(p->flags & PAGE_WRITE_ORG)) + return -1; + /* unprotect the page if it was put read-only because it + contains translated code */ + if (!(p->flags & PAGE_WRITE)) { + if (!page_unprotect(addr, 0, NULL)) + return -1; + } + return 0; + } } return 0; } @@ -1942,21 +1951,6 @@ int page_unprotect(target_ulong address, unsigned long pc, void *puc) return 0; } -/* call this function when system calls directly modify a memory area */ -/* ??? This should be redundant now we have lock_user. */ -void page_unprotect_range(target_ulong data, target_ulong data_size) -{ - target_ulong start, end, addr; - - start = data; - end = start + data_size; - start &= TARGET_PAGE_MASK; - end = TARGET_PAGE_ALIGN(end); - for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - page_unprotect(addr, 0, NULL); - } -} - static inline void tlb_set_dirty(CPUState *env, unsigned long addr, target_ulong vaddr) { diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 581ee27fa..5917cb51a 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -207,8 +207,11 @@ int target_msync(abi_ulong start, abi_ulong len, int flags); #define VERIFY_READ 0 #define VERIFY_WRITE 1 /* implies read access */ -#define access_ok(type,addr,size) \ - (page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0) +static inline int access_ok(int type, abi_ulong addr, abi_ulong size) +{ + return page_check_range((target_ulong)addr, size, + (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0; +} /* NOTE __get_user and __put_user use host pointers and don't check access. */ /* These are usually used to access struct data members once the diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 6c8f689ae..1e4ad96b3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2773,7 +2773,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = 0; /* avoid warning */ break; case TARGET_NR_read: - page_unprotect_range(arg2, arg3); if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) goto efault; ret = get_errno(read(arg1, p, arg3)); @@ -4537,7 +4536,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #ifdef TARGET_NR_pread case TARGET_NR_pread: - page_unprotect_range(arg2, arg3); if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) goto efault; ret = get_errno(pread(arg1, p, arg3, arg4)); |