Move sleepable verification code to btf_id_allow_sleepable function.
It will be used in following changes.

Adding code to retrieve type's name instead of passing it from
bpf_check_attach_target function, because this function will be
called from another place in following changes and it's easier
to retrieve the name directly in here.

Signed-off-by: Jiri Olsa <[email protected]>
---
 include/linux/bpf_verifier.h |  3 ++
 kernel/bpf/verifier.c        | 79 +++++++++++++++++++++---------------
 2 files changed, 50 insertions(+), 32 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 090aa26d1c98..186726fcf52a 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -932,6 +932,9 @@ static inline void bpf_trampoline_unpack_key(u64 key, u32 
*obj_id, u32 *btf_id)
                *btf_id = key & 0x7FFFFFFF;
 }
 
+int btf_id_allow_sleepable(u32 btf_id, unsigned long addr, const struct 
bpf_prog *prog,
+                          const struct btf *btf);
+
 int bpf_check_attach_target(struct bpf_verifier_log *log,
                            const struct bpf_prog *prog,
                            const struct bpf_prog *tgt_prog,
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index b29cd244ee27..7085688eb719 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -25059,6 +25059,52 @@ static bool is_tracing_multi_id(const struct bpf_prog 
*prog, u32 btf_id)
        return is_tracing_multi(prog->expected_attach_type) && 
bpf_multi_func_btf_id[0] == btf_id;
 }
 
+int btf_id_allow_sleepable(u32 btf_id, unsigned long addr, const struct 
bpf_prog *prog,
+                          const struct btf *btf)
+{
+       const struct btf_type *t;
+       const char *tname;
+
+       switch (prog->type) {
+       case BPF_PROG_TYPE_TRACING:
+               t = btf_type_by_id(btf, btf_id);
+               if (!t)
+                       return -EINVAL;
+               tname = btf_name_by_offset(btf, t->name_off);
+               if (!tname)
+                       return -EINVAL;
+
+               /* *.multi sleepable programs will pass initial sleepable check,
+                * the actual attached btf ids are checked later during the link
+                * attachment.
+                */
+               if (is_tracing_multi_id(prog, btf_id))
+                       return 0;
+               if (!check_attach_sleepable(btf_id, addr, tname))
+                       return 0;
+               /* fentry/fexit/fmod_ret progs can also be sleepable if they are
+                * in the fmodret id set with the KF_SLEEPABLE flag.
+                */
+               else {
+                       u32 *flags = btf_kfunc_is_modify_return(btf, btf_id, 
prog);
+
+                       if (flags && (*flags & KF_SLEEPABLE))
+                               return 0;
+               }
+               break;
+       case BPF_PROG_TYPE_LSM:
+               /* LSM progs check that they are attached to bpf_lsm_*() funcs.
+                * Only some of them are sleepable.
+                */
+               if (bpf_lsm_is_sleepable_hook(btf_id))
+                       return 0;
+               break;
+       default:
+               break;
+       }
+       return -EINVAL;
+}
+
 int bpf_check_attach_target(struct bpf_verifier_log *log,
                            const struct bpf_prog *prog,
                            const struct bpf_prog *tgt_prog,
@@ -25349,38 +25395,7 @@ int bpf_check_attach_target(struct bpf_verifier_log 
*log,
                }
 
                if (prog->sleepable) {
-                       ret = -EINVAL;
-                       switch (prog->type) {
-                       case BPF_PROG_TYPE_TRACING:
-                               /* *.multi sleepable programs will pass initial 
sleepable check,
-                                * the actual attached btf ids are checked 
later during the link
-                                * attachment.
-                                */
-                               if (is_tracing_multi_id(prog, btf_id))
-                                       ret = 0;
-                               if (!check_attach_sleepable(btf_id, addr, 
tname))
-                                       ret = 0;
-                               /* fentry/fexit/fmod_ret progs can also be 
sleepable if they are
-                                * in the fmodret id set with the KF_SLEEPABLE 
flag.
-                                */
-                               else {
-                                       u32 *flags = 
btf_kfunc_is_modify_return(btf, btf_id,
-                                                                               
prog);
-
-                                       if (flags && (*flags & KF_SLEEPABLE))
-                                               ret = 0;
-                               }
-                               break;
-                       case BPF_PROG_TYPE_LSM:
-                               /* LSM progs check that they are attached to 
bpf_lsm_*() funcs.
-                                * Only some of them are sleepable.
-                                */
-                               if (bpf_lsm_is_sleepable_hook(btf_id))
-                                       ret = 0;
-                               break;
-                       default:
-                               break;
-                       }
+                       ret = btf_id_allow_sleepable(btf_id, addr, prog, btf);
                        if (ret) {
                                module_put(mod);
                                bpf_log(log, "%s is not sleepable\n", tname);
-- 
2.53.0


Reply via email to