linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
To: Qian Cai <cai@lca.pw>
Cc: Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Martin KaFai Lau <kafai@fb.com>, Song Liu <songliubraving@fb.com>,
	Yonghong Song <yhs@fb.com>, Andrii Nakryiko <andriin@fb.com>,
	John Fastabend <john.fastabend@gmail.com>,
	KP Singh <kpsingh@chromium.org>,
	Linux Netdev List <netdev@vger.kernel.org>,
	bpf <bpf@vger.kernel.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	clang-built-linux <clang-built-linux@googlegroups.com>,
	Kees Cook <keescook@chromium.org>
Subject: Re: UBSAN: array-index-out-of-bounds in kernel/bpf/arraymap.c:177
Date: Tue, 19 May 2020 16:23:18 -0700	[thread overview]
Message-ID: <CAEf4BzZKCh7+2TL8GVetxrOKYCoL0U7jTGsO5CbDExs7Px+bYQ@mail.gmail.com> (raw)
In-Reply-To: <CAG=TAF45T4pKew6U2kPNBK0qSAjgoECAX81obmKmFnv0cjE-oA@mail.gmail.com>

On Tue, May 19, 2020 at 1:18 PM Qian Cai <cai@lca.pw> wrote:
>
> On Tue, May 19, 2020 at 3:30 PM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
> >
> > On Tue, May 19, 2020 at 8:00 AM Qian Cai <cai@lca.pw> wrote:
> > >
> > > On Mon, May 18, 2020 at 8:25 PM Andrii Nakryiko
> > > <andrii.nakryiko@gmail.com> wrote:
> > > >
> > > > On Mon, May 18, 2020 at 5:09 PM Qian Cai <cai@lca.pw> wrote:
> > > > >
> > > > > On Mon, May 18, 2020 at 7:55 PM Andrii Nakryiko
> > > > > <andrii.nakryiko@gmail.com> wrote:
> > > > > >
> > > > > > On Sun, May 17, 2020 at 7:45 PM Qian Cai <cai@lca.pw> wrote:
> > > > > > >
> > > > > > > With Clang 9.0.1,
> > > > > > >
> > > > > > > return array->value + array->elem_size * (index & array->index_mask);
> > > > > > >
> > > > > > > but array->value is,
> > > > > > >
> > > > > > > char value[0] __aligned(8);
> > > > > >
> > > > > > This, and ptrs and pptrs, should be flexible arrays. But they are in a
> > > > > > union, and unions don't support flexible arrays. Putting each of them
> > > > > > into anonymous struct field also doesn't work:
> > > > > >
> > > > > > /data/users/andriin/linux/include/linux/bpf.h:820:18: error: flexible
> > > > > > array member in a struct with no named members
> > > > > >    struct { void *ptrs[] __aligned(8); };
> > > > > >
> > > > > > So it probably has to stay this way. Is there a way to silence UBSAN
> > > > > > for this particular case?
> > > > >
> > > > > I am not aware of any way to disable a particular function in UBSAN
> > > > > except for the whole file in kernel/bpf/Makefile,
> > > > >
> > > > > UBSAN_SANITIZE_arraymap.o := n
> > > > >
> > > > > If there is no better way to do it, I'll send a patch for it.
> > > >
> > > >
> > > > That's probably going to be too drastic, we still would want to
> > > > validate the rest of arraymap.c code, probably. Not sure, maybe
> > > > someone else has better ideas.
> > >
> > > This works although it might makes sense to create a pair of
> > > ubsan_disable_current()/ubsan_enable_current() for it.
> > >
> > > diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
> > > index 11584618e861..6415b089725e 100644
> > > --- a/kernel/bpf/arraymap.c
> > > +++ b/kernel/bpf/arraymap.c
> > > @@ -170,11 +170,16 @@ static void *array_map_lookup_elem(struct
> > > bpf_map *map, void *key)
> > >  {
> > >         struct bpf_array *array = container_of(map, struct bpf_array, map);
> > >         u32 index = *(u32 *)key;
> > > +       void *elem;
> > >
> > >         if (unlikely(index >= array->map.max_entries))
> > >                 return NULL;
> > >
> > > -       return array->value + array->elem_size * (index & array->index_mask);
> > > +       current->in_ubsan++;
> > > +       elem = array->value + array->elem_size * (index & array->index_mask);
> > > +       current->in_ubsan--;
> >
> > This is an unnecessary performance hit for silencing what is clearly a
> > false positive. I'm not sure that's the right solution here. It seems
> > like something that's lacking on the tooling side instead. C language
> > doesn't allow to express the intent here using flexible array
> > approach. That doesn't mean that what we are doing here is wrong or
> > undefined.
>
> Oh, so you worry about this ++ and -- hurt the performance? If so, how
> about this?
>
> ubsan_disable_current();
> elem = array->value + array->elem_size * (index & array->index_mask);
> ubsan_enable_current();
>
> #ifdef UBSAN
> ubsan_disable_current()
> {
>       current->in_ubsan++;
> }
> #else
> ubsan_disable_current() {}
> #endif
>
> etc
>
> Production kernel would normally have UBSAN=n, so it is an noop.

That would solve runtime performance hit, yes.

>
> Leaving this false positive unsilenced may also waste many people's
> time over and over again, and increase the noisy level. Especially, it
> seems this is one-off (not seen other parts of kernel doing like this)
> and rather expensive to silence it in the UBSAN or/and compilers.

I agree, it's bad to have this noise. But again, there is nothing
wrong with the way it's used in BPF code base. We'd gladly use
flexible array, if we could. But given we can't, I'd say the proper
solution (in order of my preference) would be:

  - don't trigger false error, if zero-sized array is the member of union;
  - or have some sort of annotation at field declaration site (not a
field access site).

Is that possible?

  reply	other threads:[~2020-05-19 23:23 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-18  2:44 UBSAN: array-index-out-of-bounds in kernel/bpf/arraymap.c:177 Qian Cai
2020-05-18 23:55 ` Andrii Nakryiko
2020-05-19  0:09   ` Qian Cai
2020-05-19  0:25     ` Andrii Nakryiko
2020-05-19  1:00       ` Yonghong Song
2020-05-19  1:30         ` Andrii Nakryiko
2020-05-19  1:36           ` Yonghong Song
2020-05-19 15:00       ` Qian Cai
2020-05-19 19:29         ` Andrii Nakryiko
2020-05-19 20:18           ` Qian Cai
2020-05-19 23:23             ` Andrii Nakryiko [this message]
2020-05-20  1:55               ` Qian Cai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAEf4BzZKCh7+2TL8GVetxrOKYCoL0U7jTGsO5CbDExs7Px+bYQ@mail.gmail.com \
    --to=andrii.nakryiko@gmail.com \
    --cc=andriin@fb.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=cai@lca.pw \
    --cc=clang-built-linux@googlegroups.com \
    --cc=daniel@iogearbox.net \
    --cc=john.fastabend@gmail.com \
    --cc=kafai@fb.com \
    --cc=keescook@chromium.org \
    --cc=kpsingh@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=songliubraving@fb.com \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).