Better handling of conflicting section information between
SizeOfRawData and VirtualSize.
This commit is contained in:
parent
050b9ebf22
commit
4ebd2fc0ff
|
@ -920,27 +920,36 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
|
||||||
|
|
||||||
for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
|
for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
|
||||||
{
|
{
|
||||||
SIZE_T size;
|
SIZE_T map_size, file_size, end;
|
||||||
|
|
||||||
/* a few sanity checks */
|
if (!sec->Misc.VirtualSize)
|
||||||
size = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
|
|
||||||
if (sec->VirtualAddress > total_size || size > total_size || size < sec->VirtualAddress)
|
|
||||||
{
|
{
|
||||||
ERR_(module)( "Section %.8s too large (%lx+%lx/%lx)\n",
|
file_size = sec->SizeOfRawData;
|
||||||
sec->Name, sec->VirtualAddress, sec->Misc.VirtualSize, total_size );
|
map_size = ROUND_SIZE( 0, file_size );
|
||||||
goto error;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
map_size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
|
||||||
|
file_size = min( sec->SizeOfRawData, map_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
|
/* a few sanity checks */
|
||||||
|
end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size );
|
||||||
|
if (sec->VirtualAddress > total_size || end > total_size || end < sec->VirtualAddress)
|
||||||
|
{
|
||||||
|
ERR_(module)( "Section %.8s too large (%lx+%lx/%lx)\n",
|
||||||
|
sec->Name, sec->VirtualAddress, map_size, total_size );
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&
|
if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&
|
||||||
(sec->Characteristics & IMAGE_SCN_MEM_WRITE))
|
(sec->Characteristics & IMAGE_SCN_MEM_WRITE))
|
||||||
{
|
{
|
||||||
TRACE_(module)( "mapping shared section %.8s at %p off %lx (%x) size %lx (%lx) flags %lx\n",
|
TRACE_(module)( "mapping shared section %.8s at %p off %lx (%x) size %lx (%lx) flags %lx\n",
|
||||||
sec->Name, ptr + sec->VirtualAddress,
|
sec->Name, ptr + sec->VirtualAddress,
|
||||||
sec->PointerToRawData, (int)pos, sec->SizeOfRawData,
|
sec->PointerToRawData, (int)pos, file_size, map_size,
|
||||||
size, sec->Characteristics );
|
sec->Characteristics );
|
||||||
if (map_file_into_view( view, shared_fd, sec->VirtualAddress, size, pos,
|
if (map_file_into_view( view, shared_fd, sec->VirtualAddress, map_size, pos,
|
||||||
VPROT_COMMITTED | VPROT_READ | PROT_WRITE,
|
VPROT_COMMITTED | VPROT_READ | PROT_WRITE,
|
||||||
FALSE ) != STATUS_SUCCESS)
|
FALSE ) != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -950,33 +959,32 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
|
||||||
|
|
||||||
/* check if the import directory falls inside this section */
|
/* check if the import directory falls inside this section */
|
||||||
if (imports && imports->VirtualAddress >= sec->VirtualAddress &&
|
if (imports && imports->VirtualAddress >= sec->VirtualAddress &&
|
||||||
imports->VirtualAddress < sec->VirtualAddress + size)
|
imports->VirtualAddress < sec->VirtualAddress + map_size)
|
||||||
{
|
{
|
||||||
UINT_PTR base = imports->VirtualAddress & ~page_mask;
|
UINT_PTR base = imports->VirtualAddress & ~page_mask;
|
||||||
UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );
|
UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );
|
||||||
if (end > sec->VirtualAddress + size) end = sec->VirtualAddress + size;
|
if (end > sec->VirtualAddress + map_size) end = sec->VirtualAddress + map_size;
|
||||||
if (end > base)
|
if (end > base)
|
||||||
map_file_into_view( view, shared_fd, base, end - base,
|
map_file_into_view( view, shared_fd, base, end - base,
|
||||||
pos + (base - sec->VirtualAddress),
|
pos + (base - sec->VirtualAddress),
|
||||||
VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
|
VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
|
||||||
FALSE );
|
FALSE );
|
||||||
}
|
}
|
||||||
pos += size;
|
pos += map_size;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE_(module)( "mapping section %.8s at %p off %lx size %lx virt %lx flags %lx\n",
|
TRACE_(module)( "mapping section %.8s at %p off %lx size %lx virt %lx flags %lx\n",
|
||||||
sec->Name, ptr + sec->VirtualAddress,
|
sec->Name, ptr + sec->VirtualAddress,
|
||||||
sec->PointerToRawData, sec->SizeOfRawData,
|
sec->PointerToRawData, sec->SizeOfRawData,
|
||||||
size, sec->Characteristics );
|
sec->Misc.VirtualSize, sec->Characteristics );
|
||||||
|
|
||||||
if (!sec->PointerToRawData || !sec->SizeOfRawData) continue;
|
if (!sec->PointerToRawData || !file_size) continue;
|
||||||
if (sec->SizeOfRawData < size) size = sec->SizeOfRawData;
|
|
||||||
|
|
||||||
/* Note: if the section is not aligned properly map_file_into_view will magically
|
/* Note: if the section is not aligned properly map_file_into_view will magically
|
||||||
* fall back to read(), so we don't need to check anything here.
|
* fall back to read(), so we don't need to check anything here.
|
||||||
*/
|
*/
|
||||||
if (map_file_into_view( view, fd, sec->VirtualAddress, size, sec->PointerToRawData,
|
if (map_file_into_view( view, fd, sec->VirtualAddress, file_size, sec->PointerToRawData,
|
||||||
VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
|
VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
|
||||||
removable ) != STATUS_SUCCESS)
|
removable ) != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -984,15 +992,14 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sec->SizeOfRawData < sec->Misc.VirtualSize) && (sec->SizeOfRawData & page_mask))
|
if (file_size & page_mask)
|
||||||
{
|
{
|
||||||
DWORD end = ROUND_SIZE( 0, sec->SizeOfRawData );
|
end = ROUND_SIZE( 0, file_size );
|
||||||
if (end > sec->Misc.VirtualSize) end = sec->Misc.VirtualSize;
|
if (end > map_size) end = map_size;
|
||||||
TRACE_(module)("clearing %p - %p\n",
|
TRACE_(module)("clearing %p - %p\n",
|
||||||
ptr + sec->VirtualAddress + sec->SizeOfRawData,
|
ptr + sec->VirtualAddress + file_size,
|
||||||
ptr + sec->VirtualAddress + end );
|
ptr + sec->VirtualAddress + end );
|
||||||
memset( ptr + sec->VirtualAddress + sec->SizeOfRawData, 0,
|
memset( ptr + sec->VirtualAddress + file_size, 0, end - file_size );
|
||||||
end - sec->SizeOfRawData );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,11 +116,25 @@ static struct file *get_shared_file( struct mapping *mapping )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return the size of the memory mapping of a given section */
|
||||||
|
static inline unsigned int get_section_map_size( const IMAGE_SECTION_HEADER *sec )
|
||||||
|
{
|
||||||
|
if (!sec->Misc.VirtualSize) return ROUND_SIZE( sec->SizeOfRawData );
|
||||||
|
else return ROUND_SIZE( sec->Misc.VirtualSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the size of the file mapping of a given section */
|
||||||
|
static inline unsigned int get_section_filemap_size( const IMAGE_SECTION_HEADER *sec )
|
||||||
|
{
|
||||||
|
if (!sec->Misc.VirtualSize) return sec->SizeOfRawData;
|
||||||
|
else return min( sec->SizeOfRawData, ROUND_SIZE( sec->Misc.VirtualSize ) );
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate and fill the temp file for a shared PE image mapping */
|
/* allocate and fill the temp file for a shared PE image mapping */
|
||||||
static int build_shared_mapping( struct mapping *mapping, int fd,
|
static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
IMAGE_SECTION_HEADER *sec, unsigned int nb_sec )
|
IMAGE_SECTION_HEADER *sec, unsigned int nb_sec )
|
||||||
{
|
{
|
||||||
unsigned int i, max_size, total_size;
|
unsigned int i, size, max_size, total_size;
|
||||||
off_t shared_pos, read_pos, write_pos;
|
off_t shared_pos, read_pos, write_pos;
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
int shared_fd;
|
int shared_fd;
|
||||||
|
@ -134,9 +148,9 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) &&
|
if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) &&
|
||||||
(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE))
|
(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE))
|
||||||
{
|
{
|
||||||
unsigned int size = ROUND_SIZE( sec[i].Misc.VirtualSize );
|
size = get_section_filemap_size( &sec[i] );
|
||||||
if (size > max_size) max_size = size;
|
if (size > max_size) max_size = size;
|
||||||
total_size += size;
|
total_size += get_section_map_size( &sec[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(mapping->shared_size = total_size)) return 1; /* nothing to do */
|
if (!(mapping->shared_size = total_size)) return 1; /* nothing to do */
|
||||||
|
@ -159,10 +173,11 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue;
|
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue;
|
||||||
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue;
|
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue;
|
||||||
write_pos = shared_pos;
|
write_pos = shared_pos;
|
||||||
shared_pos += ROUND_SIZE( sec[i].Misc.VirtualSize );
|
shared_pos += get_section_map_size( &sec[i] );
|
||||||
if (!sec[i].PointerToRawData || !sec[i].SizeOfRawData) continue;
|
|
||||||
read_pos = sec[i].PointerToRawData;
|
read_pos = sec[i].PointerToRawData;
|
||||||
toread = sec[i].SizeOfRawData;
|
size = get_section_filemap_size( &sec[i] );
|
||||||
|
if (!read_pos || !size) continue;
|
||||||
|
toread = size;
|
||||||
while (toread)
|
while (toread)
|
||||||
{
|
{
|
||||||
long res = pread( fd, buffer + sec[i].SizeOfRawData - toread, toread, read_pos );
|
long res = pread( fd, buffer + sec[i].SizeOfRawData - toread, toread, read_pos );
|
||||||
|
@ -170,8 +185,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
toread -= res;
|
toread -= res;
|
||||||
read_pos += res;
|
read_pos += res;
|
||||||
}
|
}
|
||||||
if (pwrite( shared_fd, buffer, sec[i].SizeOfRawData, write_pos ) != sec[i].SizeOfRawData)
|
if (pwrite( shared_fd, buffer, size, write_pos ) != size) goto error;
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
free( buffer );
|
free( buffer );
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue