Re: [PATCH bpf] bpf: Fix remap of arena.

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

 



On Mon, Jun 17, 2024 at 8:34 AM Barret Rhoden <brho@xxxxxxxxxx> wrote:
>
> On 6/15/24 14:19, Alexei Starovoitov wrote:
> > From: Alexei Starovoitov <ast@xxxxxxxxxx>
> >
> > The bpf arena logic didn't account for mremap operation. Add a refcnt for
> > multiple mmap events to prevent use-after-free in arena_vm_close.
> >
> > Reported-by: Pengfei Xu <pengfei.xu@xxxxxxxxx>
> > Closes: https://lore.kernel.org/bpf/Zmuw29IhgyPNKnIM@xxxxxxxxxxxxxxxx/
> > Fixes: 317460317a02 ("bpf: Introduce bpf_arena.")
> > Signed-off-by: Alexei Starovoitov <ast@xxxxxxxxxx>
> > ---
> >   kernel/bpf/arena.c | 13 +++++++++++++
> >   1 file changed, 13 insertions(+)
> >
> > diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
> > index 583ee4fe48ef..f31fcaf7ee8e 100644
> > --- a/kernel/bpf/arena.c
> > +++ b/kernel/bpf/arena.c
> > @@ -48,6 +48,7 @@ struct bpf_arena {
> >       struct maple_tree mt;
> >       struct list_head vma_list;
> >       struct mutex lock;
> > +     atomic_t mmap_count;
> >   };
> >
> >   u64 bpf_arena_get_kern_vm_start(struct bpf_arena *arena)
> > @@ -227,12 +228,22 @@ static int remember_vma(struct bpf_arena *arena, struct vm_area_struct *vma)
> >       return 0;
> >   }
> >
> > +static void arena_vm_open(struct vm_area_struct *vma)
> > +{
> > +     struct bpf_map *map = vma->vm_file->private_data;
> > +     struct bpf_arena *arena = container_of(map, struct bpf_arena, map);
> > +
> > +     atomic_inc(&arena->mmap_count);
> > +}
> > +
> >   static void arena_vm_close(struct vm_area_struct *vma)
> >   {
> >       struct bpf_map *map = vma->vm_file->private_data;
> >       struct bpf_arena *arena = container_of(map, struct bpf_arena, map);
> >       struct vma_list *vml;
> >
> > +     if (!atomic_dec_and_test(&arena->mmap_count))
> > +             return;
> >       guard(mutex)(&arena->lock);
> >       vml = vma->vm_private_data;
> >       list_del(&vml->head);
> > @@ -287,6 +298,7 @@ static vm_fault_t arena_vm_fault(struct vm_fault *vmf)
> >   }
> >
> >   static const struct vm_operations_struct arena_vm_ops = {
> > +     .open           = arena_vm_open,
> >       .close          = arena_vm_close,
> >       .fault          = arena_vm_fault,
> >   };
> > @@ -361,6 +373,7 @@ static int arena_map_mmap(struct bpf_map *map, struct vm_area_struct *vma)
> >        */
> >       vm_flags_set(vma, VM_DONTEXPAND);
> >       vma->vm_ops = &arena_vm_ops;
> > +     atomic_set(&arena->mmap_count, 1);
>
> i'm not sure, but i have the feeling that this refcnt should be on the
> struct vma_list or something.
>
> what happens if two different processes mmap the same arena?  will the
> second one come in and set the mmap_count = 1, clobbering whatever the
> first process had already done?
>
> what are the rules for a vma's vm_ops?  something like: "there will be a
> close() for the initial mmap and for every open()"?

yep.

>
> if that's what it's doing, then this initial refcnt = 1 corresponds to
> the remember_vma() call.  in which case, vm_ops->open ought to lookup
> the remembered vma (struct vma_list) and do the incref there.

good point. will change.

pw-bot: cr





[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