]> www.infradead.org Git - users/willy/xarray.git/commitdiff
libbpf: Don't assume SHT_GNU_verdef presence for SHT_GNU_versym section
authorAndrii Nakryiko <andrii@kernel.org>
Mon, 16 Oct 2023 18:28:40 +0000 (11:28 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Tue, 17 Oct 2023 09:43:20 +0000 (11:43 +0200)
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: bb7fa09399b9 ("libbpf: Support symbol versioning for uprobe")
Reported-by: Liam Wisehart <liamwisehart@meta.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Tested-by: Manu Bretelle <chantr4@gmail.com>
Reviewed-by: Fangrui Song <maskray@google.com>
Acked-by: Hengqi Chen <hengqi.chen@gmail.com>
Link: https://lore.kernel.org/bpf/20231016182840.4033346-1-andrii@kernel.org
tools/lib/bpf/elf.c

index 2a158e8a8b7c593107709f431d757da7448f00dc..2a62bf411bb3e80f7dea9740d14a0a188ec6e73d 100644 (file)
@@ -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) {