Skip to content

Commit 840b961

Browse files
joestringerborkmann
authored andcommitted
bpf: Generalize ptr_or_null regs check
This check will be reused by an upcoming commit for conditional jump checks for sockets. Refactor it a bit to simplify the later commit. Signed-off-by: Joe Stringer <joe@wand.net.nz> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
1 parent 9d2be44 commit 840b961

File tree

1 file changed

+25
-18
lines changed

1 file changed

+25
-18
lines changed

kernel/bpf/verifier.c

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,11 @@ static bool type_is_pkt_pointer(enum bpf_reg_type type)
249249
type == PTR_TO_PACKET_META;
250250
}
251251

252+
static bool reg_type_may_be_null(enum bpf_reg_type type)
253+
{
254+
return type == PTR_TO_MAP_VALUE_OR_NULL;
255+
}
256+
252257
/* string representation of 'enum bpf_reg_type' */
253258
static const char * const reg_type_str[] = {
254259
[NOT_INIT] = "?",
@@ -3599,12 +3604,10 @@ static void reg_combine_min_max(struct bpf_reg_state *true_src,
35993604
}
36003605
}
36013606

3602-
static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
3603-
bool is_null)
3607+
static void mark_ptr_or_null_reg(struct bpf_reg_state *reg, u32 id,
3608+
bool is_null)
36043609
{
3605-
struct bpf_reg_state *reg = &regs[regno];
3606-
3607-
if (reg->type == PTR_TO_MAP_VALUE_OR_NULL && reg->id == id) {
3610+
if (reg_type_may_be_null(reg->type) && reg->id == id) {
36083611
/* Old offset (both fixed and variable parts) should
36093612
* have been known-zero, because we don't allow pointer
36103613
* arithmetic on pointers that might be NULL.
@@ -3617,11 +3620,13 @@ static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
36173620
}
36183621
if (is_null) {
36193622
reg->type = SCALAR_VALUE;
3620-
} else if (reg->map_ptr->inner_map_meta) {
3621-
reg->type = CONST_PTR_TO_MAP;
3622-
reg->map_ptr = reg->map_ptr->inner_map_meta;
3623-
} else {
3624-
reg->type = PTR_TO_MAP_VALUE;
3623+
} else if (reg->type == PTR_TO_MAP_VALUE_OR_NULL) {
3624+
if (reg->map_ptr->inner_map_meta) {
3625+
reg->type = CONST_PTR_TO_MAP;
3626+
reg->map_ptr = reg->map_ptr->inner_map_meta;
3627+
} else {
3628+
reg->type = PTR_TO_MAP_VALUE;
3629+
}
36253630
}
36263631
/* We don't need id from this point onwards anymore, thus we
36273632
* should better reset it, so that state pruning has chances
@@ -3634,23 +3639,23 @@ static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
36343639
/* The logic is similar to find_good_pkt_pointers(), both could eventually
36353640
* be folded together at some point.
36363641
*/
3637-
static void mark_map_regs(struct bpf_verifier_state *vstate, u32 regno,
3638-
bool is_null)
3642+
static void mark_ptr_or_null_regs(struct bpf_verifier_state *vstate, u32 regno,
3643+
bool is_null)
36393644
{
36403645
struct bpf_func_state *state = vstate->frame[vstate->curframe];
36413646
struct bpf_reg_state *reg, *regs = state->regs;
36423647
u32 id = regs[regno].id;
36433648
int i, j;
36443649

36453650
for (i = 0; i < MAX_BPF_REG; i++)
3646-
mark_map_reg(regs, i, id, is_null);
3651+
mark_ptr_or_null_reg(&regs[i], id, is_null);
36473652

36483653
for (j = 0; j <= vstate->curframe; j++) {
36493654
state = vstate->frame[j];
36503655
bpf_for_each_spilled_reg(i, state, reg) {
36513656
if (!reg)
36523657
continue;
3653-
mark_map_reg(&state->stack[i].spilled_ptr, 0, id, is_null);
3658+
mark_ptr_or_null_reg(reg, id, is_null);
36543659
}
36553660
}
36563661
}
@@ -3852,12 +3857,14 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
38523857
/* detect if R == 0 where R is returned from bpf_map_lookup_elem() */
38533858
if (BPF_SRC(insn->code) == BPF_K &&
38543859
insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
3855-
dst_reg->type == PTR_TO_MAP_VALUE_OR_NULL) {
3856-
/* Mark all identical map registers in each branch as either
3860+
reg_type_may_be_null(dst_reg->type)) {
3861+
/* Mark all identical registers in each branch as either
38573862
* safe or unknown depending R == 0 or R != 0 conditional.
38583863
*/
3859-
mark_map_regs(this_branch, insn->dst_reg, opcode == BPF_JNE);
3860-
mark_map_regs(other_branch, insn->dst_reg, opcode == BPF_JEQ);
3864+
mark_ptr_or_null_regs(this_branch, insn->dst_reg,
3865+
opcode == BPF_JNE);
3866+
mark_ptr_or_null_regs(other_branch, insn->dst_reg,
3867+
opcode == BPF_JEQ);
38613868
} else if (!try_match_pkt_pointers(insn, dst_reg, &regs[insn->src_reg],
38623869
this_branch, other_branch) &&
38633870
is_pointer_value(env, insn->dst_reg)) {

0 commit comments

Comments
 (0)