Skip to content

Commit 8e432e6

Browse files
anakryikoborkmann
authored andcommitted
bpf: Ensure precise is reset to false in __mark_reg_const_zero()
It is safe to always start with imprecise SCALAR_VALUE register. Previously __mark_reg_const_zero() relied on caller to reset precise mark, but it's very error prone and we already missed it in a few places. So instead make __mark_reg_const_zero() reset precision always, as it's a safe default for SCALAR_VALUE. Explanation is basically the same as for why we are resetting (or rather not setting) precision in current state. If necessary, precision propagation will set it to precise correctly. As such, also remove a big comment about forward precision propagation in mark_reg_stack_read() and avoid unnecessarily setting precision to true after reading from STACK_ZERO stack. Again, precision propagation will correctly handle this, if that SCALAR_VALUE register will ever be needed to be precise. Reported-by: Maxim Mikityanskiy <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Yonghong Song <[email protected]> Acked-by: Maxim Mikityanskiy <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 6079ae6 commit 8e432e6

File tree

2 files changed

+19
-20
lines changed

2 files changed

+19
-20
lines changed

kernel/bpf/verifier.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,10 +1777,14 @@ static void __mark_reg_known_zero(struct bpf_reg_state *reg)
17771777
__mark_reg_known(reg, 0);
17781778
}
17791779

1780-
static void __mark_reg_const_zero(struct bpf_reg_state *reg)
1780+
static void __mark_reg_const_zero(const struct bpf_verifier_env *env, struct bpf_reg_state *reg)
17811781
{
17821782
__mark_reg_known(reg, 0);
17831783
reg->type = SCALAR_VALUE;
1784+
/* all scalars are assumed imprecise initially (unless unprivileged,
1785+
* in which case everything is forced to be precise)
1786+
*/
1787+
reg->precise = !env->bpf_capable;
17841788
}
17851789

17861790
static void mark_reg_known_zero(struct bpf_verifier_env *env,
@@ -4706,21 +4710,10 @@ static void mark_reg_stack_read(struct bpf_verifier_env *env,
47064710
zeros++;
47074711
}
47084712
if (zeros == max_off - min_off) {
4709-
/* any access_size read into register is zero extended,
4710-
* so the whole register == const_zero
4711-
*/
4712-
__mark_reg_const_zero(&state->regs[dst_regno]);
4713-
/* backtracking doesn't support STACK_ZERO yet,
4714-
* so mark it precise here, so that later
4715-
* backtracking can stop here.
4716-
* Backtracking may not need this if this register
4717-
* doesn't participate in pointer adjustment.
4718-
* Forward propagation of precise flag is not
4719-
* necessary either. This mark is only to stop
4720-
* backtracking. Any register that contributed
4721-
* to const 0 was marked precise before spill.
4713+
/* Any access_size read into register is zero extended,
4714+
* so the whole register == const_zero.
47224715
*/
4723-
state->regs[dst_regno].precise = true;
4716+
__mark_reg_const_zero(env, &state->regs[dst_regno]);
47244717
} else {
47254718
/* have read misc data from the stack */
47264719
mark_reg_unknown(env, state->regs, dst_regno);
@@ -4803,11 +4796,11 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
48034796

48044797
if (spill_cnt == size &&
48054798
tnum_is_const(reg->var_off) && reg->var_off.value == 0) {
4806-
__mark_reg_const_zero(&state->regs[dst_regno]);
4799+
__mark_reg_const_zero(env, &state->regs[dst_regno]);
48074800
/* this IS register fill, so keep insn_flags */
48084801
} else if (zero_cnt == size) {
48094802
/* similarly to mark_reg_stack_read(), preserve zeroes */
4810-
__mark_reg_const_zero(&state->regs[dst_regno]);
4803+
__mark_reg_const_zero(env, &state->regs[dst_regno]);
48114804
insn_flags = 0; /* not restoring original register state */
48124805
} else {
48134806
mark_reg_unknown(env, state->regs, dst_regno);
@@ -7963,7 +7956,7 @@ static int process_iter_next_call(struct bpf_verifier_env *env, int insn_idx,
79637956
/* switch to DRAINED state, but keep the depth unchanged */
79647957
/* mark current iter state as drained and assume returned NULL */
79657958
cur_iter->iter.state = BPF_ITER_STATE_DRAINED;
7966-
__mark_reg_const_zero(&cur_fr->regs[BPF_REG_0]);
7959+
__mark_reg_const_zero(env, &cur_fr->regs[BPF_REG_0]);
79677960

79687961
return 0;
79697962
}

tools/testing/selftests/bpf/progs/verifier_spill_fill.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,14 @@ __success
499499
__msg("2: (7a) *(u64 *)(r10 -8) = 0 ; R10=fp0 fp-8_w=00000000")
500500
/* but fp-16 is spilled IMPRECISE zero const reg */
501501
__msg("4: (7b) *(u64 *)(r10 -16) = r0 ; R0_w=0 R10=fp0 fp-16_w=0")
502-
/* and now check that precision propagation works even for such tricky case */
503-
__msg("10: (71) r2 = *(u8 *)(r10 -9) ; R2_w=P0 R10=fp0 fp-16_w=0")
502+
/* validate that assigning R2 from STACK_ZERO doesn't mark register
503+
* precise immediately; if necessary, it will be marked precise later
504+
*/
505+
__msg("6: (71) r2 = *(u8 *)(r10 -1) ; R2_w=0 R10=fp0 fp-8_w=00000000")
506+
/* similarly, when R2 is assigned from spilled register, it is initially
507+
* imprecise, but will be marked precise later once it is used in precise context
508+
*/
509+
__msg("10: (71) r2 = *(u8 *)(r10 -9) ; R2_w=0 R10=fp0 fp-16_w=0")
504510
__msg("11: (0f) r1 += r2")
505511
__msg("mark_precise: frame0: last_idx 11 first_idx 0 subseq_idx -1")
506512
__msg("mark_precise: frame0: regs=r2 stack= before 10: (71) r2 = *(u8 *)(r10 -9)")

0 commit comments

Comments
 (0)