forked from Mirrors/wine-wine
ntdll: Add an access check for file mappings.
parent
0e85fc66de
commit
3a5ee02735
|
@ -639,7 +639,7 @@ static void test_VirtualProtect(void *base, void *section)
|
||||||
ret = VirtualProtect(section, si.dwPageSize, td[i].prot_set, &old_prot);
|
ret = VirtualProtect(section, si.dwPageSize, td[i].prot_set, &old_prot);
|
||||||
if (td[i].prot_get)
|
if (td[i].prot_get)
|
||||||
{
|
{
|
||||||
ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
|
ok(ret, "%d: VirtualProtect error %d, requested prot %#x\n", i, GetLastError(), td[i].prot_set);
|
||||||
ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
|
ok(old_prot == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, old_prot);
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
|
|
|
@ -2207,7 +2207,6 @@ static void test_mapping(void)
|
||||||
/* NT4 doesn't fail on incompatible map and view */
|
/* NT4 doesn't fail on incompatible map and view */
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
todo_wine
|
|
||||||
ok(broken(ret), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
|
ok(broken(ret), "VirtualProtect should fail, map %#x, view %#x, requested prot %#x\n", page_prot[i], view[j].prot, page_prot[k]);
|
||||||
skip("Incompatible map and view are not properly handled on this platform\n");
|
skip("Incompatible map and view are not properly handled on this platform\n");
|
||||||
break; /* NT4 won't pass remaining tests */
|
break; /* NT4 won't pass remaining tests */
|
||||||
|
|
|
@ -73,6 +73,7 @@ struct file_view
|
||||||
void *base; /* Base address */
|
void *base; /* Base address */
|
||||||
size_t size; /* Size in bytes */
|
size_t size; /* Size in bytes */
|
||||||
HANDLE mapping; /* Handle to the file mapping */
|
HANDLE mapping; /* Handle to the file mapping */
|
||||||
|
unsigned int map_protect; /* Mapping protection */
|
||||||
unsigned int protect; /* Protection for all pages at allocation time */
|
unsigned int protect; /* Protection for all pages at allocation time */
|
||||||
BYTE prot[1]; /* Protection byte for each page */
|
BYTE prot[1]; /* Protection byte for each page */
|
||||||
};
|
};
|
||||||
|
@ -474,6 +475,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz
|
||||||
view->base = base;
|
view->base = base;
|
||||||
view->size = size;
|
view->size = size;
|
||||||
view->mapping = 0;
|
view->mapping = 0;
|
||||||
|
view->map_protect = 0;
|
||||||
view->protect = vprot;
|
view->protect = vprot;
|
||||||
memset( view->prot, vprot, size >> page_shift );
|
memset( view->prot, vprot, size >> page_shift );
|
||||||
|
|
||||||
|
@ -1116,7 +1118,7 @@ static NTSTATUS stat_mapping_file( struct file_view *view, struct stat *st )
|
||||||
* Map an executable (PE format) image into memory.
|
* Map an executable (PE format) image into memory.
|
||||||
*/
|
*/
|
||||||
static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_size, SIZE_T mask,
|
static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_size, SIZE_T mask,
|
||||||
SIZE_T header_size, int shared_fd, HANDLE dup_mapping, PVOID *addr_ptr )
|
SIZE_T header_size, int shared_fd, HANDLE dup_mapping, unsigned int map_vprot, PVOID *addr_ptr )
|
||||||
{
|
{
|
||||||
IMAGE_DOS_HEADER *dos;
|
IMAGE_DOS_HEADER *dos;
|
||||||
IMAGE_NT_HEADERS *nt;
|
IMAGE_NT_HEADERS *nt;
|
||||||
|
@ -1363,6 +1365,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
|
||||||
|
|
||||||
done:
|
done:
|
||||||
view->mapping = dup_mapping;
|
view->mapping = dup_mapping;
|
||||||
|
view->map_protect = map_vprot;
|
||||||
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||||
|
|
||||||
*addr_ptr = ptr;
|
*addr_ptr = ptr;
|
||||||
|
@ -2039,6 +2042,34 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ULONG map_protection_to_access( ULONG vprot )
|
||||||
|
{
|
||||||
|
vprot &= VPROT_READ | VPROT_WRITE | VPROT_EXEC | VPROT_WRITECOPY;
|
||||||
|
if (vprot & VPROT_EXEC)
|
||||||
|
{
|
||||||
|
if (vprot & VPROT_WRITE) vprot |= VPROT_WRITECOPY;
|
||||||
|
}
|
||||||
|
else vprot &= ~VPROT_WRITECOPY;
|
||||||
|
return vprot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL is_compatible_protection( const struct file_view *view, ULONG new_prot )
|
||||||
|
{
|
||||||
|
ULONG view_prot, map_prot;
|
||||||
|
|
||||||
|
view_prot = map_protection_to_access( view->protect );
|
||||||
|
new_prot = map_protection_to_access( new_prot );
|
||||||
|
|
||||||
|
if (view_prot == new_prot) return TRUE;
|
||||||
|
if (!view_prot) return FALSE;
|
||||||
|
|
||||||
|
if ((view_prot & new_prot) != new_prot) return FALSE;
|
||||||
|
|
||||||
|
map_prot = map_protection_to_access( view->map_protect );
|
||||||
|
if ((map_prot & new_prot) == new_prot) return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* NtProtectVirtualMemory (NTDLL.@)
|
* NtProtectVirtualMemory (NTDLL.@)
|
||||||
|
@ -2098,11 +2129,15 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
|
||||||
if ((new_vprot & VPROT_WRITECOPY) && (view->protect & VPROT_VALLOC))
|
if ((new_vprot & VPROT_WRITECOPY) && (view->protect & VPROT_VALLOC))
|
||||||
status = STATUS_INVALID_PAGE_PROTECTION;
|
status = STATUS_INVALID_PAGE_PROTECTION;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (!view->mapping || is_compatible_protection( view, new_vprot ))
|
||||||
{
|
{
|
||||||
new_vprot |= VPROT_COMMITTED;
|
new_vprot |= VPROT_COMMITTED;
|
||||||
if (old_prot) *old_prot = VIRTUAL_GetWin32Prot( vprot );
|
if (old_prot) *old_prot = VIRTUAL_GetWin32Prot( vprot );
|
||||||
if (!VIRTUAL_SetProt( view, base, size, new_vprot )) status = STATUS_ACCESS_DENIED;
|
if (!VIRTUAL_SetProt( view, base, size, new_vprot )) status = STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
else status = STATUS_INVALID_PAGE_PROTECTION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else status = STATUS_NOT_COMMITTED;
|
else status = STATUS_NOT_COMMITTED;
|
||||||
|
@ -2571,14 +2606,14 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
|
||||||
if ((res = server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA,
|
if ((res = server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA,
|
||||||
&shared_fd, &shared_needs_close, NULL, NULL ))) goto done;
|
&shared_fd, &shared_needs_close, NULL, NULL ))) goto done;
|
||||||
res = map_image( handle, unix_handle, base, size, mask, header_size,
|
res = map_image( handle, unix_handle, base, size, mask, header_size,
|
||||||
shared_fd, dup_mapping, addr_ptr );
|
shared_fd, dup_mapping, map_vprot, addr_ptr );
|
||||||
if (shared_needs_close) close( shared_fd );
|
if (shared_needs_close) close( shared_fd );
|
||||||
NtClose( shared_file );
|
NtClose( shared_file );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = map_image( handle, unix_handle, base, size, mask, header_size,
|
res = map_image( handle, unix_handle, base, size, mask, header_size,
|
||||||
-1, dup_mapping, addr_ptr );
|
-1, dup_mapping, map_vprot, addr_ptr );
|
||||||
}
|
}
|
||||||
if (needs_close) close( unix_handle );
|
if (needs_close) close( unix_handle );
|
||||||
if (res >= 0) *size_ptr = size;
|
if (res >= 0) *size_ptr = size;
|
||||||
|
@ -2628,6 +2663,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
|
||||||
*addr_ptr = view->base;
|
*addr_ptr = view->base;
|
||||||
*size_ptr = size;
|
*size_ptr = size;
|
||||||
view->mapping = dup_mapping;
|
view->mapping = dup_mapping;
|
||||||
|
view->map_protect = map_vprot;
|
||||||
dup_mapping = 0; /* don't close it */
|
dup_mapping = 0; /* don't close it */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue