[linux-yocto] [PATCH][linux-yocto-4.8] bpf/verifier: Fix states_equal() comparison of pointer and UNKNOWN

Bruce Ashfield bruce.ashfield at windriver.com
Mon Apr 2 07:10:29 PDT 2018


On 2018-04-02 8:18 AM, Ovidiu Panait wrote:
> 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 <ben at decadent.org.uk>
> Cc: Edward Cree <ecree at solarflare.com>
> Cc: Jann Horn <jannh at google.com>
> Cc: Alexei Starovoitov <ast at kernel.org>
> Cc: Daniel Borkmann <daniel at iogearbox.net>
> [OP: adjusted context for kernel version 4.8]

merged.

Bruce

> Signed-off-by: Ovidiu Panait <ovidiu.panait at windriver.com>
> ---
>   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 &&
> 



More information about the linux-yocto mailing list