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

This also triggers page faults needed for DIB section access.
This commit is contained in:
Alexandre Julliard 2009-01-14 20:17:52 +01:00
parent 51c7fe5fc7
commit 39d4f9e272
3 changed files with 47 additions and 9 deletions

View File

@ -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)))

View File

@ -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;

View File

@ -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"
@ -1515,6 +1516,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
*