On 09/28/2018 01:26 AM, Joe Stringer wrote:
> Teach the verifier a little bit about a new type of pointer, a
> PTR_TO_SOCKET. This pointer type is accessed from BPF through the
> 'struct bpf_sock' structure.
> 
> Signed-off-by: Joe Stringer <j...@wand.net.nz>
[...]
> +/* Return true if it's OK to have the same insn return a different type. */
> +static bool reg_type_mismatch_ok(enum bpf_reg_type type)
> +{
> +     switch (type) {
> +     case PTR_TO_CTX:
> +     case PTR_TO_SOCKET:
> +     case PTR_TO_SOCKET_OR_NULL:
> +             return false;
> +     default:
> +             return true;
> +     }
> +}
> +
> +/* If an instruction was previously used with particular pointer types, then 
> we
> + * need to be careful to avoid cases such as the below, where it may be ok
> + * for one branch accessing the pointer, but not ok for the other branch:
> + *
> + * R1 = sock_ptr
> + * goto X;
> + * ...
> + * R1 = some_other_valid_ptr;
> + * goto X;
> + * ...
> + * R2 = *(u32 *)(R1 + 0);
> + */
> +static bool reg_type_mismatch(enum bpf_reg_type src, enum bpf_reg_type prev)
> +{
> +     return src != prev && (!reg_type_mismatch_ok(src) ||
> +                            !reg_type_mismatch_ok(prev));
> +}
> +
>  static int do_check(struct bpf_verifier_env *env)
>  {
>       struct bpf_verifier_state *state;
> @@ -4812,9 +4894,7 @@ static int do_check(struct bpf_verifier_env *env)
>                                */
>                               *prev_src_type = src_reg_type;
>  
> -                     } else if (src_reg_type != *prev_src_type &&
> -                                (src_reg_type == PTR_TO_CTX ||
> -                                 *prev_src_type == PTR_TO_CTX)) {
> +                     } else if (reg_type_mismatch(src_reg_type, 
> *prev_src_type)) {
>                               /* ABuser program is trying to use the same insn
>                                * dst_reg = *(u32*) (src_reg + off)
>                                * with different pointer types:
> @@ -4859,9 +4939,7 @@ static int do_check(struct bpf_verifier_env *env)
>  
>                       if (*prev_dst_type == NOT_INIT) {
>                               *prev_dst_type = dst_reg_type;
> -                     } else if (dst_reg_type != *prev_dst_type &&
> -                                (dst_reg_type == PTR_TO_CTX ||
> -                                 *prev_dst_type == PTR_TO_CTX)) {
> +                     } else if (reg_type_mismatch(dst_reg_type, 
> *prev_dst_type)) {
>                               verbose(env, "same insn cannot be used with 
> different pointers\n");
>                               return -EINVAL;

Can also be as follow-up later on, but it would be crucial to also have
test_verifier tests on this logic here with mixing these pointer types
from different branches (right now we only cover ctx there).

Thanks,
Daniel

Reply via email to