Alexandre Julliard : ntdll: Check buffer for access in NtWriteFile before performing I/O.

Alexandre Julliard julliard at winehq.org
Thu Jan 15 08:50:55 CST 2009


Module: wine
Branch: master
Commit: 39d4f9e272c0cc5a06d7750834ca86f7ce14ee08
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=39d4f9e272c0cc5a06d7750834ca86f7ce14ee08

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jan 14 20:17:52 2009 +0100

ntdll: Check buffer for access in NtWriteFile before performing I/O.

This also triggers page faults needed for DIB section access.

---

 dlls/ntdll/file.c       |   20 +++++++++++---------
 dlls/ntdll/ntdll_misc.h |    1 +
 dlls/ntdll/virtual.c    |   35 +++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index bea4e0f..60aec8a 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -904,6 +904,12 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
                                  &needs_close, &type, &options );
     if (status) return status;
 
+    if (!virtual_check_buffer_for_read( buffer, length ))
+    {
+        status = STATUS_INVALID_USER_BUFFER;
+        goto done;
+    }
+
     if (type == FD_TYPE_FILE && offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */ )
     {
         /* async I/O doesn't make sense on regular files */
@@ -944,19 +950,15 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
             }
             if (type == FD_TYPE_FILE) continue;  /* no async I/O on regular files */
         }
-        else
+        else if (errno != EAGAIN)
         {
             if (errno == EINTR) continue;
-            if (errno != EAGAIN)
+            if (!total)
             {
-                if (errno == EFAULT)
-                {
-                    status = STATUS_INVALID_USER_BUFFER;
-                    goto err;
-                }
-                status = FILE_GetNtStatus();
-                goto done;
+                if (errno == EFAULT) status = STATUS_INVALID_USER_BUFFER;
+                else status = FILE_GetNtStatus();
             }
+            goto done;
         }
 
         if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index dc121f5..2fcdb1a 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -141,6 +141,7 @@ extern NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T stack_size );
 extern void virtual_clear_thread_stack(void);
 extern BOOL virtual_handle_stack_fault( void *addr );
 extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err );
+extern BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size );
 extern void VIRTUAL_SetForceExec( BOOL enable );
 extern void VIRTUAL_UseLargeAddressSpace(void);
 extern struct _KUSER_SHARED_DATA *user_shared_data;
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 59fc491..33c946f 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -53,6 +53,7 @@
 #include "winternl.h"
 #include "wine/library.h"
 #include "wine/server.h"
+#include "wine/exception.h"
 #include "wine/list.h"
 #include "wine/debug.h"
 #include "ntdll_misc.h"
@@ -1516,6 +1517,40 @@ BOOL virtual_handle_stack_fault( void *addr )
 
 
 /***********************************************************************
+ *           virtual_check_buffer_for_read
+ *
+ * Check if a memory buffer can be read, triggering page faults if needed for DIB section access.
+ */
+BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size )
+{
+    if (!size) return TRUE;
+    if (!ptr) return FALSE;
+
+    __TRY
+    {
+        volatile const char *p = ptr;
+        char dummy;
+        SIZE_T count = size;
+
+        while (count > page_size)
+        {
+            dummy = *p;
+            p += page_size;
+            count -= page_size;
+        }
+        dummy = p[0];
+        dummy = p[count - 1];
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        return FALSE;
+    }
+    __ENDTRY
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           VIRTUAL_SetForceExec
  *
  * Whether to force exec prot on all views.




More information about the wine-cvs mailing list