]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bpf: Factor out check_atomic_rmw()
authorPeilin Ye <yepeilin@google.com>
Mon, 3 Mar 2025 05:37:19 +0000 (05:37 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 15 Mar 2025 18:48:26 +0000 (11:48 -0700)
Currently, check_atomic() only handles atomic read-modify-write (RMW)
instructions.  Since we are planning to introduce other types of atomic
instructions (i.e., atomic load/store), extract the existing RMW
handling logic into its own function named check_atomic_rmw().

Remove the @insn_idx parameter as it is not really necessary.  Use
'env->insn_idx' instead, as in other places in verifier.c.

Signed-off-by: Peilin Ye <yepeilin@google.com>
Link: https://lore.kernel.org/r/6323ac8e73a10a1c8ee547c77ed68cf8eb6b90e1.1740978603.git.yepeilin@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index 66b19fa4be48992c5052f7b2610608581b1a4af5..e3991ac72029f1e0dd5ffb146a728f459f7e5502 100644 (file)
@@ -7616,28 +7616,12 @@ 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_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_insn *insn)
+static int check_atomic_rmw(struct bpf_verifier_env *env,
+                           struct bpf_insn *insn)
 {
        int load_reg;
        int err;
 
-       switch (insn->imm) {
-       case BPF_ADD:
-       case BPF_ADD | BPF_FETCH:
-       case BPF_AND:
-       case BPF_AND | BPF_FETCH:
-       case BPF_OR:
-       case BPF_OR | BPF_FETCH:
-       case BPF_XOR:
-       case BPF_XOR | BPF_FETCH:
-       case BPF_XCHG:
-       case BPF_CMPXCHG:
-               break;
-       default:
-               verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n", insn->imm);
-               return -EINVAL;
-       }
-
        if (BPF_SIZE(insn->code) != BPF_W && BPF_SIZE(insn->code) != BPF_DW) {
                verbose(env, "invalid atomic operand size\n");
                return -EINVAL;
@@ -7699,12 +7683,12 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
        /* Check whether we can read the memory, with second call for fetch
         * case to simulate the register fill.
         */
-       err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
+       err = check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off,
                               BPF_SIZE(insn->code), BPF_READ, -1, true, false);
        if (!err && load_reg >= 0)
-               err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
-                                      BPF_SIZE(insn->code), BPF_READ, load_reg,
-                                      true, false);
+               err = check_mem_access(env, env->insn_idx, insn->dst_reg,
+                                      insn->off, BPF_SIZE(insn->code),
+                                      BPF_READ, load_reg, true, false);
        if (err)
                return err;
 
@@ -7714,13 +7698,34 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
                        return err;
        }
        /* Check whether we can write into the same memory. */
-       err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
+       err = check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off,
                               BPF_SIZE(insn->code), BPF_WRITE, -1, true, false);
        if (err)
                return err;
        return 0;
 }
 
+static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
+{
+       switch (insn->imm) {
+       case BPF_ADD:
+       case BPF_ADD | BPF_FETCH:
+       case BPF_AND:
+       case BPF_AND | BPF_FETCH:
+       case BPF_OR:
+       case BPF_OR | BPF_FETCH:
+       case BPF_XOR:
+       case BPF_XOR | BPF_FETCH:
+       case BPF_XCHG:
+       case BPF_CMPXCHG:
+               return check_atomic_rmw(env, insn);
+       default:
+               verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n",
+                       insn->imm);
+               return -EINVAL;
+       }
+}
+
 /* When register 'regno' is used to read the stack (either directly or through
  * a helper function) make sure that it's within stack boundary and, depending
  * on the access type and privileges, that all elements of the stack are
@@ -19224,7 +19229,7 @@ static int do_check(struct bpf_verifier_env *env)
                        enum bpf_reg_type dst_reg_type;
 
                        if (BPF_MODE(insn->code) == BPF_ATOMIC) {
-                               err = check_atomic(env, env->insn_idx, insn);
+                               err = check_atomic(env, insn);
                                if (err)
                                        return err;
                                env->insn_idx++;