]> www.infradead.org Git - users/hch/misc.git/commitdiff
bpf: Factor out check_load_mem() and check_store_reg()
authorPeilin Ye <yepeilin@google.com>
Mon, 3 Mar 2025 05:37:25 +0000 (05:37 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 15 Mar 2025 18:48:26 +0000 (11:48 -0700)
Extract BPF_LDX and most non-ATOMIC BPF_STX instruction handling logic
in do_check() into helper functions to be used later.  While we are
here, make that comment about "reserved fields" more specific.

Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Peilin Ye <yepeilin@google.com>
Link: https://lore.kernel.org/r/8b39c94eac2bb7389ff12392ca666f939124ec4f.1740978603.git.yepeilin@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index e3991ac72029f1e0dd5ffb146a728f459f7e5502..22c4edc8695c07a611a22fa42c9175e4d91b2105 100644 (file)
@@ -7616,6 +7616,67 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
 static int save_aux_ptr_type(struct bpf_verifier_env *env, enum bpf_reg_type type,
                             bool allow_trust_mismatch);
 
+static int check_load_mem(struct bpf_verifier_env *env, struct bpf_insn *insn,
+                         bool strict_alignment_once, bool is_ldsx,
+                         bool allow_trust_mismatch, const char *ctx)
+{
+       struct bpf_reg_state *regs = cur_regs(env);
+       enum bpf_reg_type src_reg_type;
+       int err;
+
+       /* check src operand */
+       err = check_reg_arg(env, insn->src_reg, SRC_OP);
+       if (err)
+               return err;
+
+       /* check dst operand */
+       err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
+       if (err)
+               return err;
+
+       src_reg_type = regs[insn->src_reg].type;
+
+       /* Check if (src_reg + off) is readable. The state of dst_reg will be
+        * updated by this call.
+        */
+       err = check_mem_access(env, env->insn_idx, insn->src_reg, insn->off,
+                              BPF_SIZE(insn->code), BPF_READ, insn->dst_reg,
+                              strict_alignment_once, is_ldsx);
+       err = err ?: save_aux_ptr_type(env, src_reg_type,
+                                      allow_trust_mismatch);
+       err = err ?: reg_bounds_sanity_check(env, &regs[insn->dst_reg], ctx);
+
+       return err;
+}
+
+static int check_store_reg(struct bpf_verifier_env *env, struct bpf_insn *insn,
+                          bool strict_alignment_once)
+{
+       struct bpf_reg_state *regs = cur_regs(env);
+       enum bpf_reg_type dst_reg_type;
+       int err;
+
+       /* check src1 operand */
+       err = check_reg_arg(env, insn->src_reg, SRC_OP);
+       if (err)
+               return err;
+
+       /* check src2 operand */
+       err = check_reg_arg(env, insn->dst_reg, SRC_OP);
+       if (err)
+               return err;
+
+       dst_reg_type = regs[insn->dst_reg].type;
+
+       /* Check if (dst_reg + off) is writeable. */
+       err = check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off,
+                              BPF_SIZE(insn->code), BPF_WRITE, insn->src_reg,
+                              strict_alignment_once, false);
+       err = err ?: save_aux_ptr_type(env, dst_reg_type, false);
+
+       return err;
+}
+
 static int check_atomic_rmw(struct bpf_verifier_env *env,
                            struct bpf_insn *insn)
 {
@@ -19199,35 +19260,16 @@ static int do_check(struct bpf_verifier_env *env)
                                return err;
 
                } else if (class == BPF_LDX) {
-                       enum bpf_reg_type src_reg_type;
-
-                       /* check for reserved fields is already done */
-
-                       /* check src operand */
-                       err = check_reg_arg(env, insn->src_reg, SRC_OP);
-                       if (err)
-                               return err;
+                       bool is_ldsx = BPF_MODE(insn->code) == BPF_MEMSX;
 
-                       err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
-                       if (err)
-                               return err;
-
-                       src_reg_type = regs[insn->src_reg].type;
-
-                       /* check that memory (src_reg + off) is readable,
-                        * the state of dst_reg will be updated by this func
+                       /* Check for reserved fields is already done in
+                        * resolve_pseudo_ldimm64().
                         */
-                       err = check_mem_access(env, env->insn_idx, insn->src_reg,
-                                              insn->off, BPF_SIZE(insn->code),
-                                              BPF_READ, insn->dst_reg, false,
-                                              BPF_MODE(insn->code) == BPF_MEMSX);
-                       err = err ?: save_aux_ptr_type(env, src_reg_type, true);
-                       err = err ?: reg_bounds_sanity_check(env, &regs[insn->dst_reg], "ldx");
+                       err = check_load_mem(env, insn, false, is_ldsx, true,
+                                            "ldx");
                        if (err)
                                return err;
                } else if (class == BPF_STX) {
-                       enum bpf_reg_type dst_reg_type;
-
                        if (BPF_MODE(insn->code) == BPF_ATOMIC) {
                                err = check_atomic(env, insn);
                                if (err)
@@ -19241,25 +19283,7 @@ static int do_check(struct bpf_verifier_env *env)
                                return -EINVAL;
                        }
 
-                       /* check src1 operand */
-                       err = check_reg_arg(env, insn->src_reg, SRC_OP);
-                       if (err)
-                               return err;
-                       /* check src2 operand */
-                       err = check_reg_arg(env, insn->dst_reg, SRC_OP);
-                       if (err)
-                               return err;
-
-                       dst_reg_type = regs[insn->dst_reg].type;
-
-                       /* check that memory (dst_reg + off) is writeable */
-                       err = check_mem_access(env, env->insn_idx, insn->dst_reg,
-                                              insn->off, BPF_SIZE(insn->code),
-                                              BPF_WRITE, insn->src_reg, false, false);
-                       if (err)
-                               return err;
-
-                       err = save_aux_ptr_type(env, dst_reg_type, false);
+                       err = check_store_reg(env, insn, false);
                        if (err)
                                return err;
                } else if (class == BPF_ST) {