|
12 | 12 | FileHeader32, FileHeader64, ET_DYN, ET_EXEC, SHN_UNDEF, STB_GLOBAL, STB_WEAK, STV_DEFAULT,
|
13 | 13 | STV_HIDDEN,
|
14 | 14 | },
|
15 |
| - macho::{MachHeader32, MachHeader64, MH_OBJECT, MH_TWOLEVEL}, |
| 15 | + macho::{LC_CODE_SIGNATURE, MH_OBJECT, MH_TWOLEVEL, MachHeader32, MachHeader64}, |
16 | 16 | read::{
|
17 | 17 | elf::{Dyn, FileHeader, SectionHeader, Sym},
|
18 | 18 | macho::{LoadCommandVariant, MachHeader, Nlist},
|
@@ -1264,6 +1264,8 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
|
1264 | 1264 | let mut undefined_symbols = vec![];
|
1265 | 1265 | let mut target_version = None;
|
1266 | 1266 | let mut sdk_version = None;
|
| 1267 | + let mut has_code_signature = false; |
| 1268 | + let mut lowest_file_offset = u64::MAX; |
1267 | 1269 |
|
1268 | 1270 | while let Some(load_command) = load_commands.next()? {
|
1269 | 1271 | match load_command.variant()? {
|
@@ -1386,10 +1388,30 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
|
1386 | 1388 | }
|
1387 | 1389 | }
|
1388 | 1390 | }
|
| 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 | + } |
1389 | 1400 | _ => {}
|
1390 | 1401 | }
|
1391 | 1402 | }
|
1392 | 1403 |
|
| 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 | + |
1393 | 1415 | if let Some(actual_target_version) = target_version {
|
1394 | 1416 | if actual_target_version != advertised_target_version {
|
1395 | 1417 | context.errors.push(format!(
|
|
0 commit comments