]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bpf: jmp_offset() and verbose_insn() utility functions
authorEduard Zingerman <eddyz87@gmail.com>
Tue, 4 Mar 2025 19:50:20 +0000 (11:50 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 15 Mar 2025 18:48:29 +0000 (11:48 -0700)
Extract two utility functions:
- One BPF jump instruction uses .imm field to encode jump offset,
  while the rest use .off. Encapsulate this detail as jmp_offset()
  function.
- Avoid duplicating instruction printing callback definitions by
  defining a verbose_insn() function, which disassembles an
  instruction into the verifier log while hiding this detail.

These functions will be used in the next patch.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20250304195024.2478889-2-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index b6664d0f6914ce3ae99aa43115e9564a78b2cab8..25910b740bbcbc090a2af0b83f1e12bbe7781e74 100644 (file)
@@ -3360,6 +3360,15 @@ static int add_subprog_and_kfunc(struct bpf_verifier_env *env)
        return 0;
 }
 
+static int jmp_offset(struct bpf_insn *insn)
+{
+       u8 code = insn->code;
+
+       if (code == (BPF_JMP32 | BPF_JA))
+               return insn->imm;
+       return insn->off;
+}
+
 static int check_subprogs(struct bpf_verifier_env *env)
 {
        int i, subprog_start, subprog_end, off, cur_subprog = 0;
@@ -3386,10 +3395,7 @@ static int check_subprogs(struct bpf_verifier_env *env)
                        goto next;
                if (BPF_OP(code) == BPF_EXIT || BPF_OP(code) == BPF_CALL)
                        goto next;
-               if (code == (BPF_JMP32 | BPF_JA))
-                       off = i + insn[i].imm + 1;
-               else
-                       off = i + insn[i].off + 1;
+               off = i + jmp_offset(&insn[i]) + 1;
                if (off < subprog_start || off >= subprog_end) {
                        verbose(env, "jump out of range from insn %d to %d\n", i, off);
                        return -EINVAL;
@@ -3919,6 +3925,17 @@ static const char *disasm_kfunc_name(void *data, const struct bpf_insn *insn)
        return btf_name_by_offset(desc_btf, func->name_off);
 }
 
+static void verbose_insn(struct bpf_verifier_env *env, struct bpf_insn *insn)
+{
+       const struct bpf_insn_cbs cbs = {
+               .cb_call        = disasm_kfunc_name,
+               .cb_print       = verbose,
+               .private_data   = env,
+       };
+
+       print_bpf_insn(&cbs, insn, env->allow_ptr_leaks);
+}
+
 static inline void bt_init(struct backtrack_state *bt, u32 frame)
 {
        bt->frame = frame;
@@ -4119,11 +4136,6 @@ static bool calls_callback(struct bpf_verifier_env *env, int insn_idx);
 static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
                          struct bpf_insn_hist_entry *hist, struct backtrack_state *bt)
 {
-       const struct bpf_insn_cbs cbs = {
-               .cb_call        = disasm_kfunc_name,
-               .cb_print       = verbose,
-               .private_data   = env,
-       };
        struct bpf_insn *insn = env->prog->insnsi + idx;
        u8 class = BPF_CLASS(insn->code);
        u8 opcode = BPF_OP(insn->code);
@@ -4141,7 +4153,7 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
                fmt_stack_mask(env->tmp_str_buf, TMP_STR_BUF_LEN, bt_stack_mask(bt));
                verbose(env, "stack=%s before ", env->tmp_str_buf);
                verbose(env, "%d: ", idx);
-               print_bpf_insn(&cbs, insn, env->allow_ptr_leaks);
+               verbose_insn(env, insn);
        }
 
        /* If there is a history record that some registers gained range at this insn,
@@ -19273,19 +19285,13 @@ static int do_check(struct bpf_verifier_env *env)
                }
 
                if (env->log.level & BPF_LOG_LEVEL) {
-                       const struct bpf_insn_cbs cbs = {
-                               .cb_call        = disasm_kfunc_name,
-                               .cb_print       = verbose,
-                               .private_data   = env,
-                       };
-
                        if (verifier_state_scratched(env))
                                print_insn_state(env, state, state->curframe);
 
                        verbose_linfo(env, env->insn_idx, "; ");
                        env->prev_log_pos = env->log.end_pos;
                        verbose(env, "%d: ", env->insn_idx);
-                       print_bpf_insn(&cbs, insn, env->allow_ptr_leaks);
+                       verbose_insn(env, insn);
                        env->prev_insn_print_pos = env->log.end_pos - env->prev_log_pos;
                        env->prev_log_pos = env->log.end_pos;
                }