server: Enforce valid flags for file mappings.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-09-08 12:15:03 +02:00
parent 3d3d080688
commit e5c39a565a
3 changed files with 138 additions and 12 deletions

View File

@ -1444,7 +1444,61 @@ static void test_NtAreMappedFilesTheSame(void)
static void test_CreateFileMapping(void)
{
HANDLE handle, handle2;
HANDLE handle, handle2, file[3];
char path[MAX_PATH], filename[MAX_PATH];
unsigned int i;
NTSTATUS status;
static const struct { DWORD file, flags, error, attrs; } sec_flag_tests[] =
{
/* anonymous mapping */
{ 0, SEC_RESERVE, 0 }, /* 0 */
{ 0, SEC_RESERVE | SEC_NOCACHE, 0 },
{ 0, SEC_RESERVE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
{ 0, SEC_RESERVE | SEC_WRITECOMBINE, 0 },
{ 0, SEC_COMMIT, 0 },
{ 0, SEC_COMMIT | SEC_NOCACHE, 0 }, /* 5 */
{ 0, SEC_COMMIT | SEC_WRITECOMBINE, 0 },
{ 0, SEC_RESERVE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
{ 0, SEC_IMAGE, ERROR_BAD_EXE_FORMAT },
{ 0, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
{ 0, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, /* 10 */
{ 0, SEC_NOCACHE, ERROR_INVALID_PARAMETER },
{ 0, SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
{ 0, SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER },
{ 0, SEC_FILE, ERROR_INVALID_PARAMETER },
{ 0, SEC_FILE | SEC_RESERVE, ERROR_INVALID_PARAMETER }, /* 15 */
{ 0, SEC_FILE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
{ 0, 0, 0, SEC_COMMIT },
/* normal file */
{ 1, SEC_RESERVE, 0, SEC_FILE },
{ 1, SEC_RESERVE | SEC_NOCACHE, 0, SEC_FILE | SEC_NOCACHE },
{ 1, SEC_RESERVE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, /* 20 */
{ 1, SEC_RESERVE | SEC_WRITECOMBINE, 0, SEC_FILE | SEC_WRITECOMBINE },
{ 1, SEC_COMMIT, 0, SEC_FILE },
{ 1, SEC_COMMIT | SEC_NOCACHE, 0, SEC_FILE | SEC_NOCACHE },
{ 1, SEC_COMMIT | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
{ 1, SEC_COMMIT | SEC_WRITECOMBINE, 0, SEC_FILE | SEC_WRITECOMBINE }, /* 25 */
{ 1, SEC_RESERVE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
{ 1, SEC_IMAGE, ERROR_BAD_EXE_FORMAT },
{ 1, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
{ 1, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
{ 1, SEC_NOCACHE, ERROR_INVALID_PARAMETER }, /* 30 */
{ 1, SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
{ 1, SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER },
{ 1, SEC_FILE, ERROR_INVALID_PARAMETER },
{ 1, SEC_FILE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
{ 1, SEC_FILE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, /* 35 */
{ 1, 0, 0, SEC_FILE },
/* PE image file */
{ 2, SEC_IMAGE, 0, SEC_FILE | SEC_IMAGE },
{ 2, SEC_IMAGE | SEC_FILE, ERROR_INVALID_PARAMETER },
{ 2, SEC_IMAGE | SEC_NOCACHE, 0, SEC_FILE | SEC_IMAGE },
{ 2, SEC_IMAGE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER }, /* 40 */
{ 2, SEC_IMAGE | SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER },
{ 2, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
{ 2, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
};
/* test case sensitivity */
@ -1479,6 +1533,62 @@ static void test_CreateFileMapping(void)
ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
CloseHandle( handle );
/* test SEC_* flags */
file[0] = INVALID_HANDLE_VALUE;
GetTempPathA( MAX_PATH, path );
GetTempFileNameA( path, "map", 0, filename );
file[1] = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
ok( file[1] != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
SetFilePointer( file[1], 0x2000, NULL, FILE_BEGIN );
SetEndOfFile( file[1] );
GetSystemDirectoryA( path, MAX_PATH );
strcat( path, "\\kernel32.dll" );
file[2] = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
ok( file[2] != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
for (i = 0; i < sizeof(sec_flag_tests) / sizeof(sec_flag_tests[0]); i++)
{
DWORD flags = sec_flag_tests[i].flags;
DWORD perm = sec_flag_tests[i].file == 2 ? PAGE_READONLY : PAGE_READWRITE;
SetLastError( 0xdeadbeef );
handle = CreateFileMappingA( file[sec_flag_tests[i].file], NULL,
flags | perm, 0, 0x1000, "Wine Test Mapping" );
if (sec_flag_tests[i].error)
{
ok( !handle, "%u: CreateFileMapping succeeded\n", i );
ok( GetLastError() == sec_flag_tests[i].error, "%u: wrong error %u\n", i, GetLastError());
}
else
{
/* SEC_WRITECOMBINE and SEC_IMAGE_NO_EXECUTE not supported on older Windows */
BOOL new_flags = ((flags & SEC_WRITECOMBINE) ||
((flags & SEC_IMAGE_NO_EXECUTE) == SEC_IMAGE_NO_EXECUTE));
ok( handle != NULL || broken(new_flags),
"%u: CreateFileMapping failed with error %u\n", i, GetLastError());
ok( GetLastError() == 0 || broken(new_flags && GetLastError() == ERROR_INVALID_PARAMETER),
"%u: wrong error %u\n", i, GetLastError());
}
if (handle)
{
SECTION_BASIC_INFORMATION info;
DWORD expect = sec_flag_tests[i].attrs ? sec_flag_tests[i].attrs : sec_flag_tests[i].flags;
status = pNtQuerySection( handle, SectionBasicInformation, &info, sizeof(info), NULL );
ok( !status, "%u: NtQuerySection failed err %x\n", i, status );
/* SEC_NOCACHE not supported on older Windows */
ok( info.Attributes == expect || broken( info.Attributes == (expect & ~SEC_NOCACHE) ),
"%u: NtQuerySection wrong attr %08x\n", i, info.Attributes );
CloseHandle( handle );
}
}
CloseHandle( file[1] );
CloseHandle( file[2] );
DeleteFileA( filename );
}
static void test_IsBadReadPtr(void)

View File

@ -340,8 +340,8 @@ HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
DWORD protect, DWORD size_high,
DWORD size_low, LPCWSTR name )
{
static const int sec_flags = SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE;
static const int sec_flags = (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT |
SEC_NOCACHE | SEC_WRITECOMBINE | SEC_LARGE_PAGES);
HANDLE ret;
NTSTATUS status;
DWORD access, sec_type;

View File

@ -497,6 +497,28 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s
return STATUS_INVALID_FILE_FOR_SECTION;
}
static unsigned int get_mapping_flags( obj_handle_t handle, unsigned int flags )
{
switch (flags & (SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_FILE))
{
case SEC_IMAGE:
if (flags & (SEC_WRITECOMBINE | SEC_LARGE_PAGES)) break;
if (handle) return SEC_FILE | SEC_IMAGE;
set_error( STATUS_INVALID_FILE_FOR_SECTION );
return 0;
case SEC_COMMIT:
if (!handle) return flags;
/* fall through */
case SEC_RESERVE:
if (flags & SEC_LARGE_PAGES) break;
if (handle) return SEC_FILE | (flags & (SEC_NOCACHE | SEC_WRITECOMBINE));
return flags;
}
set_error( STATUS_INVALID_PARAMETER );
return 0;
}
static struct object *create_mapping( struct object *root, const struct unicode_str *name,
unsigned int attr, mem_size_t size, unsigned int flags, int protect,
obj_handle_t handle, const struct security_descriptor *sd )
@ -516,12 +538,13 @@ static struct object *create_mapping( struct object *root, const struct unicode_
return &mapping->obj; /* Nothing else to do */
mapping->size = size;
mapping->flags = flags & (SEC_IMAGE | SEC_NOCACHE | SEC_WRITECOMBINE | SEC_LARGE_PAGES);
mapping->protect = protect;
mapping->fd = NULL;
mapping->shared_file = NULL;
mapping->committed = NULL;
if (!(mapping->flags = get_mapping_flags( handle, flags ))) goto error;
if (protect & VPROT_READ) access |= FILE_READ_DATA;
if (protect & VPROT_WRITE) access |= FILE_WRITE_DATA;
@ -530,11 +553,6 @@ static struct object *create_mapping( struct object *root, const struct unicode_
const unsigned int sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
unsigned int mapping_access = FILE_MAPPING_ACCESS;
if (flags & SEC_RESERVE)
{
set_error( STATUS_INVALID_PARAMETER );
goto error;
}
if (!(file = get_file_obj( current->process, handle, access ))) goto error;
fd = get_obj_fd( (struct object *)file );
@ -542,7 +560,6 @@ static struct object *create_mapping( struct object *root, const struct unicode_
if (flags & SEC_IMAGE) mapping_access |= FILE_MAPPING_IMAGE;
else if (protect & VPROT_WRITE) mapping_access |= FILE_MAPPING_WRITE;
mapping->flags |= SEC_FILE;
if (!(mapping->fd = get_fd_object_for_mapping( fd, mapping_access, sharing )))
{
mapping->fd = dup_fd_object( fd, mapping_access, sharing, FILE_SYNCHRONOUS_IO_NONALERT );
@ -585,12 +602,11 @@ static struct object *create_mapping( struct object *root, const struct unicode_
}
else /* Anonymous mapping (no associated file) */
{
if (!mapping->size || (flags & SEC_IMAGE))
if (!mapping->size)
{
set_error( STATUS_INVALID_PARAMETER );
goto error;
}
mapping->flags |= flags & (SEC_COMMIT | SEC_RESERVE);
if (flags & SEC_RESERVE)
{
if (!(mapping->committed = mem_alloc( offsetof(struct ranges, ranges[8]) ))) goto error;