Re: [PATCH bpf-next v4 1/2] bpf: Fix ref_obj_id for dynptr data slices in verifier

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Aug 9, 2022 at 2:41 PM Joanne Koong <joannelkoong@xxxxxxxxx> wrote:
>
> When a data slice is obtained from a dynptr (through the bpf_dynptr_data API),
> the ref obj id of the dynptr must be found and then associated with the data
> slice.
>
> The ref obj id of the dynptr must be found *before* the caller saved regs are
> reset. Without this fix, the ref obj id tracking is not correct for
> dynptrs that are at an offset from the frame pointer.
>
> Please also note that the data slice's ref obj id must be assigned after the
> ret types are parsed, since RET_PTR_TO_ALLOC_MEM-type return regs get
> zero-marked.
>
> Fixes: 34d4ef5775f776ec4b0d53a02d588bf3195cada6 ("bpf: Add dynptr data slices");

The proper format is:
Fixes: 34d4ef5775f7 ("bpf: Add dynptr data slices")
make sure you have abbrev = 12 in your .gitconfig
No need for ; at the end.

> Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx>
> ---
>  kernel/bpf/verifier.c | 38 ++++++++++++++++++++------------------
>  1 file changed, 20 insertions(+), 18 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 01e7f48b4d8c..28b02dc67a2a 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -504,7 +504,7 @@ static bool is_ptr_cast_function(enum bpf_func_id func_id)
>                 func_id == BPF_FUNC_skc_to_tcp_request_sock;
>  }
>
> -static bool is_dynptr_acquire_function(enum bpf_func_id func_id)
> +static bool is_dynptr_ref_function(enum bpf_func_id func_id)
>  {
>         return func_id == BPF_FUNC_dynptr_data;
>  }
> @@ -518,7 +518,7 @@ static bool helper_multiple_ref_obj_use(enum bpf_func_id func_id,
>                 ref_obj_uses++;
>         if (is_acquire_function(func_id, map))
>                 ref_obj_uses++;
> -       if (is_dynptr_acquire_function(func_id))
> +       if (is_dynptr_ref_function(func_id))
>                 ref_obj_uses++;
>
>         return ref_obj_uses > 1;
> @@ -7320,6 +7320,23 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
>                         }
>                 }
>                 break;
> +       case BPF_FUNC_dynptr_data:
> +               for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
> +                       if (arg_type_is_dynptr(fn->arg_type[i])) {
> +                               if (meta.ref_obj_id) {
> +                                       verbose(env, "verifier internal error: meta.ref_obj_id already set\n");
> +                                       return -EFAULT;
> +                               }
> +                               /* Find the id of the dynptr we're tracking the reference of */
> +                               meta.ref_obj_id = stack_slot_get_id(env, &regs[BPF_REG_1 + i]);
> +                               break;
> +                       }
> +               }
> +               if (i == MAX_BPF_FUNC_REG_ARGS) {
> +                       verbose(env, "verifier internal error: no dynptr in bpf_dynptr_data()\n");
> +                       return -EFAULT;
> +               }
> +               break;
>         }
>
>         if (err)
> @@ -7457,7 +7474,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
>                 return -EFAULT;
>         }
>
> -       if (is_ptr_cast_function(func_id)) {
> +       if (is_ptr_cast_function(func_id) || is_dynptr_ref_function(func_id)) {
>                 /* For release_reference() */
>                 regs[BPF_REG_0].ref_obj_id = meta.ref_obj_id;
>         } else if (is_acquire_function(func_id, meta.map_ptr)) {
> @@ -7469,21 +7486,6 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
>                 regs[BPF_REG_0].id = id;
>                 /* For release_reference() */
>                 regs[BPF_REG_0].ref_obj_id = id;
> -       } else if (is_dynptr_acquire_function(func_id)) {
> -               int dynptr_id = 0, i;
> -
> -               /* Find the id of the dynptr we're tracking the reference of */
> -               for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
> -                       if (arg_type_is_dynptr(fn->arg_type[i])) {
> -                               if (dynptr_id) {
> -                                       verbose(env, "verifier internal error: multiple dynptr args in func\n");
> -                                       return -EFAULT;
> -                               }
> -                               dynptr_id = stack_slot_get_id(env, &regs[BPF_REG_1 + i]);

So this bit of code was just grabbing REG_[1-5] with reg->off == 0
and random spilled_ptr.id ?
It never worked correctly, right?

Technically bpf material, but applied to bpf-next due to conflicts.



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux