Commit 3d97b40b05c61d6d85ad1ab9cbb72a076db2aa74
1 parent
7c829863
EFAULT - verify pages are in cache and are read/write, by Thayne Harbaugh.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3506 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
30 additions
and
1 deletions
cpu-all.h
| @@ -691,6 +691,7 @@ void page_dump(FILE *f); | @@ -691,6 +691,7 @@ void page_dump(FILE *f); | ||
| 691 | int page_get_flags(target_ulong address); | 691 | int page_get_flags(target_ulong address); |
| 692 | void page_set_flags(target_ulong start, target_ulong end, int flags); | 692 | void page_set_flags(target_ulong start, target_ulong end, int flags); |
| 693 | void page_unprotect_range(target_ulong data, target_ulong data_size); | 693 | void page_unprotect_range(target_ulong data, target_ulong data_size); |
| 694 | +int page_check_range(target_ulong start, target_ulong len, int flags); | ||
| 694 | 695 | ||
| 695 | CPUState *cpu_copy(CPUState *env); | 696 | CPUState *cpu_copy(CPUState *env); |
| 696 | 697 |
exec.c
| @@ -1875,6 +1875,33 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) | @@ -1875,6 +1875,33 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) | ||
| 1875 | spin_unlock(&tb_lock); | 1875 | spin_unlock(&tb_lock); |
| 1876 | } | 1876 | } |
| 1877 | 1877 | ||
| 1878 | +int page_check_range(target_ulong start, target_ulong len, int flags) | ||
| 1879 | +{ | ||
| 1880 | + PageDesc *p; | ||
| 1881 | + target_ulong end; | ||
| 1882 | + target_ulong addr; | ||
| 1883 | + | ||
| 1884 | + end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */ | ||
| 1885 | + start = start & TARGET_PAGE_MASK; | ||
| 1886 | + | ||
| 1887 | + if( end < start ) | ||
| 1888 | + /* we've wrapped around */ | ||
| 1889 | + return -1; | ||
| 1890 | + for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { | ||
| 1891 | + p = page_find(addr >> TARGET_PAGE_BITS); | ||
| 1892 | + if( !p ) | ||
| 1893 | + return -1; | ||
| 1894 | + if( !(p->flags & PAGE_VALID) ) | ||
| 1895 | + return -1; | ||
| 1896 | + | ||
| 1897 | + if (!(p->flags & PAGE_READ) && (flags & PAGE_READ) ) | ||
| 1898 | + return -1; | ||
| 1899 | + if (!(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE) ) | ||
| 1900 | + return -1; | ||
| 1901 | + } | ||
| 1902 | + return 0; | ||
| 1903 | +} | ||
| 1904 | + | ||
| 1878 | /* called from signal handler: invalidate the code and unprotect the | 1905 | /* called from signal handler: invalidate the code and unprotect the |
| 1879 | page. Return TRUE if the fault was succesfully handled. */ | 1906 | page. Return TRUE if the fault was succesfully handled. */ |
| 1880 | int page_unprotect(target_ulong address, unsigned long pc, void *puc) | 1907 | int page_unprotect(target_ulong address, unsigned long pc, void *puc) |
linux-user/qemu.h
| @@ -203,7 +203,8 @@ int target_msync(abi_ulong start, abi_ulong len, int flags); | @@ -203,7 +203,8 @@ int target_msync(abi_ulong start, abi_ulong len, int flags); | ||
| 203 | #define VERIFY_READ 0 | 203 | #define VERIFY_READ 0 |
| 204 | #define VERIFY_WRITE 1 | 204 | #define VERIFY_WRITE 1 |
| 205 | 205 | ||
| 206 | -#define access_ok(type,addr,size) (1) | 206 | +#define access_ok(type,addr,size) \ |
| 207 | + (page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0) | ||
| 207 | 208 | ||
| 208 | /* NOTE get_user and put_user use host addresses. */ | 209 | /* NOTE get_user and put_user use host addresses. */ |
| 209 | #define __put_user(x,ptr)\ | 210 | #define __put_user(x,ptr)\ |