linker_sanity_check_elf_symtab() only validates a symbol's st_shndx against the section count when it is below SHN_LORESERVE: if (sym->st_shndx < SHN_LORESERVE && sym->st_shndx >= obj->sec_cnt) return -EINVAL; For a STT_SECTION symbol the following check only rejects a non-zero st_value, so a section symbol carrying a reserved index such as SHN_ABS (0xfff1) with st_value == 0 passes validation. When a relocation references such a symbol, linker_append_elf_relos() indexes the per-object section array with no bound check: if (ELF64_ST_TYPE(src_sym->st_info) == STT_SECTION) { struct src_sec *sec = &obj->secs[src_sym->st_shndx]; ... insn->imm += sec->dst_off; obj->secs holds only obj->sec_cnt entries, so obj->secs[0xfff1] dereferences memory tens of thousands of entries past the allocation (reading sec->dst_off) when linking a crafted relocatable object, an out-of-bounds read that faults or folds unrelated heap contents into the patched instruction. A STT_SECTION symbol must reference a real section, so reject one whose st_shndx is not a valid section index. Reserved indices are always >= SHN_LORESERVE, which exceeds sec_cnt, and the in-range case is already handled above, so a single sec_cnt bound closes the gap without affecting valid inputs. Signed-off-by: Naveed Khan --- diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c index 78f92c3929..8a93faa41d 100644 --- a/tools/lib/bpf/linker.c +++ b/tools/lib/bpf/linker.c @@ -973,7 +973,7 @@ static int linker_sanity_check_elf_symtab(struct src_obj *obj, struct src_sec *s return -EINVAL; } if (sym_type == STT_SECTION) { - if (sym->st_value != 0) + if (sym->st_value != 0 || sym->st_shndx >= obj->sec_cnt) return -EINVAL; continue; } -- 2.52.0