netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Joanne Koong <joannelkoong@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: bpf@vger.kernel.org, daniel@iogearbox.net, andrii@kernel.org,
	martin.lau@kernel.org, ast@kernel.org, netdev@vger.kernel.org,
	memxor@gmail.com, kernel-team@fb.com
Subject: Re: [PATCH v9 bpf-next 3/5] bpf: Add skb dynptrs
Date: Mon, 30 Jan 2023 17:13:19 -0800	[thread overview]
Message-ID: <CAJnrk1Y61=Qc3fndvAPghgu8+iNwzU2wvtwsi2jk_NeEwdP9aw@mail.gmail.com> (raw)
In-Reply-To: <CAEf4BzYA2sT7z+2W1XOd_nk2PC3mKST7MC2X8pRg1HfFK3yFpA@mail.gmail.com>

On Mon, Jan 30, 2023 at 5:06 PM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Mon, Jan 30, 2023 at 4:56 PM Joanne Koong <joannelkoong@gmail.com> wrote:
> >
> > On Mon, Jan 30, 2023 at 4:48 PM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> > >
> > > On Fri, Jan 27, 2023 at 11:18 AM Joanne Koong <joannelkoong@gmail.com> wrote:
> > > >
> > > > Add skb dynptrs, which are dynptrs whose underlying pointer points
> > > > to a skb. The dynptr acts on skb data. skb dynptrs have two main
> > > > benefits. One is that they allow operations on sizes that are not
> > > > statically known at compile-time (eg variable-sized accesses).
> > > > Another is that parsing the packet data through dynptrs (instead of
> > > > through direct access of skb->data and skb->data_end) can be more
> > > > ergonomic and less brittle (eg does not need manual if checking for
> > > > being within bounds of data_end).
> > > >
> > > > For bpf prog types that don't support writes on skb data, the dynptr is
> > > > read-only (bpf_dynptr_write() will return an error and bpf_dynptr_data()
> > > > will return a data slice that is read-only where any writes to it will
> > > > be rejected by the verifier).
> > > >
> > > > For reads and writes through the bpf_dynptr_read() and bpf_dynptr_write()
> > > > interfaces, reading and writing from/to data in the head as well as from/to
> > > > non-linear paged buffers is supported. For data slices (through the
> > > > bpf_dynptr_data() interface), if the data is in a paged buffer, the user
> > > > must first call bpf_skb_pull_data() to pull the data into the linear
> > > > portion.
> > > >
> > > > Any bpf_dynptr_write() automatically invalidates any prior data slices
> > > > to the skb dynptr. This is because a bpf_dynptr_write() may be writing
> > > > to data in a paged buffer, so it will need to pull the buffer first into
> > > > the head. The reason it needs to be pulled instead of writing directly to
> > > > the paged buffers is because they may be cloned (only the head of the skb
> > > > is by default uncloned). As such, any bpf_dynptr_write() will
> > > > automatically have its prior data slices invalidated, even if the write
> > > > is to data in the skb head (the verifier has no way of differentiating
> > > > whether the write is to the head or paged buffers during program load
> > > > time). Please note as well that any other helper calls that change the
> > > > underlying packet buffer (eg bpf_skb_pull_data()) invalidates any data
> > > > slices of the skb dynptr as well. The stack trace for this is
> > > > check_helper_call() -> clear_all_pkt_pointers() ->
> > > > __clear_all_pkt_pointers() -> mark_reg_unknown().
> > > >
> > > > For examples of how skb dynptrs can be used, please see the attached
> > > > selftests.
> > > >
> > > > Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
> > > > ---
> > > >  include/linux/bpf.h            |  82 +++++++++------
> > > >  include/linux/filter.h         |  18 ++++
> > > >  include/uapi/linux/bpf.h       |  37 +++++--
> > > >  kernel/bpf/btf.c               |  18 ++++
> > > >  kernel/bpf/helpers.c           |  95 ++++++++++++++---
> > > >  kernel/bpf/verifier.c          | 185 ++++++++++++++++++++++++++-------
> > > >  net/core/filter.c              |  60 ++++++++++-
> > > >  tools/include/uapi/linux/bpf.h |  37 +++++--
> > > >  8 files changed, 432 insertions(+), 100 deletions(-)
> > > >
> > >
> > > [...]
> > >
> > > >  static const struct bpf_func_proto bpf_dynptr_write_proto = {
> > > > @@ -1560,6 +1595,8 @@ static const struct bpf_func_proto bpf_dynptr_write_proto = {
> > > >
> > > >  BPF_CALL_3(bpf_dynptr_data, const struct bpf_dynptr_kern *, ptr, u32, offset, u32, len)
> > > >  {
> > > > +       enum bpf_dynptr_type type;
> > > > +       void *data;
> > > >         int err;
> > > >
> > > >         if (!ptr->data)
> > > > @@ -1569,10 +1606,36 @@ BPF_CALL_3(bpf_dynptr_data, const struct bpf_dynptr_kern *, ptr, u32, offset, u3
> > > >         if (err)
> > > >                 return 0;
> > > >
> > > > -       if (bpf_dynptr_is_rdonly(ptr))
> > > > -               return 0;
> > > > +       type = bpf_dynptr_get_type(ptr);
> > > > +
> > > > +       switch (type) {
> > > > +       case BPF_DYNPTR_TYPE_LOCAL:
> > > > +       case BPF_DYNPTR_TYPE_RINGBUF:
> > > > +               if (bpf_dynptr_is_rdonly(ptr))
> > > > +                       return 0;
> > >
> > > will something break if we return ptr->data for read-only LOCAL/RINGBUF dynptr?
> >
> > There will be nothing guarding against direct writes into read-only
> > LOCAL/RINGBUF dynptrs if we return ptr->data. For skb type dynptrs,
> > it's guarded by the ptr->data return pointer being marked as
> > MEM_RDONLY in the verifier if the skb is non-writable.
> >
>
> Ah, so we won't add MEM_RDONLY for bpf_dynptr_data()'s returned
> PTR_TO_MEM if we know (statically) that dynptr is read-only?

I think you meant will, not won't? If so, then yes we only add
MEM_RDONLY for the returned data slice if we can pre-determine that
the dynptr is read-only, else bpf_dynptr_data() will return null.

>
> Ok, not a big deal, just something that we might want to improve in the future.

I'm curious to hear how you think this could be improved. If we're not
able to know statically whether the dynptr is read-only or writable,
then there's no way to enforce it in the verifier before the bpf
program runs. Or is there some way to do this?

>
> > >
> > > > +
> > > > +               data = ptr->data;
> > > > +               break;
> > > > +       case BPF_DYNPTR_TYPE_SKB:
> > > > +       {
> > > > +               struct sk_buff *skb = ptr->data;
> > > >
> > >
> > > [...]

  reply	other threads:[~2023-01-31  1:13 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-27 19:16 [PATCH v9 bpf-next 0/5] Add skb + xdp dynptrs Joanne Koong
2023-01-27 19:16 ` [PATCH v9 bpf-next 1/5] bpf: Allow "sk_buff" and "xdp_buff" as valid kfunc arg types Joanne Koong
2023-01-27 19:17 ` [PATCH v9 bpf-next 2/5] bpf: Allow initializing dynptrs in kfuncs Joanne Koong
2023-01-27 19:17 ` [PATCH v9 bpf-next 3/5] bpf: Add skb dynptrs Joanne Koong
2023-01-29 23:39   ` Alexei Starovoitov
2023-01-31  0:44     ` Joanne Koong
2023-01-31  5:36       ` Alexei Starovoitov
2023-01-31 17:54         ` Joanne Koong
2023-01-31 19:50           ` Alexei Starovoitov
2023-01-31 21:29             ` Joanne Koong
2023-02-08 21:46           ` Joanne Koong
2023-02-08 23:22             ` Alexei Starovoitov
2023-01-30 22:04   ` Martin KaFai Lau
2023-01-30 22:31     ` Alexei Starovoitov
2023-01-30 23:11       ` Martin KaFai Lau
2023-01-31  1:04       ` Andrii Nakryiko
2023-01-31  1:49         ` Martin KaFai Lau
2023-01-31  4:43           ` Andrii Nakryiko
2023-01-31  5:30             ` Alexei Starovoitov
2023-01-31 22:07               ` Martin KaFai Lau
2023-01-31 23:17               ` Joanne Koong
2023-02-01  0:46                 ` Alexei Starovoitov
2023-02-01  0:11               ` Andrii Nakryiko
2023-02-01  0:40                 ` Alexei Starovoitov
2023-02-02  1:21                   ` Andrii Nakryiko
2023-02-02 11:43                     ` Alexei Starovoitov
2023-02-03 21:37                       ` Andrii Nakryiko
2023-02-08  2:25                         ` Alexei Starovoitov
2023-02-08 20:13                           ` Joanne Koong
2023-02-09  0:39                             ` Andrii Nakryiko
2023-01-31 18:30         ` Joanne Koong
2023-01-31 19:58           ` Alexei Starovoitov
2023-01-31 20:47             ` Joanne Koong
2023-01-31 21:10               ` Alexei Starovoitov
2023-01-31 21:33                 ` Joanne Koong
2023-01-31 18:18     ` Joanne Koong
2023-01-31  0:48   ` Andrii Nakryiko
2023-01-31  0:55     ` Joanne Koong
2023-01-31  1:06       ` Andrii Nakryiko
2023-01-31  1:13         ` Joanne Koong [this message]
2023-01-31  1:19           ` Andrii Nakryiko
2023-01-27 19:17 ` [PATCH v9 bpf-next 4/5] bpf: Add xdp dynptrs Joanne Koong
2023-01-27 19:17 ` [PATCH v9 bpf-next 5/5] selftests/bpf: tests for using dynptrs to parse skb and xdp buffers Joanne Koong
2023-01-31  0:49   ` Andrii Nakryiko

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='CAJnrk1Y61=Qc3fndvAPghgu8+iNwzU2wvtwsi2jk_NeEwdP9aw@mail.gmail.com' \
    --to=joannelkoong@gmail.com \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@fb.com \
    --cc=martin.lau@kernel.org \
    --cc=memxor@gmail.com \
    --cc=netdev@vger.kernel.org \
    /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).