]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pe-binary: wrap remaining LE fields with byte-swap macros
authorOblivionsage <cookieandcream560@gmail.com>
Wed, 18 Feb 2026 17:22:48 +0000 (18:22 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 27 Feb 2026 20:05:57 +0000 (20:05 +0000)
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.

(cherry picked from commit b3a2444ba57c90b93b5f76cc7f62b84acb7adec8)
(cherry picked from commit 35e92d9de27cf6f30be5f64caf6c59c63e0ad19b)
(cherry picked from commit c9504fbc7dbce7ac3968bac8526b81efc266a0bb)

src/shared/bootspec.c
src/shared/pe-binary.c

index 52d46fa93b61b5735e8198c415e6d9baf0c76078..d009618997cf4891a0949291fabf7cdb54d9d0a0 100644 (file)
@@ -999,7 +999,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_data= */ NULL);
index 0e15846e8abc69387ae783c4b786279f2831ae00..46a61715320e9fa1c63ff6714d444dd5a0cc904f 100644 (file)
@@ -334,7 +334,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));
 }
 #endif
 
@@ -383,7 +383,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)
@@ -391,7 +391,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)
@@ -399,7 +399,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);
@@ -410,19 +410,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;
 
@@ -564,13 +564,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);