libbpf: Fix ld_imm64 copy logic for ksym in light skeleton.
authorAlexei Starovoitov <ast@kernel.org>
Sun, 19 Mar 2023 20:30:13 +0000 (13:30 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 May 2023 14:03:18 +0000 (23:03 +0900)
[ Upstream commit a506d6ce1dd184051037dc9d26c3eb187c9fe625 ]

Unlike normal libbpf the light skeleton 'loader' program is doing
btf_find_by_name_kind() call at run-time to find ksym in the kernel and
populate its {btf_id, btf_obj_fd} pair in ld_imm64 insn. To avoid doing the
search multiple times for the same ksym it remembers the first patched ld_imm64
insn and copies {btf_id, btf_obj_fd} from it into subsequent ld_imm64 insn.
Fix a bug in copying logic, since it may incorrectly clear BPF_PSEUDO_BTF_ID flag.

Also replace always true if (btf_obj_fd >= 0) check with unconditional JMP_JA
to clarify the code.

Fixes: d995816b77eb ("libbpf: Avoid reload of imm for weak, unresolved, repeating ksym")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20230319203014.55866-1-alexei.starovoitov@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
tools/lib/bpf/gen_loader.c

index 23f5c46..b74c82b 100644 (file)
@@ -804,11 +804,13 @@ static void emit_relo_ksym_btf(struct bpf_gen *gen, struct ksym_relo_desc *relo,
                return;
        /* try to copy from existing ldimm64 insn */
        if (kdesc->ref > 1) {
-               move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
-                              kdesc->insn + offsetof(struct bpf_insn, imm));
                move_blob2blob(gen, insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm), 4,
                               kdesc->insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm));
-               /* jump over src_reg adjustment if imm is not 0, reuse BPF_REG_0 from move_blob2blob */
+               move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
+                              kdesc->insn + offsetof(struct bpf_insn, imm));
+               /* jump over src_reg adjustment if imm (btf_id) is not 0, reuse BPF_REG_0 from move_blob2blob
+                * If btf_id is zero, clear BPF_PSEUDO_BTF_ID flag in src_reg of ld_imm64 insn
+                */
                emit(gen, BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3));
                goto clear_src_reg;
        }
@@ -831,7 +833,7 @@ static void emit_relo_ksym_btf(struct bpf_gen *gen, struct ksym_relo_desc *relo,
        emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_7,
                              sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm)));
        /* skip src_reg adjustment */
-       emit(gen, BPF_JMP_IMM(BPF_JSGE, BPF_REG_7, 0, 3));
+       emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, 3));
 clear_src_reg:
        /* clear bpf_object__relocate_data's src_reg assignment, otherwise we get a verifier failure */
        reg_mask = src_reg_mask();