Skip to content

Commit 99e762a

Browse files
committed
bpf: Factor out check_load_mem() and check_store_reg()
JIRA: https://issues.redhat.com/browse/RHEL-78202 commit a752ba4 Author: Peilin Ye <yepeilin@google.com> Date: Mon Mar 3 05:37:25 2025 +0000 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: Eduard Zingerman <eddyz87@gmail.com> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Peilin Ye <yepeilin@google.com> Link: https://lore.kernel.org/r/8b39c94eac2bb7389ff12392ca666f939124ec4f.1740978603.git.yepeilin@google.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Gregory Bell <grbell@redhat.com>
1 parent 2b6dc25 commit 99e762a

File tree

1 file changed

+67
-43
lines changed

1 file changed

+67
-43
lines changed

kernel/bpf/verifier.c

Lines changed: 67 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7616,6 +7616,67 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
76167616
static 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_load_mem(struct bpf_verifier_env *env, struct bpf_insn *insn,
7620+
bool strict_alignment_once, bool is_ldsx,
7621+
bool allow_trust_mismatch, const char *ctx)
7622+
{
7623+
struct bpf_reg_state *regs = cur_regs(env);
7624+
enum bpf_reg_type src_reg_type;
7625+
int err;
7626+
7627+
/* check src operand */
7628+
err = check_reg_arg(env, insn->src_reg, SRC_OP);
7629+
if (err)
7630+
return err;
7631+
7632+
/* check dst operand */
7633+
err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
7634+
if (err)
7635+
return err;
7636+
7637+
src_reg_type = regs[insn->src_reg].type;
7638+
7639+
/* Check if (src_reg + off) is readable. The state of dst_reg will be
7640+
* updated by this call.
7641+
*/
7642+
err = check_mem_access(env, env->insn_idx, insn->src_reg, insn->off,
7643+
BPF_SIZE(insn->code), BPF_READ, insn->dst_reg,
7644+
strict_alignment_once, is_ldsx);
7645+
err = err ?: save_aux_ptr_type(env, src_reg_type,
7646+
allow_trust_mismatch);
7647+
err = err ?: reg_bounds_sanity_check(env, &regs[insn->dst_reg], ctx);
7648+
7649+
return err;
7650+
}
7651+
7652+
static int check_store_reg(struct bpf_verifier_env *env, struct bpf_insn *insn,
7653+
bool strict_alignment_once)
7654+
{
7655+
struct bpf_reg_state *regs = cur_regs(env);
7656+
enum bpf_reg_type dst_reg_type;
7657+
int err;
7658+
7659+
/* check src1 operand */
7660+
err = check_reg_arg(env, insn->src_reg, SRC_OP);
7661+
if (err)
7662+
return err;
7663+
7664+
/* check src2 operand */
7665+
err = check_reg_arg(env, insn->dst_reg, SRC_OP);
7666+
if (err)
7667+
return err;
7668+
7669+
dst_reg_type = regs[insn->dst_reg].type;
7670+
7671+
/* Check if (dst_reg + off) is writeable. */
7672+
err = check_mem_access(env, env->insn_idx, insn->dst_reg, insn->off,
7673+
BPF_SIZE(insn->code), BPF_WRITE, insn->src_reg,
7674+
strict_alignment_once, false);
7675+
err = err ?: save_aux_ptr_type(env, dst_reg_type, false);
7676+
7677+
return err;
7678+
}
7679+
76197680
static int check_atomic_rmw(struct bpf_verifier_env *env,
76207681
struct bpf_insn *insn)
76217682
{
@@ -19186,35 +19247,16 @@ static int do_check(struct bpf_verifier_env *env)
1918619247
return err;
1918719248

1918819249
} else if (class == BPF_LDX) {
19189-
enum bpf_reg_type src_reg_type;
19190-
19191-
/* check for reserved fields is already done */
19192-
19193-
/* check src operand */
19194-
err = check_reg_arg(env, insn->src_reg, SRC_OP);
19195-
if (err)
19196-
return err;
19250+
bool is_ldsx = BPF_MODE(insn->code) == BPF_MEMSX;
1919719251

19198-
err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
19199-
if (err)
19200-
return err;
19201-
19202-
src_reg_type = regs[insn->src_reg].type;
19203-
19204-
/* check that memory (src_reg + off) is readable,
19205-
* the state of dst_reg will be updated by this func
19252+
/* Check for reserved fields is already done in
19253+
* resolve_pseudo_ldimm64().
1920619254
*/
19207-
err = check_mem_access(env, env->insn_idx, insn->src_reg,
19208-
insn->off, BPF_SIZE(insn->code),
19209-
BPF_READ, insn->dst_reg, false,
19210-
BPF_MODE(insn->code) == BPF_MEMSX);
19211-
err = err ?: save_aux_ptr_type(env, src_reg_type, true);
19212-
err = err ?: reg_bounds_sanity_check(env, &regs[insn->dst_reg], "ldx");
19255+
err = check_load_mem(env, insn, false, is_ldsx, true,
19256+
"ldx");
1921319257
if (err)
1921419258
return err;
1921519259
} else if (class == BPF_STX) {
19216-
enum bpf_reg_type dst_reg_type;
19217-
1921819260
if (BPF_MODE(insn->code) == BPF_ATOMIC) {
1921919261
err = check_atomic(env, insn);
1922019262
if (err)
@@ -19228,25 +19270,7 @@ static int do_check(struct bpf_verifier_env *env)
1922819270
return -EINVAL;
1922919271
}
1923019272

19231-
/* check src1 operand */
19232-
err = check_reg_arg(env, insn->src_reg, SRC_OP);
19233-
if (err)
19234-
return err;
19235-
/* check src2 operand */
19236-
err = check_reg_arg(env, insn->dst_reg, SRC_OP);
19237-
if (err)
19238-
return err;
19239-
19240-
dst_reg_type = regs[insn->dst_reg].type;
19241-
19242-
/* check that memory (dst_reg + off) is writeable */
19243-
err = check_mem_access(env, env->insn_idx, insn->dst_reg,
19244-
insn->off, BPF_SIZE(insn->code),
19245-
BPF_WRITE, insn->src_reg, false, false);
19246-
if (err)
19247-
return err;
19248-
19249-
err = save_aux_ptr_type(env, dst_reg_type, false);
19273+
err = check_store_reg(env, insn, false);
1925019274
if (err)
1925119275
return err;
1925219276
} else if (class == BPF_ST) {

0 commit comments

Comments
 (0)