From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
To: Dave Marchevsky <davemarchevsky@fb.com>
Cc: bpf@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Kernel Team <kernel-team@fb.com>, Tejun Heo <tj@kernel.org>
Subject: Re: [PATCH v4 bpf-next 08/11] bpf: Special verifier handling for bpf_rbtree_{remove, first}
Date: Fri, 10 Feb 2023 14:55:41 +0100 [thread overview]
Message-ID: <20230210135541.xtwn6wzng7mspgrm@apollo> (raw)
In-Reply-To: <20230209174144.3280955-9-davemarchevsky@fb.com>
On Thu, Feb 09, 2023 at 06:41:41PM CET, Dave Marchevsky wrote:
> Newly-added bpf_rbtree_{remove,first} kfuncs have some special properties
> that require handling in the verifier:
>
> * both bpf_rbtree_remove and bpf_rbtree_first return the type containing
> the bpf_rb_node field, with the offset set to that field's offset,
> instead of a struct bpf_rb_node *
> * mark_reg_graph_node helper added in previous patch generalizes
> this logic, use it
>
> * bpf_rbtree_remove's node input is a node that's been inserted
> in the tree - a non-owning reference.
>
> * bpf_rbtree_remove must invalidate non-owning references in order to
> avoid aliasing issue. Use previously-added
> invalidate_non_owning_refs helper to mark this function as a
> non-owning ref invalidation point.
>
> * Unlike other functions, which convert one of their input arg regs to
> non-owning reference, bpf_rbtree_first takes no arguments and just
> returns a non-owning reference (possibly null)
> * For now verifier logic for this is special-cased instead of
> adding new kfunc flag.
>
> This patch, along with the previous one, complete special verifier
> handling for all rbtree API functions added in this series.
>
I think there are two issues with the current approach. The fundamental
assumption with non-owning references is that it is part of the collection. So
bpf_rbtree_{add,first}, bpf_list_push_{front,back} will create them, as no node
is being removed from collection. Marking bpf_rbtree_remove (and in the future
bpf_list_del) as invalidation points is also right, since once a node has been
removed it is going to be unclear whether existing non-owning references have
the same value, and thus the property of 'part of the collection' will be
broken.
The first issue relates to usability. If I have non-owning references to nodes
inserted into both a list and an rbtree, bpf_rbtree_remove should only
invalidate the ones that are part of the particular rbtree. It should have no
effect on others. Likewise for the bpf_list_del operation in the future.
Therefore, we need to track the collection identity associated with each
non-owning reference, then only invalidate non-owning references associated with
the same collection.
The case of bpf_spin_unlock is different, which should invalidate all non-owning
references.
The second issue is more serious. By not tracking the collection identity, we
will currently allow a non-owning reference for an object inserted into a list
to be passed to bpf_rbtree_remove, because the verifier cannot discern between
'inserted into rbtree' vs 'inserted into list'. For it, both are currently
equivalent in the verifier state. An object is allowed to have both
bpf_list_node and bpf_rb_node, but it can only be part of one collection at a
time (because of no shared ownership).
struct obj {
bpf_list_node ln;
bpf_rb_node rn;
};
bpf_list_push_front(head, &obj->ln); // node is non-own-ref
bpf_rbtree_remove(&obj->rn); // should not work, but does
So some notion of a collection identity needs to be constructed, the amount of
data which needs to be remembered in each non-owning reference's register state
depends on our requirements.
The first sanity check is that bpf_rbtree_remove only removes something in an
rbtree, so probably an enum member indicating whether collection is a list or
rbtree. To ensure proper scoped invalidation, we will unfortunately need more
than just the reg->id of the reg holding the graph root, since map values of
different maps may have same id (0). Hence, we need id and ptr similar to the
active lock case for proper matching. Even this won't be enough, as there can be
multiple list or rbtree roots in a particular memory region, therefore the
offset also needs to be part of the collection identity.
So it seems it will amount to:
struct bpf_collection_id {
enum bpf_collection_type type;
void *ptr;
int id;
int off;
};
There might be ways to optimize the memory footprint of this struct, but I'm
just trying to state why we'll need to include all four, so we don't miss out on
a corner case again.
> Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
> ---
> [...]
next prev parent reply other threads:[~2023-02-10 13:55 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-09 17:41 [PATCH v4 bpf-next 00/11] BPF rbtree next-gen datastructure Dave Marchevsky
2023-02-09 17:41 ` [PATCH v4 bpf-next 01/11] bpf: Migrate release_on_unlock logic to non-owning ref semantics Dave Marchevsky
2023-02-10 13:24 ` Kumar Kartikeya Dwivedi
2023-02-10 17:13 ` Alexei Starovoitov
2023-02-09 17:41 ` [PATCH v4 bpf-next 02/11] bpf: Improve bpf_reg_state space usage for non-owning ref lock Dave Marchevsky
2023-02-09 17:41 ` [PATCH v4 bpf-next 03/11] selftests/bpf: Update linked_list tests for non-owning ref semantics Dave Marchevsky
2023-02-09 17:41 ` [PATCH v4 bpf-next 04/11] bpf: Add basic bpf_rb_{root,node} support Dave Marchevsky
2023-02-10 14:18 ` Kumar Kartikeya Dwivedi
2023-02-09 17:41 ` [PATCH v4 bpf-next 05/11] bpf: Add bpf_rbtree_{add,remove,first} kfuncs Dave Marchevsky
2023-02-09 17:41 ` [PATCH v4 bpf-next 06/11] bpf: Add support for bpf_rb_root and bpf_rb_node in kfunc args Dave Marchevsky
2023-02-09 17:41 ` [PATCH v4 bpf-next 07/11] bpf: Add callback validation to kfunc verifier logic Dave Marchevsky
2023-02-09 17:41 ` [PATCH v4 bpf-next 08/11] bpf: Special verifier handling for bpf_rbtree_{remove, first} Dave Marchevsky
2023-02-10 3:11 ` Alexei Starovoitov
2023-02-10 8:22 ` Dave Marchevsky
2023-02-10 17:30 ` Alexei Starovoitov
2023-02-10 14:15 ` Kumar Kartikeya Dwivedi
2023-02-10 13:55 ` Kumar Kartikeya Dwivedi [this message]
2023-02-10 17:21 ` Alexei Starovoitov
2023-02-10 18:03 ` Kumar Kartikeya Dwivedi
2023-02-10 18:58 ` Alexei Starovoitov
2023-02-10 19:38 ` Kumar Kartikeya Dwivedi
2023-02-10 20:01 ` Alexei Starovoitov
2023-02-10 19:01 ` Dave Marchevsky
2023-02-09 17:41 ` [PATCH v4 bpf-next 09/11] bpf: Add bpf_rbtree_{add,remove,first} decls to bpf_experimental.h Dave Marchevsky
2023-02-09 17:41 ` [PATCH v4 bpf-next 10/11] selftests/bpf: Add rbtree selftests Dave Marchevsky
2023-02-10 2:52 ` Alexei Starovoitov
2023-02-09 17:41 ` [PATCH v4 bpf-next 11/11] bpf, documentation: Add graph documentation for non-owning refs Dave Marchevsky
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=20230210135541.xtwn6wzng7mspgrm@apollo \
--to=memxor@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davemarchevsky@fb.com \
--cc=kernel-team@fb.com \
--cc=tj@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