Module: wine Branch: master Commit: 63bff0937f949379193b6d3b87b03edeaaf77d52 URL: http://source.winehq.org/git/wine.git/?a=commit;h=63bff0937f949379193b6d3b87...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Jan 14 20:17:52 2009 +0100
ntdll: Check buffer for access in NtReadFile before performing I/O.
This also triggers page faults needed for write watches.
---
dlls/ntdll/file.c | 15 +++++++++------ dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/virtual.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 60aec8a..cbb0eac 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -568,6 +568,12 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, &needs_close, &type, &options ); if (status) return status;
+ if (!virtual_check_buffer_for_write( buffer, length )) + { + status = STATUS_ACCESS_VIOLATION; + 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 */ @@ -615,14 +621,11 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, } else 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) - { - status = FILE_GetNtStatus(); - goto done; - } + if (!total) 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 2fcdb1a..306b36d 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -142,6 +142,7 @@ 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 BOOL virtual_check_buffer_for_write( 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 33c946f..74e72fd 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1551,6 +1551,39 @@ BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size )
/*********************************************************************** + * virtual_check_buffer_for_write + * + * Check if a memory buffer can be written to, triggering page faults if needed for write watches. + */ +BOOL virtual_check_buffer_for_write( void *ptr, SIZE_T size ) +{ + if (!size) return TRUE; + if (!ptr) return FALSE; + + __TRY + { + volatile char *p = ptr; + SIZE_T count = size; + + while (count > page_size) + { + *p |= 0; + p += page_size; + count -= page_size; + } + p[0] |= 0; + p[count - 1] |= 0; + } + __EXCEPT_PAGE_FAULT + { + return FALSE; + } + __ENDTRY + return TRUE; +} + + +/*********************************************************************** * VIRTUAL_SetForceExec * * Whether to force exec prot on all views.