@@ -7616,28 +7616,12 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
76167616static int save_aux_ptr_type(struct bpf_verifier_env *env, enum bpf_reg_type type,
76177617 bool allow_trust_mismatch);
76187618
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)
76207621{
76217622 int load_reg;
76227623 int err;
76237624
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-
76417625 if (BPF_SIZE(insn->code) != BPF_W && BPF_SIZE(insn->code) != BPF_DW) {
76427626 verbose(env, "invalid atomic operand size\n");
76437627 return -EINVAL;
@@ -7699,12 +7683,12 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
76997683 /* Check whether we can read the memory, with second call for fetch
77007684 * case to simulate the register fill.
77017685 */
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,
77037687 BPF_SIZE(insn->code), BPF_READ, -1, true, false);
77047688 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);
77087692 if (err)
77097693 return err;
77107694
@@ -7714,13 +7698,34 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
77147698 return err;
77157699 }
77167700 /* 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,
77187702 BPF_SIZE(insn->code), BPF_WRITE, -1, true, false);
77197703 if (err)
77207704 return err;
77217705 return 0;
77227706}
77237707
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+
77247729/* When register 'regno' is used to read the stack (either directly or through
77257730 * a helper function) make sure that it's within stack boundary and, depending
77267731 * 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)
1922419229 enum bpf_reg_type dst_reg_type;
1922519230
1922619231 if (BPF_MODE(insn->code) == BPF_ATOMIC) {
19227- err = check_atomic(env, env->insn_idx, insn);
19232+ err = check_atomic(env, insn);
1922819233 if (err)
1922919234 return err;
1923019235 env->insn_idx++;
0 commit comments