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 04/11] bpf: Add basic bpf_rb_{root,node} support
Date: Fri, 10 Feb 2023 15:18:17 +0100 [thread overview]
Message-ID: <20230210141817.idcbotzn4uof4yfu@apollo> (raw)
In-Reply-To: <20230209174144.3280955-5-davemarchevsky@fb.com>
On Thu, Feb 09, 2023 at 06:41:37PM CET, Dave Marchevsky wrote:
> This patch adds special BPF_RB_{ROOT,NODE} btf_field_types similar to
> BPF_LIST_{HEAD,NODE}, adds the necessary plumbing to detect the new
> types, and adds bpf_rb_root_free function for freeing bpf_rb_root in
> map_values.
>
> structs bpf_rb_root and bpf_rb_node are opaque types meant to
> obscure structs rb_root_cached rb_node, respectively.
>
> btf_struct_access will prevent BPF programs from touching these special
> fields automatically now that they're recognized.
>
> btf_check_and_fixup_fields now groups list_head and rb_root together as
> "graph root" fields and {list,rb}_node as "graph node", and does same
> ownership cycle checking as before. Note that this function does _not_
> prevent ownership type mixups (e.g. rb_root owning list_node) - that's
> handled by btf_parse_graph_root.
>
> After this patch, a bpf program can have a struct bpf_rb_root in a
> map_value, but not add anything to nor do anything useful with it.
>
> Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
> ---
> [...]
> +#define GRAPH_ROOT_MASK (BPF_LIST_HEAD | BPF_RB_ROOT)
> +#define GRAPH_NODE_MASK (BPF_LIST_NODE | BPF_RB_NODE)
> +
> int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec)
> {
> int i;
>
> - /* There are two owning types, kptr_ref and bpf_list_head. The former
> - * only supports storing kernel types, which can never store references
> - * to program allocated local types, atleast not yet. Hence we only need
> - * to ensure that bpf_list_head ownership does not form cycles.
> + /* There are three types that signify ownership of some other type:
> + * kptr_ref, bpf_list_head, bpf_rb_root.
> + * kptr_ref only supports storing kernel types, which can't store
> + * references to program allocated local types.
> + *
> + * Hence we only need to ensure that bpf_{list_head,rb_root} ownership
> + * does not form cycles.
> */
> - if (IS_ERR_OR_NULL(rec) || !(rec->field_mask & BPF_LIST_HEAD))
> + if (IS_ERR_OR_NULL(rec) || !(rec->field_mask & GRAPH_ROOT_MASK))
> return 0;
> for (i = 0; i < rec->cnt; i++) {
> struct btf_struct_meta *meta;
> u32 btf_id;
>
> - if (!(rec->fields[i].type & BPF_LIST_HEAD))
> + if (!(rec->fields[i].type & GRAPH_ROOT_MASK))
> continue;
> btf_id = rec->fields[i].graph_root.value_btf_id;
> meta = btf_find_struct_meta(btf, btf_id);
> @@ -3762,39 +3803,47 @@ int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec)
> return -EFAULT;
> rec->fields[i].graph_root.value_rec = meta->record;
>
> - if (!(rec->field_mask & BPF_LIST_NODE))
> + /* We need to set value_rec for all root types, but no need
> + * to check ownership cycle for a type unless it's also a
> + * node type.
> + */
> + if (!(rec->field_mask & GRAPH_NODE_MASK))
> continue;
>
> /* We need to ensure ownership acyclicity among all types. The
> * proper way to do it would be to topologically sort all BTF
> * IDs based on the ownership edges, since there can be multiple
> - * bpf_list_head in a type. Instead, we use the following
> - * reasoning:
> + * bpf_{list_head,rb_node} in a type. Instead, we use the
> + * following resaoning:
> *
> * - A type can only be owned by another type in user BTF if it
> - * has a bpf_list_node.
> + * has a bpf_{list,rb}_node. Let's call these node types.
> * - A type can only _own_ another type in user BTF if it has a
> - * bpf_list_head.
> + * bpf_{list_head,rb_root}. Let's call these root types.
> *
> - * We ensure that if a type has both bpf_list_head and
> - * bpf_list_node, its element types cannot be owning types.
> + * We ensure that if a type is both a root and node, its
> + * element types cannot be root types.
> *
> * To ensure acyclicity:
> *
> - * When A only has bpf_list_head, ownership chain can be:
> + * When A is an root type but not a node, its ownership
> + * chain can be:
> * A -> B -> C
> * Where:
> - * - B has both bpf_list_head and bpf_list_node.
> - * - C only has bpf_list_node.
> + * - A is an root, e.g. has bpf_rb_root.
> + * - B is both a root and node, e.g. has bpf_rb_node and
> + * bpf_list_head.
> + * - C is only an root, e.g. has bpf_list_node
> *
> - * When A has both bpf_list_head and bpf_list_node, some other
> - * type already owns it in the BTF domain, hence it can not own
> - * another owning type through any of the bpf_list_head edges.
> + * When A is both a root and node, some other type already
> + * owns it in the BTF domain, hence it can not own
> + * another root type through any of the ownership edges.
> * A -> B
> * Where:
> - * - B only has bpf_list_node.
> + * - A is both an root and node.
> + * - B is only an node.
> */
> - if (meta->record->field_mask & BPF_LIST_HEAD)
> + if (meta->record->field_mask & GRAPH_ROOT_MASK)
> return -ELOOP;
While you are at it, can you include BTF selftests (similar to what linked list
tests are doing in test_btf) to ensure all of this being correctly rejected for
rbtree and mixed rbtree + list cases?
next prev parent reply other threads:[~2023-02-10 14:18 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 [this message]
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
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=20230210141817.idcbotzn4uof4yfu@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