[PATCH bpf 1/2] libbpf: Reject out-of-range linker relocation offsets

From: HyeongJun An

Date: Sun Jun 14 2026 - 01:40:02 EST


The static linker sanity-checks relocation sections before appending them,
but for executable target sections it only verifies that r_offset is
BPF-instruction aligned. It does not verify that the offset is inside the
relocated section.

A malformed object can therefore pass an out-of-range offset through
linker_sanity_check_elf_relos(). When the relocation is against an
STT_SECTION symbol, linker_append_elf_relos() uses the unchecked offset to
find the instruction to adjust:

insn = dst_linked_sec->raw_data + dst_rel->r_offset;

and then reads insn->code and updates insn->imm.

This is reproducible with bpftool's static linker by crafting a BPF object
with a 16-byte executable section and a relocation in its .rel section
whose r_offset is 0x1000:

BUG: AddressSanitizer: heap-buffer-overflow in linker_append_elf_relos
READ of size 1
linker_append_elf_relos
bpf_linker_add_file
bpf_linker__add_file
do_object

Reject relocation offsets that are outside the relocated section before any
later use. This mirrors the normal object loading path, which already
rejects executable relocations whose r_offset is not inside the program
section.

Fixes: faf6ed321cf6 ("libbpf: Add BPF static linker APIs")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Codex:gpt-5
Signed-off-by: HyeongJun An <sammiee5311@xxxxxxxxx>
---
tools/lib/bpf/linker.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c
index 78f92c39290a..3eb23da167d2 100644
--- a/tools/lib/bpf/linker.c
+++ b/tools/lib/bpf/linker.c
@@ -1048,6 +1048,12 @@ static int linker_sanity_check_elf_relos(struct src_obj *obj, struct src_sec *se
return -EINVAL;
}

+ if (relo->r_offset >= link_sec->shdr->sh_size) {
+ pr_warn("ELF relo #%d in section #%zu has invalid offset %zu in %s\n",
+ i, sec->sec_idx, (size_t)relo->r_offset, obj->filename);
+ return -EINVAL;
+ }
+
if (link_sec->shdr->sh_flags & SHF_EXECINSTR) {
if (relo->r_offset % sizeof(struct bpf_insn) != 0) {
pr_warn("ELF relo #%d in section #%zu points to missing symbol #%zu in %s\n",
--
2.43.0