commit 37435f7e80ef9adc32a69013c18f135e3f434244 upstream commit taken from: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit/?id=37435f7e80ef9adc32a69013c18f135e3f434244
An UNKNOWN_VALUE is not supposed to be derived from a pointer, unless pointer leaks are allowed. Therefore, states_equal() must not treat a state with a pointer in a register as "equal" to a state with an UNKNOWN_VALUE in that register. This was fixed differently upstream, but the code around here was largely rewritten in 4.14 by commit f1174f77b50c "bpf/verifier: rework value tracking". The bug can be detected by the bpf/verifier sub-test "pointer/scalar confusion in state equality check (way 1)". Signed-off-by: Ben Hutchings <[email protected]> Cc: Edward Cree <[email protected]> Cc: Jann Horn <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Daniel Borkmann <[email protected]> [OP: adjusted context for kernel version 4.8] Signed-off-by: Ovidiu Panait <[email protected]> --- kernel/bpf/verifier.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 48fe5d4da143..d2e228eeb733 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -706,12 +706,13 @@ static int check_ctx_access(struct verifier_env *env, int off, int size, return -EACCES; } -static bool is_pointer_value(struct verifier_env *env, int regno) +static bool __is_pointer_value(bool allow_ptr_leaks, + const struct reg_state *reg) { - if (env->allow_ptr_leaks) + if (allow_ptr_leaks) return false; - switch (env->cur_state.regs[regno].type) { + switch (reg->type) { case UNKNOWN_VALUE: case CONST_IMM: return false; @@ -720,6 +721,12 @@ static bool is_pointer_value(struct verifier_env *env, int regno) } } +static bool is_pointer_value(struct verifier_env *env, int regno) +{ + return __is_pointer_value(env->allow_ptr_leaks, &env->cur_state.regs[regno]); +} + + static int check_ptr_alignment(struct verifier_env *env, struct reg_state *reg, int off, int size) { @@ -2147,9 +2154,9 @@ static bool states_equal(struct verifier_state *old, struct verifier_state *cur) if (memcmp(rold, rcur, sizeof(*rold)) == 0) continue; - if (rold->type == NOT_INIT || - (rold->type == UNKNOWN_VALUE && rcur->type != NOT_INIT)) + (rold->type == UNKNOWN_VALUE && rcur->type != NOT_INIT && + !__is_pointer_value(capable(CAP_SYS_ADMIN), rcur))) continue; if (rold->type == PTR_TO_PACKET && rcur->type == PTR_TO_PACKET && -- 2.11.0 -- _______________________________________________ linux-yocto mailing list [email protected] https://lists.yoctoproject.org/listinfo/linux-yocto
