Module: wine Branch: master Commit: 39d4f9e272c0cc5a06d7750834ca86f7ce14ee08 URL: http://source.winehq.org/git/wine.git/?a=commit;h=39d4f9e272c0cc5a06d7750834...
Author: Alexandre Julliard julliard@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.