This patch added name checking for the following types:
 . BTF_KIND_PTR, BTF_KIND_ARRAY, BTF_KIND_VOLATILE,
   BTF_KIND_CONST, BTF_KIND_RESTRICT:
     the name must be null
 . BTF_KIND_STRUCT, BTF_KIND_UNION: the struct/member name
     is either null or a valid identifier
 . BTF_KIND_ENUM: the enum type name is either null or a valid
     identifier; the enumerator name must be a valid identifier.
 . BTF_KIND_FWD: the name must be a valid identifier
 . BTF_KIND_TYPEDEF: the name must be a valid identifier

For those places a valid name is required, the name must be
a valid C identifier. This can be relaxed later if we found
use cases for a different (non-C) frontend.

Fixes: 69b693f0aefa ("bpf: btf: Introduce BPF Type Format (BTF)")
Acked-by: Martin KaFai Lau <ka...@fb.com>
Signed-off-by: Yonghong Song <y...@fb.com>
---
 kernel/bpf/btf.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 93c233ab2db6..4da543d6bea2 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -1168,6 +1168,22 @@ static int btf_ref_type_check_meta(struct 
btf_verifier_env *env,
                return -EINVAL;
        }
 
+       /* typedef type must have a valid name, and other ref types,
+        * volatile, const, restrict, should have a null name.
+        */
+       if (BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF) {
+               if (!t->name_off ||
+                   !btf_name_valid_identifier(env->btf, t->name_off)) {
+                       btf_verifier_log_type(env, t, "Invalid name");
+                       return -EINVAL;
+               }
+       } else {
+               if (t->name_off) {
+                       btf_verifier_log_type(env, t, "Invalid name");
+                       return -EINVAL;
+               }
+       }
+
        btf_verifier_log_type(env, t, NULL);
 
        return 0;
@@ -1325,6 +1341,13 @@ static s32 btf_fwd_check_meta(struct btf_verifier_env 
*env,
                return -EINVAL;
        }
 
+       /* fwd type must have a valid name */
+       if (!t->name_off ||
+           !btf_name_valid_identifier(env->btf, t->name_off)) {
+               btf_verifier_log_type(env, t, "Invalid name");
+               return -EINVAL;
+       }
+
        btf_verifier_log_type(env, t, NULL);
 
        return 0;
@@ -1381,6 +1404,12 @@ static s32 btf_array_check_meta(struct btf_verifier_env 
*env,
                return -EINVAL;
        }
 
+       /* array type should not have a name */
+       if (t->name_off) {
+               btf_verifier_log_type(env, t, "Invalid name");
+               return -EINVAL;
+       }
+
        if (btf_type_vlen(t)) {
                btf_verifier_log_type(env, t, "vlen != 0");
                return -EINVAL;
@@ -1557,6 +1586,13 @@ static s32 btf_struct_check_meta(struct btf_verifier_env 
*env,
                return -EINVAL;
        }
 
+       /* struct type either no name or a valid one */
+       if (t->name_off &&
+           !btf_name_valid_identifier(env->btf, t->name_off)) {
+               btf_verifier_log_type(env, t, "Invalid name");
+               return -EINVAL;
+       }
+
        btf_verifier_log_type(env, t, NULL);
 
        last_offset = 0;
@@ -1568,6 +1604,12 @@ static s32 btf_struct_check_meta(struct btf_verifier_env 
*env,
                        return -EINVAL;
                }
 
+               /* struct member either no name or a valid one */
+               if (member->name_off &&
+                   !btf_name_valid_identifier(btf, member->name_off)) {
+                       btf_verifier_log_member(env, t, member, "Invalid name");
+                       return -EINVAL;
+               }
                /* A member cannot be in type void */
                if (!member->type || !BTF_TYPE_ID_VALID(member->type)) {
                        btf_verifier_log_member(env, t, member,
@@ -1755,6 +1797,13 @@ static s32 btf_enum_check_meta(struct btf_verifier_env 
*env,
                return -EINVAL;
        }
 
+       /* enum type either no name or a valid one */
+       if (t->name_off &&
+           !btf_name_valid_identifier(env->btf, t->name_off)) {
+               btf_verifier_log_type(env, t, "Invalid name");
+               return -EINVAL;
+       }
+
        btf_verifier_log_type(env, t, NULL);
 
        for (i = 0; i < nr_enums; i++) {
@@ -1764,6 +1813,14 @@ static s32 btf_enum_check_meta(struct btf_verifier_env 
*env,
                        return -EINVAL;
                }
 
+               /* enum member must have a valid name */
+               if (!enums[i].name_off ||
+                   !btf_name_valid_identifier(btf, enums[i].name_off)) {
+                       btf_verifier_log_type(env, t, "Invalid name");
+                       return -EINVAL;
+               }
+
+
                btf_verifier_log(env, "\t%s val=%d\n",
                                 btf_name_by_offset(btf, enums[i].name_off),
                                 enums[i].val);
-- 
2.17.1

Reply via email to