Skip to content

Commit d9691ed

Browse files
authored
Remove holes in ELF files (#213)
* Remove holes in elf files These holes cause issues when signing/hashing/encrypting, as the data in the hole can be different depending on the load method used (00s or FFs) This will only effect ELF files which are written out afterwards, so the `seal`, `encrypt`, and `partition create` commands * Revert "Add support for encrypting elfs with section holes within segments (#150)" This is no longer required now picotool plugs the holes, and just adds extra complexity This reverts commit b62ead3.
1 parent 3ad3a38 commit d9691ed

2 files changed

Lines changed: 27 additions & 27 deletions

File tree

elf/elf_file.cpp

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -230,15 +230,6 @@ void elf_file::flatten(void) {
230230
}
231231
idx++;
232232
}
233-
234-
idx = 0;
235-
for (const auto &ph : ph_entries) {
236-
if (ph.filez) {
237-
elf_bytes.resize(std::max(ph.offset + ph.filez, (uint32_t)elf_bytes.size()));
238-
memcpy(&elf_bytes[ph.offset], &ph_data[idx][0], ph.filez);
239-
}
240-
idx++;
241-
}
242233
if (verbose) printf("Elf file size %zu\n", elf_bytes.size());
243234
}
244235

@@ -260,6 +251,29 @@ void elf_file::read_sh(void) {
260251
}
261252
}
262253

254+
// If there are holes between sections within segments, increase the section size to plug the hole
255+
// This is necessary to ensure the whole segment contains data defined in sections, otherwise you end up
256+
// signing/hashing/encrypting data that may not be written, as many tools write in sections not segments
257+
void elf_file::remove_sh_holes(void) {
258+
for (int i=0; i+1 < sh_entries.size(); i++) {
259+
auto sh0 = &(sh_entries[i]);
260+
elf32_sh_entry sh1 = sh_entries[i+1];
261+
if (
262+
(sh0->type == SHT_PROGBITS && sh1.type == SHT_PROGBITS)
263+
&& (sh0->size && sh1.size)
264+
&& (sh0->addr + sh0->size < sh1.addr)
265+
&& (segment_from_virtual_address(sh0->addr) == segment_from_virtual_address(sh1.addr))
266+
) {
267+
uint32_t gap = sh1.addr - sh0->addr - sh0->size;
268+
if (gap > sh1.addralign) {
269+
fail(ERROR_INCOMPATIBLE, "Cannot plug gap greater than alignment - gap %d, alignment %d", gap, sh1.addralign);
270+
}
271+
if (verbose) printf("Section %d: Moving end from 0x%08x to 0x%08x to plug gap\n", i, sh0->addr + sh0->size, sh1.addr);
272+
sh0->size = sh1.addr - sh0->addr;
273+
}
274+
}
275+
}
276+
263277
// Read the section data from the internal byte array into discrete sections.
264278
// This is used after modifying segments but before inserting new segments
265279
void elf_file::read_sh_data(void) {
@@ -274,18 +288,6 @@ void elf_file::read_sh_data(void) {
274288
}
275289
}
276290

277-
void elf_file::read_ph_data(void) {
278-
int ph_idx = 0;
279-
ph_data.resize(eh.ph_num);
280-
for (const auto &ph: ph_entries) {
281-
if (ph.filez) {
282-
ph_data[ph_idx].resize(ph.filez);
283-
read_bytes(ph.offset, ph.filez, &ph_data[ph_idx][0]);
284-
}
285-
ph_idx++;
286-
}
287-
}
288-
289291
const std::string elf_file::section_name(uint32_t sh_name) const {
290292
if (!eh.sh_str_index || eh.sh_str_index > eh.sh_num)
291293
return "";
@@ -391,9 +393,11 @@ int elf_file::read_file(std::shared_ptr<std::iostream> file) {
391393
if (!rc) {
392394
read_ph();
393395
read_sh();
396+
397+
// Remove any holes in the ELF file, as these cause issues when signing/hashing/encrypting
398+
remove_sh_holes();
394399
}
395400
read_sh_data();
396-
read_ph_data();
397401
}
398402
catch (const std::ios_base::failure &e) {
399403
std::cerr << "Failed to read elf file" << std::endl;
@@ -440,7 +444,6 @@ void elf_file::content(const elf32_ph_entry &ph, const std::vector<uint8_t> &con
440444
if (verbose) printf("Update segment content offset %x content size %zx physical size %x\n", ph.offset, content.size(), ph.filez);
441445
memcpy(&elf_bytes[ph.offset], &content[0], std::min(content.size(), (size_t) ph.filez));
442446
read_sh_data(); // Extract the sections after modifying the content
443-
read_ph_data();
444447
}
445448

446449
void elf_file::content(const elf32_sh_entry &sh, const std::vector<uint8_t> &content) {
@@ -449,7 +452,6 @@ void elf_file::content(const elf32_sh_entry &sh, const std::vector<uint8_t> &con
449452
if (verbose) printf("Update section content offset %x content size %zx section size %x\n", sh.offset, content.size(), sh.size);
450453
memcpy(&elf_bytes[sh.offset], &content[0], std::min(content.size(), (size_t) sh.size));
451454
read_sh_data(); // Extract the sections after modifying the content
452-
read_ph_data();
453455
}
454456

455457
const elf32_ph_entry* elf_file::segment_from_physical_address(uint32_t paddr) {
@@ -527,7 +529,6 @@ const elf32_ph_entry& elf_file::append_segment(uint32_t vaddr, uint32_t paddr, u
527529
sh_entries.push_back(sh);
528530
sh_data.push_back(std::vector<uint8_t>(size));
529531
ph_entries.back().offset = sh.offset;
530-
ph_data.push_back(std::vector<uint8_t>(size));
531532

532533
eh.sh_offset = sh.offset + sh.size;
533534
eh.sh_num++;

elf/elf_file.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ class elf_file {
5454
int read_header(void);
5555
void read_ph(void);
5656
void read_sh(void);
57+
void remove_sh_holes(void);
5758
void read_sh_data(void);
58-
void read_ph_data(void);
5959
void read_bytes(unsigned offset, unsigned length, void *dest);
6060
uint32_t append_section_name(const std::string &sh_name_str);
6161
void flatten(void);
@@ -66,7 +66,6 @@ class elf_file {
6666
std::vector<elf32_ph_entry> ph_entries;
6767
std::vector<elf32_sh_entry> sh_entries;
6868
std::vector<std::vector<uint8_t>> sh_data;
69-
std::vector<std::vector<uint8_t>> ph_data;
7069
bool verbose;
7170
};
7271
int rp_check_elf_header(const elf32_header &eh);

0 commit comments

Comments
 (0)