Skip to content

Commit efb67dd

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

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

src/validation.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ 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},
18-
macho::{LoadCommandVariant, MachHeader, Nlist},
18+
macho::{LoadCommandVariant, MachHeader, Nlist, Section, Segment},
1919
pe::{ImageNtHeaders, PeFile, PeFile32, PeFile64},
2020
},
2121
Architecture, Endianness, FileKind, Object, SectionIndex, SymbolScope,
@@ -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,34 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
13861388
}
13871389
}
13881390
}
1391+
LoadCommandVariant::Segment32(segment, segment_data) => {
1392+
for section in segment.sections(endian, segment_data)? {
1393+
lowest_file_offset = lowest_file_offset.min(section.offset(endian).into());
1394+
}
1395+
}
1396+
LoadCommandVariant::Segment64(segment, segment_data) => {
1397+
for section in segment.sections(endian, segment_data)? {
1398+
lowest_file_offset = lowest_file_offset.min(section.offset(endian).into());
1399+
}
1400+
}
1401+
LoadCommandVariant::LinkeditData(c) if c.cmd.get(endian) == LC_CODE_SIGNATURE => {
1402+
has_code_signature = true;
1403+
}
13891404
_ => {}
13901405
}
13911406
}
13921407

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

0 commit comments

Comments
 (0)