bpf: Don't promote bogus looking registers after null check.

[ Upstream commit e60b0d12a95dcf16a63225cead4541567f5cb517 ]

If we ever get to a point again where we convert a bogus looking <ptr>_or_null
typed register containing a non-zero fixed or variable offset, then lets not
reset these bounds to zero since they are not and also don't promote the register
to a <ptr> type, but instead leave it as <ptr>_or_null. Converting to a unknown
register could be an avenue as well, but then if we run into this case it would
allow to leak a kernel pointer this way.

Fixes: f1174f77b5 ("bpf/verifier: rework value tracking")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Daniel Borkmann 2022-01-05 11:35:13 -08:00 committed by Greg Kroah-Hartman
parent 0036c78c49
commit 342332fb0b

View File

@ -7725,15 +7725,15 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state,
{ {
if (reg_type_may_be_null(reg->type) && reg->id == id && if (reg_type_may_be_null(reg->type) && reg->id == id &&
!WARN_ON_ONCE(!reg->id)) { !WARN_ON_ONCE(!reg->id)) {
/* Old offset (both fixed and variable parts) should
* have been known-zero, because we don't allow pointer
* arithmetic on pointers that might be NULL.
*/
if (WARN_ON_ONCE(reg->smin_value || reg->smax_value || if (WARN_ON_ONCE(reg->smin_value || reg->smax_value ||
!tnum_equals_const(reg->var_off, 0) || !tnum_equals_const(reg->var_off, 0) ||
reg->off)) { reg->off)) {
__mark_reg_known_zero(reg); /* Old offset (both fixed and variable parts) should
reg->off = 0; * have been known-zero, because we don't allow pointer
* arithmetic on pointers that might be NULL. If we
* see this happening, don't convert the register.
*/
return;
} }
if (is_null) { if (is_null) {
reg->type = SCALAR_VALUE; reg->type = SCALAR_VALUE;