Doesn't work on /bin/busybox
danielzgtg opened this issue · comments
bingrep
errors out on /bin/busybox
with the following message:
$ cargo run --release /bin/busybox
Finished release [optimized] target(s) in 0.02s
Running `target/release/bingrep /bin/busybox`
Malformed entity: Section 63 size (4195032) + addr (1008) is out of bounds. Overflowed: false
Environment
Built at c3516e7.
readelf /bin/busybox
works fine.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.1 LTS
Release: 20.04
Codename: focal
$ dpkg -S /bin/busybox
busybox-static: /bin/busybox
$ dpkg -s busybox-static
[...]
Version: 1:1.30.1-4ubuntu6.3
[...]
$ sha256sum /bin/busybox
6278d294297c0eb6224e4674da95a180d6c1805f17e640d0977f68553033bddb /bin/busybox
thanks for the issue! it looks like 6495cfee9ce7219e4fe1dde5953a2c73b01a8382 in goblin (m4b/goblin#243) introduced this issue.
something like this should fix it:
- section.check_size(bytes.len())?;
- let sh_relocs = RelocSection::parse(bytes, section.sh_offset as usize, section.sh_size as usize, is_rela, ctx)?;
- shdr_relocs.push((idx, sh_relocs));
+ match section.check_size(bytes.len()) {
+ Ok(_) => {
+ let sh_relocs = RelocSection::parse(
+ bytes,
+ section.sh_offset as usize,
+ section.sh_size as usize,
+ is_rela,
+ ctx,
+ )?;
+ shdr_relocs.push((idx, sh_relocs));
+ }
+ Err(e) => log::warn!(
+ "Dropping shdr relocs for section #{} size for {:?}: {}",
+ idx,
+ shdr_strtab
+ .get(section.sh_name)
+ .unwrap_or(Ok("BAD_SECTION_NAME"))?,
+ e
+ ),
+ }
though it still has a regression compared to 0.2.0 that can succesfully parse out some of the shdr relocs
@m4b your patch would suppress the error but also prevent parsing the relocation entry. I believe, that the section size check is wrong for relocation entries. m4b/goblin#243 added effectively checks for sh_addr + sh_size <= file_size
:
let (end, overflow) = self.sh_addr.overflowing_add(self.sh_size);
if overflow || end > size as u64 {
I believe that comparing the virtual memory range with the physical file size is not valid in this context, and the correct patch would be:
diff --git a/src/elf/section_header.rs b/src/elf/section_header.rs
index 308606b..22cfdf2 100644
--- a/src/elf/section_header.rs
+++ b/src/elf/section_header.rs
@@ -474,7 +474,7 @@ if_alloc! {
return Err(error::Error::Malformed(message));
}
let (end, overflow) = self.sh_addr.overflowing_add(self.sh_size);
- if overflow || end > size as u64 {
+ if overflow {
let message = format!("Section {} size ({}) + addr ({}) is out of bounds. Overflowed: {}",
self.sh_name, self.sh_addr, self.sh_size, overflow);
return Err(error::Error::Malformed(message));
Confirmed your patch fixes, and latest goblin is released, and bingrep updated to use it with lockfile; also tagged new release :) thanks for everyone's help and involvement here, including the bug report! :D