Commit a752ba43 authored by Peilin Ye's avatar Peilin Ye Committed by Alexei Starovoitov
Browse files

bpf: Factor out check_load_mem() and check_store_reg()



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: default avatarEduard Zingerman <eddyz87@gmail.com>
Acked-by: default avatarEduard Zingerman <eddyz87@gmail.com>
Signed-off-by: default avatarPeilin Ye <yepeilin@google.com>
Link: https://lore.kernel.org/r/8b39c94eac2bb7389ff12392ca666f939124ec4f.1740978603.git.yepeilin@google.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 2626ffe9
Loading
Loading
Loading
Loading
+67 −43
Original line number Diff line number Diff line
@@ -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;
			bool is_ldsx = BPF_MODE(insn->code) == BPF_MEMSX;
			/* check for reserved fields is already done */
			/* check src operand */
			err = check_reg_arg(env, insn->src_reg, SRC_OP);
			if (err)
				return err;
			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) {