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

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
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -141,14 +141,15 @@ static int elf_sym_iter_new(struct elf_sym_iter *iter,
	iter->versyms = elf_getdata(scn, 0);

	scn = elf_find_next_scn_by_type(elf, SHT_GNU_verdef, NULL);
	if (!scn) {
		pr_debug("elf: failed to find verdef ELF sections in '%s'\n", binary_path);
		return -ENOENT;
	}
	if (!gelf_getshdr(scn, &sh))
	if (!scn)
		return 0;

	iter->verdefs = elf_getdata(scn, 0);
	if (!iter->verdefs || !gelf_getshdr(scn, &sh)) {
		pr_warn("elf: failed to get verdef ELF section in '%s'\n", binary_path);
		return -EINVAL;
	}
	iter->verdef_strtabidx = sh.sh_link;
	iter->verdefs = elf_getdata(scn, 0);

	return 0;
}
@@ -199,6 +200,9 @@ static const char *elf_get_vername(struct elf_sym_iter *iter, int ver)
	GElf_Verdef verdef;
	int offset;

	if (!iter->verdefs)
		return NULL;

	offset = 0;
	while (gelf_getverdef(iter->verdefs, offset, &verdef)) {
		if (verdef.vd_ndx != ver) {