Thread (40 messages) flat view 40 messages, 4 authors, 2020-07-30

Re: [PATCH v8 bpf-next 06/13] bpf: Factor btf_struct_access function

From: Jiri Olsa <hidden>
Date: 2020-07-29 15:59:50
Also in: bpf

On Tue, Jul 28, 2020 at 04:27:21PM -0700, Andrii Nakryiko wrote:

SNIP
quoted
 kernel/bpf/btf.c | 73 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 60 insertions(+), 13 deletions(-)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 841be6c49f11..1ab5fd5bf992 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3873,16 +3873,22 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
        return true;
 }

-int btf_struct_access(struct bpf_verifier_log *log,
-                     const struct btf_type *t, int off, int size,
-                     enum bpf_access_type atype,
-                     u32 *next_btf_id)
+enum walk_return {
+       /* < 0 error */
+       walk_scalar = 0,
+       walk_ptr,
+       walk_struct,
+};
let's keep enum values in ALL_CAPS? walk_return is also a bit generic,
maybe something like bpf_struct_walk_result?
ok
quoted
+
+static int btf_struct_walk(struct bpf_verifier_log *log,
+                          const struct btf_type *t, int off, int size,
+                          u32 *rid)
 {
        u32 i, moff, mtrue_end, msize = 0, total_nelems = 0;
        const struct btf_type *mtype, *elem_type = NULL;
        const struct btf_member *member;
        const char *tname, *mname;
-       u32 vlen;
+       u32 vlen, elem_id, mid;

 again:
        tname = __btf_name_by_offset(btf_vmlinux, t->name_off);
@@ -3924,8 +3930,7 @@ int btf_struct_access(struct bpf_verifier_log *log,
                        goto error;

                off = (off - moff) % elem_type->size;
-               return btf_struct_access(log, elem_type, off, size, atype,
-                                        next_btf_id);
+               return btf_struct_walk(log, elem_type, off, size, rid);
oh, btw, this is a recursion in the kernel, let's fix that? I think it
could easily be just `goto again` here?
probably, I'll put it into separate change then

SNIP
quoted
@@ -4066,11 +4080,10 @@ int btf_struct_access(struct bpf_verifier_log *log,
                                        mname, moff, tname, off, size);
                                return -EACCES;
                        }
-
                        stype = btf_type_skip_modifiers(btf_vmlinux, mtype->type, &id);
                        if (btf_type_is_struct(stype)) {
-                               *next_btf_id = id;
-                               return PTR_TO_BTF_ID;
+                               *rid = id;
nit: rid is a very opaque name, I find next_btf_id more appropriate
(even if it's meaning changes depending on walk_ptr vs walk_struct.
ok, will change

SNIP
quoted
+int btf_struct_access(struct bpf_verifier_log *log,
+                     const struct btf_type *t, int off, int size,
+                     enum bpf_access_type atype __maybe_unused,
+                     u32 *next_btf_id)
+{
+       int err;
+       u32 id;
+
+       do {
+               err = btf_struct_walk(log, t, off, size, &id);
+               if (err < 0)
+                       return err;
+
+               /* We found the pointer or scalar on t+off,
+                * we're done.
+                */
+               if (err == walk_ptr) {
+                       *next_btf_id = id;
+                       return PTR_TO_BTF_ID;
+               }
+               if (err == walk_scalar)
+                       return SCALAR_VALUE;
+
+               /* We found nested struct, so continue the search
+                * by diving in it. At this point the offset is
+                * aligned with the new type, so set it to 0.
+                */
+               t = btf_type_by_id(btf_vmlinux, id);
+               off = 0;
It's very easy to miss that this case corresponds to walk_struct here.
If someone in the future adds a 4th special value, it will be too easy
to forget to update this piece of logic. So when dealing with enums, I
generally prefer this approach:

switch (err) {
case walk_ptr:
    ...
case walk_scalar:
    ...
case walk_struct:
    ...
default: /* complain loudly here */
}

WDYT?
right, I like it, make sense for future.. will change

thanks,
jirka
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help