Skip to content

Commit 0f40b54

Browse files
fix(profiling): mask local/abs symbol flags and bounds check Mach-O tables
1 parent 83fa763 commit 0f40b54

1 file changed

Lines changed: 33 additions & 11 deletions

File tree

profiling/src/io/got_macho.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,9 @@ unsafe fn rebind_symbols_for_image(
327327
// file. At runtime, __LINKEDIT is mapped at (vmaddr + slide). By subtracting
328328
// the file offset of __LINKEDIT itself, we get a base we can add any file
329329
// offset to in order to get a valid runtime pointer.
330-
linkedit_base =
331-
(slide as usize).wrapping_add(seg.vmaddr as usize) - seg.fileoff as usize;
330+
linkedit_base = (slide as usize)
331+
.wrapping_add(seg.vmaddr as usize)
332+
.wrapping_sub(seg.fileoff as usize);
332333
linkedit_found = true;
333334
}
334335
}
@@ -390,7 +391,10 @@ unsafe fn rebind_symbols_for_image(
390391
slide,
391392
symtab,
392393
strtab,
394+
(*symtab_cmd).nsyms as usize,
395+
(*symtab_cmd).strsize as usize,
393396
indirect_symtab,
397+
(*dysymtab_cmd).nindirectsyms as usize,
394398
overwrites,
395399
segname == "__DATA_CONST",
396400
) {
@@ -422,7 +426,10 @@ unsafe fn rebind_symbols_in_section(
422426
slide: isize,
423427
symtab: *const Nlist64,
424428
strtab: *const c_char,
429+
nsyms: usize,
430+
strsize: usize,
425431
indirect_symtab: *const u32,
432+
nindirectsyms: usize,
426433
overwrites: &mut [GotSymbolOverwrite],
427434
is_data_const: bool,
428435
) -> bool {
@@ -432,7 +439,14 @@ unsafe fn rebind_symbols_in_section(
432439

433440
// The indirect symbol table entries for this section start at index `section.reserved1`.
434441
// Entry `indirect_sym_indices[i]` tells us which symbol table entry corresponds to slot `i`.
435-
let indirect_sym_indices = indirect_symtab.add(section.reserved1 as usize);
442+
let indirect_sym_start = section.reserved1 as usize;
443+
let Some(indirect_sym_end) = indirect_sym_start.checked_add(num_indirect_syms) else {
444+
return false;
445+
};
446+
if indirect_sym_end > nindirectsyms {
447+
return false;
448+
}
449+
let indirect_sym_indices = indirect_symtab.add(indirect_sym_start);
436450

437451
// The actual pointer slots in memory (adjusted by ASLR slide).
438452
let symbol_ptrs = ((slide as usize).wrapping_add(section.addr as usize)) as *mut *mut c_void;
@@ -445,19 +459,27 @@ unsafe fn rebind_symbols_in_section(
445459
let symtab_index = *indirect_sym_indices.add(i);
446460

447461
// Skip special entries that don't refer to real external symbols
448-
if symtab_index == INDIRECT_SYMBOL_LOCAL
449-
|| symtab_index == INDIRECT_SYMBOL_ABS
450-
|| symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)
451-
{
462+
if (symtab_index & (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) != 0 {
463+
continue;
464+
}
465+
466+
if symtab_index as usize >= nsyms {
452467
continue;
453468
}
454469

455470
// Step 2: Look up the symbol in the symbol table to get its name
456471
let nlist = &*symtab.add(symtab_index as usize);
457-
let name_ptr = strtab.add(nlist.n_strx as usize);
458-
let name = match CStr::from_ptr(name_ptr).to_str() {
459-
Ok(n) => n,
460-
Err(_) => continue,
472+
let name_offset = nlist.n_strx as usize;
473+
if name_offset >= strsize {
474+
continue;
475+
}
476+
let name_bytes =
477+
std::slice::from_raw_parts(strtab.add(name_offset) as *const u8, strsize - name_offset);
478+
let Ok(name) = CStr::from_bytes_until_nul(name_bytes) else {
479+
continue;
480+
};
481+
let Ok(name) = name.to_str() else {
482+
continue;
461483
};
462484

463485
// Step 3: Strip the Mach-O leading underscore (e.g. "_recv" → "recv") so we can

0 commit comments

Comments
 (0)