ntdll: Check buffer for access in NtReadFile before performing I/O.
This also triggers page faults needed for write watches.
This commit is contained in:
parent
39d4f9e272
commit
63bff0937f
|
@ -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)))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1550,6 +1550,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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue