From: Kui-Feng Lee <thinker.li@gmail.com>
To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev,
song@kernel.org, kernel-team@meta.com, andrii@kernel.org
Cc: sinquersw@gmail.com, kuifeng@meta.com,
Kui-Feng Lee <thinker.li@gmail.com>
Subject: [PATCH bpf-next v3 3/7] bpf: create repeated fields for arrays.
Date: Wed, 1 May 2024 13:47:25 -0700 [thread overview]
Message-ID: <20240501204729.484085-4-thinker.li@gmail.com> (raw)
In-Reply-To: <20240501204729.484085-1-thinker.li@gmail.com>
The verifier uses field information for certain special types, such as
kptr, rbtree root, and list head. These types are treated
differently. However, we did not previously support these types in
arrays. This update examines arrays and duplicates field information the
same number of times as the length of the array if the element type is one
of the special types.
Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
---
kernel/bpf/btf.c | 81 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 76 insertions(+), 5 deletions(-)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index d4c3342e2027..4a78cd28fab0 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3493,6 +3493,41 @@ static int btf_get_field_type(const char *name, u32 field_mask, u32 *seen_mask,
#undef field_mask_test_name
+/* Repeat a field for a specified number of times.
+ *
+ * Copy and repeat a field for repeat_cnt
+ * times. The field is repeated by adding the offset of each field
+ * with
+ * (i + 1) * elem_size
+ * where i is the repeat index and elem_size is the size of the element.
+ */
+static int btf_repeat_field(struct btf_field_info *info, u32 field,
+ u32 repeat_cnt, u32 elem_size)
+{
+ u32 i;
+ u32 cur;
+
+ /* Ensure not repeating fields that should not be repeated. */
+ switch (info[field].type) {
+ case BPF_KPTR_UNREF:
+ case BPF_KPTR_REF:
+ case BPF_KPTR_PERCPU:
+ case BPF_LIST_HEAD:
+ case BPF_RB_ROOT:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cur = field + 1;
+ for (i = 0; i < repeat_cnt; i++) {
+ memcpy(&info[cur], &info[field], sizeof(info[0]));
+ info[cur++].off += (i + 1) * elem_size;
+ }
+
+ return 0;
+}
+
static int btf_find_struct_field(const struct btf *btf,
const struct btf_type *t, u32 field_mask,
struct btf_field_info *info, int info_cnt)
@@ -3505,6 +3540,19 @@ static int btf_find_struct_field(const struct btf *btf,
for_each_member(i, t, member) {
const struct btf_type *member_type = btf_type_by_id(btf,
member->type);
+ const struct btf_array *array;
+ u32 j, nelems = 1;
+
+ /* Walk into array types to find the element type and the
+ * number of elements in the (flattened) array.
+ */
+ for (j = 0; j < MAX_RESOLVE_DEPTH && btf_type_is_array(member_type); j++) {
+ array = btf_array(member_type);
+ nelems *= array->nelems;
+ member_type = btf_type_by_id(btf, array->type);
+ }
+ if (nelems == 0)
+ continue;
field_type = btf_get_field_type(__btf_name_by_offset(btf, member_type->name_off),
field_mask, &seen_mask, &align, &sz);
@@ -3556,9 +3604,14 @@ static int btf_find_struct_field(const struct btf *btf,
if (ret == BTF_FIELD_IGNORE)
continue;
- if (idx >= info_cnt)
+ if (idx + nelems > info_cnt)
return -E2BIG;
- ++idx;
+ if (nelems > 1) {
+ ret = btf_repeat_field(info, idx, nelems - 1, sz);
+ if (ret < 0)
+ return ret;
+ }
+ idx += nelems;
}
return idx;
}
@@ -3575,6 +3628,19 @@ static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
for_each_vsi(i, t, vsi) {
const struct btf_type *var = btf_type_by_id(btf, vsi->type);
const struct btf_type *var_type = btf_type_by_id(btf, var->type);
+ const struct btf_array *array;
+ u32 j, nelems = 1;
+
+ /* Walk into array types to find the element type and the
+ * number of elements in the (flattened) array.
+ */
+ for (j = 0; j < MAX_RESOLVE_DEPTH && btf_type_is_array(var_type); j++) {
+ array = btf_array(var_type);
+ nelems *= array->nelems;
+ var_type = btf_type_by_id(btf, array->type);
+ }
+ if (nelems == 0)
+ continue;
field_type = btf_get_field_type(__btf_name_by_offset(btf, var_type->name_off),
field_mask, &seen_mask, &align, &sz);
@@ -3584,7 +3650,7 @@ static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
return field_type;
off = vsi->offset;
- if (vsi->size != sz)
+ if (vsi->size != sz * nelems)
continue;
if (off % align)
continue;
@@ -3624,9 +3690,14 @@ static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
if (ret == BTF_FIELD_IGNORE)
continue;
- if (idx >= info_cnt)
+ if (idx + nelems > info_cnt)
return -E2BIG;
- ++idx;
+ if (nelems > 1) {
+ ret = btf_repeat_field(info, idx, nelems - 1, sz);
+ if (ret < 0)
+ return ret;
+ }
+ idx += nelems;
}
return idx;
}
--
2.34.1
next prev parent reply other threads:[~2024-05-01 20:47 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-01 20:47 [PATCH bpf-next v3 0/7] Enable BPF programs to declare arrays of kptr, bpf_rb_root, and bpf_list_head Kui-Feng Lee
2024-05-01 20:47 ` [PATCH bpf-next v3 1/7] bpf: Remove unnecessary checks on the offset of btf_field Kui-Feng Lee
2024-05-01 20:47 ` [PATCH bpf-next v3 2/7] bpf: Remove unnecessary call to btf_field_type_size() Kui-Feng Lee
2024-05-01 20:47 ` Kui-Feng Lee [this message]
2024-05-02 17:20 ` [PATCH bpf-next v3 3/7] bpf: create repeated fields for arrays Eduard Zingerman
2024-05-03 18:02 ` Kui-Feng Lee
2024-05-03 18:10 ` Eduard Zingerman
2024-05-01 20:47 ` [PATCH bpf-next v3 4/7] bpf: look into the types of the fields of a struct type recursively Kui-Feng Lee
2024-05-02 19:34 ` Eduard Zingerman
2024-05-03 18:07 ` Kui-Feng Lee
2024-05-01 20:47 ` [PATCH bpf-next v3 5/7] selftests/bpf: Test kptr arrays and kptrs in nested struct fields Kui-Feng Lee
2024-05-01 20:47 ` [PATCH bpf-next v3 6/7] selftests/bpf: Test global bpf_rb_root arrays and fields in nested struct types Kui-Feng Lee
2024-05-01 20:47 ` [PATCH bpf-next v3 7/7] selftests/bpf: Test global bpf_list_head arrays Kui-Feng Lee
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=20240501204729.484085-4-thinker.li@gmail.com \
--to=thinker.li@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=kernel-team@meta.com \
--cc=kuifeng@meta.com \
--cc=martin.lau@linux.dev \
--cc=sinquersw@gmail.com \
--cc=song@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).