On Wed, 2007-11-07 at 20:18 +0100, Fabrice Bellard wrote:

> - Fix page_check_range() so that it handles writes to pages containing
> code by calling page_unprotect when necessary (the current code can fail
> in this case !).
> 
> - Suppress no longer needed page_unprotect_range() call in syscall.c.

Something like this?

Looks like exec.c needs some attention regarding target_ulong/abi_ulong.
Index: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c	2007-11-12 09:56:01.000000000 -0700
+++ qemu/linux-user/syscall.c	2007-11-12 09:56:12.000000000 -0700
@@ -2745,7 +2745,6 @@
         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));
@@ -4538,7 +4537,6 @@
         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));
Index: qemu/exec.c
===================================================================
--- qemu.orig/exec.c	2007-11-12 09:56:01.000000000 -0700
+++ qemu/exec.c	2007-11-12 10:00:41.000000000 -0700
@@ -1898,6 +1898,9 @@
             return -1;
         if (!(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE) )
             return -1;
+        if ((p->flags & PAGE_EXEC) && (flags & PAGE_WRITE)
+            && page_unprotect(addr, 0, NULL))
+            return -1;
     }
     return 0;
 }
@@ -1942,21 +1945,6 @@
     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)
 {

Reply via email to