From: Oblivionsage Date: Wed, 18 Feb 2026 17:22:48 +0000 (+0100) Subject: pe-binary: wrap remaining LE fields with byte-swap macros X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3a2444ba57c90b93b5f76cc7f62b84acb7adec8;p=thirdparty%2Fsystemd.git pe-binary: wrap remaining LE fields with byte-swap macros Follow-up to 02cab70acf5ca67e838d0d34860baacbf9fc3b6c. pe_hash(), section_offset_cmp() and uki_hash() still had a bunch of raw accesses to LE fields (e_lfanew, SizeOfHeaders, PointerToRawData, SizeOfRawData, VirtualSize, certificate_table->Size) without le32toh(), so they'd produce garbage on big-endian. Also wrap VirtualSize in bootspec.c for consistency. --- diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index d8ce45475f5..5901729e884 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -1020,7 +1020,7 @@ static int pe_find_uki_sections( } /* Permit "masking" of sections in the base profile */ - if (found->VirtualSize == 0) + if (le32toh(found->VirtualSize) == 0) continue; r = pe_read_section_data(fd, found, PE_SECTION_SIZE_MAX, (void**) t->data, /* ret_size= */ NULL); diff --git a/src/shared/pe-binary.c b/src/shared/pe-binary.c index 2818fae2cb8..f342801bea2 100644 --- a/src/shared/pe-binary.c +++ b/src/shared/pe-binary.c @@ -336,7 +336,7 @@ static int hash_file(int fd, EVP_MD_CTX *md_ctx, uint64_t offset, uint64_t size) } static int section_offset_cmp(const IMAGE_SECTION_HEADER *a, const IMAGE_SECTION_HEADER *b) { - return CMP(ASSERT_PTR(a)->PointerToRawData, ASSERT_PTR(b)->PointerToRawData); + return CMP(le32toh(ASSERT_PTR(a)->PointerToRawData), le32toh(ASSERT_PTR(b)->PointerToRawData)); } int pe_hash(int fd, @@ -384,7 +384,7 @@ int pe_hash(int fd, return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to allocate message digest."); /* Everything from beginning of file to CheckSum field in PE header */ - p = (uint64_t) dos_header->e_lfanew + + p = (uint64_t) le32toh(dos_header->e_lfanew) + offsetof(PeHeader, optional.CheckSum); r = hash_file(fd, mdctx, 0, p); if (r < 0) @@ -392,7 +392,7 @@ int pe_hash(int fd, p += sizeof(le32_t); /* Everything between the CheckSum field and the Image Data Directory Entry for the Certification Table */ - q = (uint64_t) dos_header->e_lfanew + + q = (uint64_t) le32toh(dos_header->e_lfanew) + PE_HEADER_OPTIONAL_FIELD_OFFSET(pe_header, DataDirectory[IMAGE_DATA_DIRECTORY_INDEX_CERTIFICATION_TABLE]); r = hash_file(fd, mdctx, p, q - p); if (r < 0) @@ -400,7 +400,7 @@ int pe_hash(int fd, q += sizeof(IMAGE_DATA_DIRECTORY); /* The rest of the header + the section table */ - p = pe_header->optional.SizeOfHeaders; + p = le32toh(pe_header->optional.SizeOfHeaders); if (p < q) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "SizeOfHeaders too short."); r = hash_file(fd, mdctx, q, p - q); @@ -411,19 +411,19 @@ int pe_hash(int fd, typesafe_qsort(sections, le16toh(pe_header->pe.NumberOfSections), section_offset_cmp); FOREACH_ARRAY(section, sections, le16toh(pe_header->pe.NumberOfSections)) { - r = hash_file(fd, mdctx, section->PointerToRawData, section->SizeOfRawData); + r = hash_file(fd, mdctx, le32toh(section->PointerToRawData), le32toh(section->SizeOfRawData)); if (r < 0) return r; - p += section->SizeOfRawData; + p += le32toh(section->SizeOfRawData); } if ((uint64_t) st.st_size > p) { - if (st.st_size - p < certificate_table->Size) + if ((uint64_t) st.st_size - p < le32toh(certificate_table->Size)) return log_debug_errno(errno, "No space for certificate table, refusing."); - r = hash_file(fd, mdctx, p, st.st_size - p - certificate_table->Size); + r = hash_file(fd, mdctx, p, st.st_size - p - le32toh(certificate_table->Size)); if (r < 0) return r; @@ -560,13 +560,13 @@ int uki_hash(int fd, if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to allocate message digest."); - r = hash_file(fd, mdctx, section->PointerToRawData, MIN(section->VirtualSize, section->SizeOfRawData)); + r = hash_file(fd, mdctx, le32toh(section->PointerToRawData), MIN(le32toh(section->VirtualSize), le32toh(section->SizeOfRawData))); if (r < 0) return r; - if (section->SizeOfRawData < section->VirtualSize) { + if (le32toh(section->SizeOfRawData) < le32toh(section->VirtualSize)) { uint8_t zeroes[1024] = {}; - size_t remaining = section->VirtualSize - section->SizeOfRawData; + size_t remaining = le32toh(section->VirtualSize) - le32toh(section->SizeOfRawData); while (remaining > 0) { size_t sz = MIN(sizeof(zeroes), remaining);