Netdev Archive mirror
 help / color / mirror / Atom feed
From: Amery Hung <ameryhung@gmail.com>
To: netdev@vger.kernel.org
Cc: bpf@vger.kernel.org, yangpeihao@sjtu.edu.cn,
	daniel@iogearbox.net, andrii@kernel.org, martin.lau@kernel.org,
	sinquersw@gmail.com, toke@redhat.com, jhs@mojatatu.com,
	jiri@resnulli.us, sdf@google.com, xiyou.wangcong@gmail.com,
	yepeilin.cs@gmail.com, ameryhung@gmail.com
Subject: [RFC PATCH v8 06/20] bpf: Recognize kernel types as graph values
Date: Fri, 10 May 2024 19:23:58 +0000	[thread overview]
Message-ID: <20240510192412.3297104-7-amery.hung@bytedance.com> (raw)
In-Reply-To: <20240510192412.3297104-1-amery.hung@bytedance.com>

This patch teaches bpf to recognize graphs that contain kernel objects
as graph values. BPF programs can use a new BTF declaration tag
"contain_kptr" to signal that the value of a graph will be a kernel type.
"contains_kptr" follows the same annotation format as "contains".

For the implementation, when the value is a kernel type, we uses kernel
BTF for node and roots as well so that we don't need to match the same
type in different BTF. Since graph values can be kernel types, we can
no longer make the assumption that the BTF is from programs when finding
and parsing graph nodes and roots. Therefore, we record the BTF of a
node in btf_field_info and use it later.

No kernel object can be added to bpf graphs yet. In later patches,
we will teach the verifier to allow moving kptr in and out collections.

Signed-off-by: Amery Hung <amery.hung@bytedance.com>
---
 include/linux/btf.h                           |  4 +-
 kernel/bpf/btf.c                              | 49 ++++++++++++-------
 kernel/bpf/syscall.c                          |  2 +-
 .../testing/selftests/bpf/bpf_experimental.h  |  1 +
 4 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/include/linux/btf.h b/include/linux/btf.h
index f9e56fd12a9f..2579b8a51172 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -219,7 +219,7 @@ bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
 			   u32 expected_offset, u32 expected_size);
 struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type *t,
 				    u32 field_mask, u32 value_size);
-int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec);
+int btf_check_and_fixup_fields(struct btf_record *rec);
 bool btf_type_is_void(const struct btf_type *t);
 s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind);
 s32 bpf_find_btf_id(const char *name, u32 kind, struct btf **btf_p);
@@ -569,7 +569,7 @@ static inline int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dt
 {
 	return 0;
 }
-static inline struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id)
+static inline struct btf_struct_meta *btf_find_struct_meta(u32 btf_id)
 {
 	return NULL;
 }
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 5ee6ccc2fab7..37fb6143da79 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3296,6 +3296,7 @@ struct btf_field_info {
 		struct {
 			const char *node_name;
 			u32 value_btf_id;
+			const struct btf *btf;
 		} graph_root;
 	};
 };
@@ -3405,7 +3406,9 @@ btf_find_graph_root(const struct btf *btf, const struct btf_type *pt,
 		    enum btf_field_type head_type)
 {
 	const char *node_field_name;
+	bool value_is_kptr = false;
 	const char *value_type;
+	struct btf *kptr_btf;
 	s32 id;
 
 	if (!__btf_type_is_struct(t))
@@ -3413,15 +3416,26 @@ btf_find_graph_root(const struct btf *btf, const struct btf_type *pt,
 	if (t->size != sz)
 		return BTF_FIELD_IGNORE;
 	value_type = btf_find_decl_tag_value(btf, pt, comp_idx, "contains:");
-	if (IS_ERR(value_type))
-		return -EINVAL;
+	if (!IS_ERR(value_type))
+		goto found;
+	value_type = btf_find_decl_tag_value(btf, pt, comp_idx, "contains_kptr:");
+	if (!IS_ERR(value_type)) {
+		value_is_kptr = true;
+		goto found;
+	}
+	return -EINVAL;
+found:
 	node_field_name = strstr(value_type, ":");
 	if (!node_field_name)
 		return -EINVAL;
 	value_type = kstrndup(value_type, node_field_name - value_type, GFP_KERNEL | __GFP_NOWARN);
 	if (!value_type)
 		return -ENOMEM;
-	id = btf_find_by_name_kind(btf, value_type, BTF_KIND_STRUCT);
+	if (value_is_kptr)
+		id = bpf_find_btf_id(value_type, BTF_KIND_STRUCT, &kptr_btf);
+	else
+		id = btf_find_by_name_kind(btf, value_type, BTF_KIND_STRUCT);
+
 	kfree(value_type);
 	if (id < 0)
 		return id;
@@ -3431,6 +3445,7 @@ btf_find_graph_root(const struct btf *btf, const struct btf_type *pt,
 	info->type = head_type;
 	info->off = off;
 	info->graph_root.value_btf_id = id;
+	info->graph_root.btf = value_is_kptr ? kptr_btf : btf;
 	info->graph_root.node_name = node_field_name;
 	return BTF_FIELD_FOUND;
 }
@@ -3722,13 +3737,13 @@ static int btf_parse_kptr(const struct btf *btf, struct btf_field *field,
 	return ret;
 }
 
-static int btf_parse_graph_root(const struct btf *btf,
-				struct btf_field *field,
+static int btf_parse_graph_root(struct btf_field *field,
 				struct btf_field_info *info,
 				const char *node_type_name,
 				size_t node_type_align)
 {
 	const struct btf_type *t, *n = NULL;
+	const struct btf *btf = info->graph_root.btf;
 	const struct btf_member *member;
 	u32 offset;
 	int i;
@@ -3766,18 +3781,16 @@ static int btf_parse_graph_root(const struct btf *btf,
 	return 0;
 }
 
-static int btf_parse_list_head(const struct btf *btf, struct btf_field *field,
-			       struct btf_field_info *info)
+static int btf_parse_list_head(struct btf_field *field, struct btf_field_info *info)
 {
-	return btf_parse_graph_root(btf, field, info, "bpf_list_node",
-					    __alignof__(struct bpf_list_node));
+	return btf_parse_graph_root(field, info, "bpf_list_node",
+				    __alignof__(struct bpf_list_node));
 }
 
-static int btf_parse_rb_root(const struct btf *btf, struct btf_field *field,
-			     struct btf_field_info *info)
+static int btf_parse_rb_root(struct btf_field *field, struct btf_field_info *info)
 {
-	return btf_parse_graph_root(btf, field, info, "bpf_rb_node",
-					    __alignof__(struct bpf_rb_node));
+	return btf_parse_graph_root(field, info, "bpf_rb_node",
+				    __alignof__(struct bpf_rb_node));
 }
 
 static int btf_field_cmp(const void *_a, const void *_b, const void *priv)
@@ -3859,12 +3872,12 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
 				goto end;
 			break;
 		case BPF_LIST_HEAD:
-			ret = btf_parse_list_head(btf, &rec->fields[i], &info_arr[i]);
+			ret = btf_parse_list_head(&rec->fields[i], &info_arr[i]);
 			if (ret < 0)
 				goto end;
 			break;
 		case BPF_RB_ROOT:
-			ret = btf_parse_rb_root(btf, &rec->fields[i], &info_arr[i]);
+			ret = btf_parse_rb_root(&rec->fields[i], &info_arr[i]);
 			if (ret < 0)
 				goto end;
 			break;
@@ -3901,7 +3914,7 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
 	return ERR_PTR(ret);
 }
 
-int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec)
+int btf_check_and_fixup_fields(struct btf_record *rec)
 {
 	int i;
 
@@ -3917,11 +3930,13 @@ int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec)
 		return 0;
 	for (i = 0; i < rec->cnt; i++) {
 		struct btf_struct_meta *meta;
+		struct btf *btf;
 		u32 btf_id;
 
 		if (!(rec->fields[i].type & BPF_GRAPH_ROOT))
 			continue;
 		btf_id = rec->fields[i].graph_root.value_btf_id;
+		btf = rec->fields[i].graph_root.btf;
 		meta = btf_find_struct_meta(btf, btf_id);
 		if (!meta)
 			return -EFAULT;
@@ -5630,7 +5645,7 @@ static struct btf *btf_parse(const union bpf_attr *attr, bpfptr_t uattr, u32 uat
 		int i;
 
 		for (i = 0; i < struct_meta_tab->cnt; i++) {
-			err = btf_check_and_fixup_fields(btf, struct_meta_tab->types[i].record);
+			err = btf_check_and_fixup_fields(struct_meta_tab->types[i].record);
 			if (err < 0)
 				goto errout_meta;
 		}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index e44c276e8617..9e93d48efe19 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1157,7 +1157,7 @@ static int map_check_btf(struct bpf_map *map, struct bpf_token *token,
 		}
 	}
 
-	ret = btf_check_and_fixup_fields(btf, map->record);
+	ret = btf_check_and_fixup_fields(map->record);
 	if (ret < 0)
 		goto free_map_tab;
 
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index a5b9df38c162..a4da75df819c 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -7,6 +7,7 @@
 #include <bpf/bpf_core_read.h>
 
 #define __contains(name, node) __attribute__((btf_decl_tag("contains:" #name ":" #node)))
+#define __contains_kptr(name, node) __attribute__((btf_decl_tag("contains_kptr:" #name ":" #node)))
 
 /* Description
  *	Allocates an object of the type represented by 'local_type_id' in
-- 
2.20.1


  parent reply	other threads:[~2024-05-10 19:24 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-10 19:23 [RFC PATCH v8 00/20] bpf qdisc Amery Hung
2024-05-10 19:23 ` [RFC PATCH v8 01/20] bpf: Support passing referenced kptr to struct_ops programs Amery Hung
2024-05-16 23:59   ` Kumar Kartikeya Dwivedi
2024-05-17  0:17     ` Amery Hung
2024-05-17  0:23       ` Kumar Kartikeya Dwivedi
2024-05-17  1:22         ` Amery Hung
2024-05-17  2:00           ` Kumar Kartikeya Dwivedi
2024-05-10 19:23 ` [RFC PATCH v8 02/20] selftests/bpf: Test referenced kptr arguments of " Amery Hung
2024-05-10 21:33   ` Kui-Feng Lee
2024-05-10 22:16     ` Amery Hung
2024-05-16 23:14       ` Amery Hung
2024-05-16 23:43         ` Martin KaFai Lau
2024-05-17  0:54           ` Amery Hung
2024-05-17  1:07             ` Martin KaFai Lau
2024-05-10 19:23 ` [RFC PATCH v8 03/20] bpf: Allow struct_ops prog to return referenced kptr Amery Hung
2024-05-17  2:06   ` Amery Hung
2024-05-17  5:30     ` Martin KaFai Lau
2024-05-10 19:23 ` [RFC PATCH v8 04/20] selftests/bpf: Test returning kptr from struct_ops programs Amery Hung
2024-05-10 19:23 ` [RFC PATCH v8 05/20] bpf: Generate btf_struct_metas for kernel BTF Amery Hung
2024-05-10 19:23 ` Amery Hung [this message]
2024-05-10 19:23 ` [RFC PATCH v8 07/20] bpf: Allow adding kernel objects to collections Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 08/20] selftests/bpf: Test adding kernel object to bpf graph Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 09/20] bpf: Find special BTF fields in union Amery Hung
2024-05-16 23:37   ` Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 10/20] bpf: Introduce exclusive-ownership list and rbtree nodes Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 11/20] bpf: Allow adding exclusive nodes to bpf list and rbtree Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 12/20] selftests/bpf: Modify linked_list tests to work with macro-ified removes Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 13/20] bpf: net_sched: Support implementation of Qdisc_ops in bpf Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 14/20] bpf: net_sched: Add bpf qdisc kfuncs Amery Hung
2024-05-22 23:55   ` Martin KaFai Lau
2024-05-23  1:06     ` Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 15/20] bpf: net_sched: Allow more optional methods in Qdisc_ops Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 16/20] libbpf: Support creating and destroying qdisc Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 17/20] selftests: Add a basic fifo qdisc test Amery Hung
2024-05-21  3:15   ` Stanislav Fomichev
2024-05-21 15:03     ` Amery Hung
2024-05-21 17:57       ` Stanislav Fomichev
2024-05-10 19:24 ` [RFC PATCH v8 18/20] selftests: Add a bpf fq qdisc to selftest Amery Hung
2024-05-24  6:24   ` Martin KaFai Lau
2024-05-24  7:40     ` Toke Høiland-Jørgensen
2024-05-26  1:08       ` Martin KaFai Lau
2024-05-27 10:09         ` Toke Høiland-Jørgensen
2024-05-24 19:33     ` Alexei Starovoitov
2024-05-24 20:54       ` Martin KaFai Lau
2024-05-10 19:24 ` [RFC PATCH v8 19/20] selftests: Add a bpf netem " Amery Hung
2024-05-10 19:24 ` [RFC PATCH v8 20/20] selftests: Add a prio bpf qdisc Amery Hung

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=20240510192412.3297104-7-amery.hung@bytedance.com \
    --to=ameryhung@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=jhs@mojatatu.com \
    --cc=jiri@resnulli.us \
    --cc=martin.lau@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=sdf@google.com \
    --cc=sinquersw@gmail.com \
    --cc=toke@redhat.com \
    --cc=xiyou.wangcong@gmail.com \
    --cc=yangpeihao@sjtu.edu.cn \
    --cc=yepeilin.cs@gmail.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 read-only IMAP folder(s) and NNTP newsgroup(s).