Re: [PATCH bpf-next 8/9] libbpf: Add MSan annotations

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

 



On Thu, Feb 9, 2023 at 2:02 AM Ilya Leoshkevich <iii@xxxxxxxxxxxxx> wrote:
>
> On Wed, 2023-02-08 at 17:29 -0800, Andrii Nakryiko wrote:
> > On Wed, Feb 8, 2023 at 12:57 PM Ilya Leoshkevich <iii@xxxxxxxxxxxxx>
> > wrote:
> > >
> > > MSan runs into a few false positives in libbpf. They all come from
> > > the
> > > fact that MSan does not know anything about the bpf syscall,
> > > particularly, what it writes to.
> > >
> > > Add libbpf_mark_defined() function to mark memory modified by the
> > > bpf
> > > syscall. Use the abstract name (it could be e.g.
> > > libbpf_msan_unpoison()), because it can be used for valgrind in the
> > > future as well.
> > >
> > > Signed-off-by: Ilya Leoshkevich <iii@xxxxxxxxxxxxx>
> > > ---
> >
> > This is a lot to satisfy MSan, especially mark_map_value_defined
> > which
> > has to do bpf_obj_get_info_by_fd()... Is there any other way? What
> > happens if we don't do it?
>
> It would generate false positives when accessing the resulting map
> values, which is not nice. The main complexity in this case comes not
> from mark_map_value_defined() per se, but from the fact that we don't
> know the value size, especially for percpu maps.
>
> I toyed with the idea to extend the BPF_MAP_LOOKUP_ELEM interface to
> return the number of bytes written, but decided against it - the only
> user of this would be MSan, and at least for the beginning it's better
> to have extra complexity in userspace, rather than in kernel.

yep, I know, it's a source of very confusing problems in some cases.
Which is why bpf_map__lookup_elem() and such expect user to provide
total key/value size (and checks it against struct bpf_map's knowledge
of key/value size, taking into account if map is per-CPU)

Ok, I don't see any other way around this as well. Just please extract
this check of whether the map is per-cpu or not into a separate
helper, so we can maintain this list in only one place. Currently we
have this check in validate_map_op() and I don't want to duplicate
this.

>
> > As for libbpf_mark_defined, wouldn't it be cleaner to teach it to
> > handle NULL pointer and/or zero size transparently? Also, we can have
> > libbpf_mark_defined_if(void *ptr, size_t sz, bool cond), so in code
> > we
> > don't have to have those explicit if conditions. Instead of:
> >
> > > +       if (!ret && prog_ids)
> > > +               libbpf_mark_defined(prog_ids,
> > > +                                   attr.query.prog_cnt *
> > > sizeof(*prog_ids));
> >
> > we can write just
> >
> > libbpf_mark_defined_if(prog_ids, attr.query.prog_cnt *
> > sizeof(*prog_ids), ret == 0);
> >
> > ?
> >
> > Should we also call a helper something like
> > 'libbpf_mark_mem_written',
> > because that's what we are saying here, right?
>
> Sure, all this sounds reasonable. Will do.
>
> >
> > >  tools/lib/bpf/bpf.c             | 70
> > > +++++++++++++++++++++++++++++++--
> > >  tools/lib/bpf/btf.c             |  1 +
> > >  tools/lib/bpf/libbpf.c          |  1 +
> > >  tools/lib/bpf/libbpf_internal.h | 14 +++++++
> > >  4 files changed, 82 insertions(+), 4 deletions(-)
> > >
> >
> > [...]
> >
> > > diff --git a/tools/lib/bpf/libbpf_internal.h
> > > b/tools/lib/bpf/libbpf_internal.h
> > > index fbaf68335394..4e4622f66fdf 100644
> > > --- a/tools/lib/bpf/libbpf_internal.h
> > > +++ b/tools/lib/bpf/libbpf_internal.h
> > > @@ -577,4 +577,18 @@ static inline bool is_pow_of_2(size_t x)
> > >  #define PROG_LOAD_ATTEMPTS 5
> > >  int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int
> > > attempts);
> > >
> > > +#if defined(__has_feature)
> > > +#if __has_feature(memory_sanitizer)
> > > +#define LIBBPF_MSAN
> > > +#endif
> > > +#endif
> > > +
> > > +#ifdef LIBBPF_MSAN
> >
> > would below work:
> >
> > #if defined(__has_feature) && __has_feature(memory_sanitizer)
> >
> > ?
> >
> > > +#define HAVE_LIBBPF_MARK_DEFINED
> > > +#include <sanitizer/msan_interface.h>
> > > +#define libbpf_mark_defined __msan_unpoison
> > > +#else
> > > +static inline void libbpf_mark_defined(void *s, size_t n) {}
> > > +#endif
> > > +
> > >  #endif /* __LIBBPF_LIBBPF_INTERNAL_H */
> > > --
> > > 2.39.1
> > >
>



[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