Commit 137df118 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Daniel Borkmann

libbpf: Don't assume SHT_GNU_verdef presence for SHT_GNU_versym section

Fix too eager assumption that SHT_GNU_verdef ELF section is going to be
present whenever binary has SHT_GNU_versym section. It seems like either
SHT_GNU_verdef or SHT_GNU_verneed can be used, so failing on missing
SHT_GNU_verdef actually breaks use cases in production.

One specific reported issue, which was used to manually test this fix,
was trying to attach to `readline` function in BASH binary.

Fixes: bb7fa093 ("libbpf: Support symbol versioning for uprobe")
Reported-by: default avatarLiam Wisehart <liamwisehart@meta.com>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Tested-by: default avatarManu Bretelle <chantr4@gmail.com>
Reviewed-by: default avatarFangrui Song <maskray@google.com>
Acked-by: default avatarHengqi Chen <hengqi.chen@gmail.com>
Link: https://lore.kernel.org/bpf/20231016182840.4033346-1-andrii@kernel.org
parent a3c2dd96
...@@ -141,14 +141,15 @@ static int elf_sym_iter_new(struct elf_sym_iter *iter, ...@@ -141,14 +141,15 @@ static int elf_sym_iter_new(struct elf_sym_iter *iter,
iter->versyms = elf_getdata(scn, 0); iter->versyms = elf_getdata(scn, 0);
scn = elf_find_next_scn_by_type(elf, SHT_GNU_verdef, NULL); scn = elf_find_next_scn_by_type(elf, SHT_GNU_verdef, NULL);
if (!scn) { if (!scn)
pr_debug("elf: failed to find verdef ELF sections in '%s'\n", binary_path); return 0;
return -ENOENT;
} iter->verdefs = elf_getdata(scn, 0);
if (!gelf_getshdr(scn, &sh)) if (!iter->verdefs || !gelf_getshdr(scn, &sh)) {
pr_warn("elf: failed to get verdef ELF section in '%s'\n", binary_path);
return -EINVAL; return -EINVAL;
}
iter->verdef_strtabidx = sh.sh_link; iter->verdef_strtabidx = sh.sh_link;
iter->verdefs = elf_getdata(scn, 0);
return 0; return 0;
} }
...@@ -199,6 +200,9 @@ static const char *elf_get_vername(struct elf_sym_iter *iter, int ver) ...@@ -199,6 +200,9 @@ static const char *elf_get_vername(struct elf_sym_iter *iter, int ver)
GElf_Verdef verdef; GElf_Verdef verdef;
int offset; int offset;
if (!iter->verdefs)
return NULL;
offset = 0; offset = 0;
while (gelf_getverdef(iter->verdefs, offset, &verdef)) { while (gelf_getverdef(iter->verdefs, offset, &verdef)) {
if (verdef.vd_ndx != ver) { if (verdef.vd_ndx != ver) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment