Skip to content

Commit d3b398e

Browse files
anakryikogregkh
authored andcommitted
bpf: preserve constant zero when doing partial register restore
[ Upstream commit e322f0b ] Similar to special handling of STACK_ZERO, when reading 1/2/4 bytes from stack from slot that has register spilled into it and that register has a constant value zero, preserve that zero and mark spilled register as precise for that. This makes spilled const zero register and STACK_ZERO cases equivalent in their behavior. Acked-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/r/20231205184248.1502704-7-andrii@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com> Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 6d40191 commit d3b398e

1 file changed

Lines changed: 21 additions & 4 deletions

File tree

kernel/bpf/verifier.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4952,22 +4952,39 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
49524952
copy_register_state(&state->regs[dst_regno], reg);
49534953
state->regs[dst_regno].subreg_def = subreg_def;
49544954
} else {
4955+
int spill_cnt = 0, zero_cnt = 0;
4956+
49554957
for (i = 0; i < size; i++) {
49564958
type = stype[(slot - i) % BPF_REG_SIZE];
4957-
if (type == STACK_SPILL)
4959+
if (type == STACK_SPILL) {
4960+
spill_cnt++;
49584961
continue;
4962+
}
49594963
if (type == STACK_MISC)
49604964
continue;
4961-
if (type == STACK_ZERO)
4965+
if (type == STACK_ZERO) {
4966+
zero_cnt++;
49624967
continue;
4968+
}
49634969
if (type == STACK_INVALID && env->allow_uninit_stack)
49644970
continue;
49654971
verbose(env, "invalid read from stack off %d+%d size %d\n",
49664972
off, i, size);
49674973
return -EACCES;
49684974
}
4969-
mark_reg_unknown(env, state->regs, dst_regno);
4970-
insn_flags = 0; /* not restoring original register state */
4975+
4976+
if (spill_cnt == size &&
4977+
tnum_is_const(reg->var_off) && reg->var_off.value == 0) {
4978+
__mark_reg_const_zero(&state->regs[dst_regno]);
4979+
/* this IS register fill, so keep insn_flags */
4980+
} else if (zero_cnt == size) {
4981+
/* similarly to mark_reg_stack_read(), preserve zeroes */
4982+
__mark_reg_const_zero(&state->regs[dst_regno]);
4983+
insn_flags = 0; /* not restoring original register state */
4984+
} else {
4985+
mark_reg_unknown(env, state->regs, dst_regno);
4986+
insn_flags = 0; /* not restoring original register state */
4987+
}
49714988
}
49724989
state->regs[dst_regno].live |= REG_LIVE_WRITTEN;
49734990
} else if (dst_regno >= 0) {

0 commit comments

Comments
 (0)