pe-binary: only read the raw data of a section
pe_read_section_data() reads VirtualSize bytes starting at PointerToRawData. When VirtualSize is larger than SizeOfRawData, because the section ends with zero-initialized data, it returns the start of the next section, or fails with EBADMSG at the end of the file. Read MIN(VirtualSize, SizeOfRawData) bytes, like systemd-stub and uki_hash() do. (cherry picked from commit f219e7e790ec7b1064b71173ad697f48a5d71830)
This commit is contained in:
committed by
Luca Boccassi
parent
6f076ff729
commit
762840e4e0
@@ -251,7 +251,10 @@ int pe_read_section_data(
|
||||
assert(fd >= 0);
|
||||
assert(section);
|
||||
|
||||
size_t n = le32toh(section->VirtualSize);
|
||||
/* SizeOfRawData includes padding up to the file alignment. VirtualSize is larger than
|
||||
* SizeOfRawData when the section ends with zero-initialized data. The file does not contain
|
||||
* that data. Reading VirtualSize bytes would return bytes of the next section instead. */
|
||||
size_t n = MIN(le32toh(section->VirtualSize), le32toh(section->SizeOfRawData));
|
||||
if (n > MIN(max_size, (size_t) SSIZE_MAX))
|
||||
return -EBADMSG;
|
||||
|
||||
|
||||
@@ -342,6 +342,40 @@ TEST(pe_load_sections_multi_one_past_eof) {
|
||||
ASSERT_ERROR(load_headers_and_sections(fd, &dos, &pe, §ions), EBADMSG);
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* pe_read_section_data
|
||||
* ====================================================================== */
|
||||
|
||||
/* The bytes after the SizeOfRawData bytes of .cmdline belong to .uname, so reading .cmdline must not
|
||||
* return them. */
|
||||
TEST(pe_read_section_data_reads_raw_data_only) {
|
||||
size_t base = SECTION_TABLE_OFFSET + 2 * IMAGE_SECTION_HEADER_BYTES;
|
||||
SectionSpec specs[2] = {
|
||||
{ .name = ".cmdline", .virtual_size = 32, .size_of_raw_data = 16,
|
||||
.pointer_to_raw_data = (uint32_t) base },
|
||||
{ .name = ".uname", .virtual_size = 8, .size_of_raw_data = 16,
|
||||
.pointer_to_raw_data = (uint32_t) (base + 16) },
|
||||
};
|
||||
static const char contents[] = "0123456789abcdefABCDEFGHIJKLMNOP";
|
||||
_cleanup_close_ int fd = build_pe_file(specs, /* n_sections= */ 2, /* override_file_size= */ 0);
|
||||
ASSERT_OK_EQ_ERRNO(pwrite(fd, contents, strlen(contents), base), (ssize_t) strlen(contents));
|
||||
|
||||
_cleanup_free_ PeHeader *pe = NULL;
|
||||
_cleanup_free_ IMAGE_SECTION_HEADER *sections = NULL;
|
||||
ASSERT_OK(pe_load_headers_and_sections(fd, &pe, §ions));
|
||||
|
||||
_cleanup_free_ void *data = NULL;
|
||||
size_t size;
|
||||
ASSERT_OK(pe_read_section_data(fd, sections + 0, SIZE_MAX, &data, &size));
|
||||
ASSERT_EQ(size, 16U);
|
||||
ASSERT_EQ(memcmp(data, "0123456789abcdef", size), 0);
|
||||
|
||||
data = mfree(data);
|
||||
ASSERT_OK(pe_read_section_data(fd, sections + 1, SIZE_MAX, &data, &size));
|
||||
ASSERT_EQ(size, 8U);
|
||||
ASSERT_EQ(memcmp(data, "ABCDEFGH", size), 0);
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* uki_hash — zero-padding cap from PLAN §3.2
|
||||
* ====================================================================== */
|
||||
|
||||
Reference in New Issue
Block a user