libbpf: Fix CO-RE relocs against .text section
authorAndrii Nakryiko <andriin@fb.com>
Fri, 19 Jun 2020 23:04:22 +0000 (16:04 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 24 Jun 2020 00:01:43 +0000 (17:01 -0700)
bpf_object__find_program_by_title(), used by CO-RE relocation code, doesn't
return .text "BPF program", if it is a function storage for sub-programs.
Because of that, any CO-RE relocation in helper non-inlined functions will
fail. Fix this by searching for .text-corresponding BPF program manually.

Adjust one of bpf_iter selftest to exhibit this pattern.

Fixes: ddc7c3042614 ("libbpf: implement BPF CO-RE offset relocation algorithm")
Reported-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20200619230423.691274-1-andriin@fb.com
tools/lib/bpf/libbpf.c
tools/testing/selftests/bpf/progs/bpf_iter_netlink.c

index 477c679..f17151d 100644 (file)
@@ -4818,7 +4818,13 @@ bpf_core_reloc_fields(struct bpf_object *obj, const char *targ_btf_path)
                        err = -EINVAL;
                        goto out;
                }
-               prog = bpf_object__find_program_by_title(obj, sec_name);
+               prog = NULL;
+               for (i = 0; i < obj->nr_programs; i++) {
+                       if (!strcmp(obj->programs[i].section_name, sec_name)) {
+                               prog = &obj->programs[i];
+                               break;
+                       }
+               }
                if (!prog) {
                        pr_warn("failed to find program '%s' for CO-RE offset relocation\n",
                                sec_name);
index e7b8753..75ecf95 100644 (file)
@@ -25,7 +25,7 @@ struct bpf_iter__netlink {
        struct netlink_sock *sk;
 } __attribute__((preserve_access_index));
 
-static inline struct inode *SOCK_INODE(struct socket *socket)
+static __attribute__((noinline)) struct inode *SOCK_INODE(struct socket *socket)
 {
        return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
 }