mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 12:03:54 +02:00
bpf: Factor out check_atomic_rmw()
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>
This commit is contained in:
parent
66faaea94e
commit
2626ffe9f3
|
|
@ -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++;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user