@@ -7616,28 +7616,12 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
7616
7616
static int save_aux_ptr_type(struct bpf_verifier_env *env, enum bpf_reg_type type,
7617
7617
bool allow_trust_mismatch);
7618
7618
7619
- static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_insn *insn)
7619
+ static int check_atomic_rmw(struct bpf_verifier_env *env,
7620
+ struct bpf_insn *insn)
7620
7621
{
7621
7622
int load_reg;
7622
7623
int err;
7623
7624
7624
- switch (insn->imm) {
7625
- case BPF_ADD:
7626
- case BPF_ADD | BPF_FETCH:
7627
- case BPF_AND:
7628
- case BPF_AND | BPF_FETCH:
7629
- case BPF_OR:
7630
- case BPF_OR | BPF_FETCH:
7631
- case BPF_XOR:
7632
- case BPF_XOR | BPF_FETCH:
7633
- case BPF_XCHG:
7634
- case BPF_CMPXCHG:
7635
- break;
7636
- default:
7637
- verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n", insn->imm);
7638
- return -EINVAL;
7639
- }
7640
-
7641
7625
if (BPF_SIZE(insn->code) != BPF_W && BPF_SIZE(insn->code) != BPF_DW) {
7642
7626
verbose(env, "invalid atomic operand size\n");
7643
7627
return -EINVAL;
@@ -7699,12 +7683,12 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
7699
7683
/* Check whether we can read the memory, with second call for fetch
7700
7684
* case to simulate the register fill.
7701
7685
*/
7702
- err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
7686
+ err = check_mem_access(env, env-> insn_idx, insn->dst_reg, insn->off,
7703
7687
BPF_SIZE(insn->code), BPF_READ, -1, true, false);
7704
7688
if (!err && load_reg >= 0)
7705
- err = check_mem_access(env, insn_idx, insn->dst_reg , insn->off ,
7706
- BPF_SIZE(insn->code), BPF_READ, load_reg ,
7707
- true, false);
7689
+ err = check_mem_access(env, env->insn_idx , insn->dst_reg ,
7690
+ insn->off, BPF_SIZE(insn->code),
7691
+ BPF_READ, load_reg, true, false);
7708
7692
if (err)
7709
7693
return err;
7710
7694
@@ -7714,13 +7698,34 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
7714
7698
return err;
7715
7699
}
7716
7700
/* Check whether we can write into the same memory. */
7717
- err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
7701
+ err = check_mem_access(env, env-> insn_idx, insn->dst_reg, insn->off,
7718
7702
BPF_SIZE(insn->code), BPF_WRITE, -1, true, false);
7719
7703
if (err)
7720
7704
return err;
7721
7705
return 0;
7722
7706
}
7723
7707
7708
+ static int check_atomic(struct bpf_verifier_env *env, struct bpf_insn *insn)
7709
+ {
7710
+ switch (insn->imm) {
7711
+ case BPF_ADD:
7712
+ case BPF_ADD | BPF_FETCH:
7713
+ case BPF_AND:
7714
+ case BPF_AND | BPF_FETCH:
7715
+ case BPF_OR:
7716
+ case BPF_OR | BPF_FETCH:
7717
+ case BPF_XOR:
7718
+ case BPF_XOR | BPF_FETCH:
7719
+ case BPF_XCHG:
7720
+ case BPF_CMPXCHG:
7721
+ return check_atomic_rmw(env, insn);
7722
+ default:
7723
+ verbose(env, "BPF_ATOMIC uses invalid atomic opcode %02x\n",
7724
+ insn->imm);
7725
+ return -EINVAL;
7726
+ }
7727
+ }
7728
+
7724
7729
/* When register 'regno' is used to read the stack (either directly or through
7725
7730
* a helper function) make sure that it's within stack boundary and, depending
7726
7731
* 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)
19224
19229
enum bpf_reg_type dst_reg_type;
19225
19230
19226
19231
if (BPF_MODE(insn->code) == BPF_ATOMIC) {
19227
- err = check_atomic(env, env->insn_idx, insn);
19232
+ err = check_atomic(env, insn);
19228
19233
if (err)
19229
19234
return err;
19230
19235
env->insn_idx++;
0 commit comments