Skip to content

Commit f2e48e1

Browse files
committed
Add test for sufficient headerpad
1 parent 4ec8e29 commit f2e48e1

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

src/validation.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use {
1212
FileHeader32, FileHeader64, ET_DYN, ET_EXEC, SHN_UNDEF, STB_GLOBAL, STB_WEAK, STV_DEFAULT,
1313
STV_HIDDEN,
1414
},
15-
macho::{MachHeader32, MachHeader64, MH_OBJECT, MH_TWOLEVEL},
15+
macho::{LC_CODE_SIGNATURE, MH_OBJECT, MH_TWOLEVEL, MachHeader32, MachHeader64},
1616
read::{
1717
elf::{Dyn, FileHeader, SectionHeader, Sym},
1818
macho::{LoadCommandVariant, MachHeader, Nlist},
@@ -1264,6 +1264,8 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
12641264
let mut undefined_symbols = vec![];
12651265
let mut target_version = None;
12661266
let mut sdk_version = None;
1267+
let mut has_code_signature = false;
1268+
let mut lowest_file_offset = u64::MAX;
12671269

12681270
while let Some(load_command) = load_commands.next()? {
12691271
match load_command.variant()? {
@@ -1386,10 +1388,30 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
13861388
}
13871389
}
13881390
}
1391+
LoadCommandVariant::Segment32(segment, _) => {
1392+
lowest_file_offset = lowest_file_offset.min(segment.fileoff.get(endian).into());
1393+
}
1394+
LoadCommandVariant::Segment64(segment, _) => {
1395+
lowest_file_offset = lowest_file_offset.min(segment.fileoff.get(endian).into());
1396+
}
1397+
LoadCommandVariant::LinkeditData(c) if c.cmd.get(endian) == LC_CODE_SIGNATURE => {
1398+
has_code_signature = true;
1399+
}
13891400
_ => {}
13901401
}
13911402
}
13921403

1404+
let end_of_load_commands =
1405+
std::mem::size_of_val(header) as u64 + header.sizeofcmds(endian) as u64;
1406+
if header.filetype(endian) != MH_OBJECT
1407+
&& end_of_load_commands + if has_code_signature { 0 } else { 16 } > lowest_file_offset
1408+
{
1409+
context.errors.push(format!(
1410+
"{}: Insufficient headerpad between end of load commands {end_of_load_commands:#x} and beginning of code {lowest_file_offset:#x}",
1411+
path.display(),
1412+
));
1413+
}
1414+
13931415
if let Some(actual_target_version) = target_version {
13941416
if actual_target_version != advertised_target_version {
13951417
context.errors.push(format!(

0 commit comments

Comments
 (0)