bpf: btf: check name validity for various types
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: 69b693f0ae ("bpf: btf: Introduce BPF Type Format (BTF)")
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
committed by
Alexei Starovoitov
parent
cdbb096add
commit
eb04bbb608
@@ -1168,6 +1168,22 @@ static int btf_ref_type_check_meta(struct btf_verifier_env *env,
|
|||||||
return -EINVAL;
|
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);
|
btf_verifier_log_type(env, t, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1325,6 +1341,13 @@ static s32 btf_fwd_check_meta(struct btf_verifier_env *env,
|
|||||||
return -EINVAL;
|
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);
|
btf_verifier_log_type(env, t, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1381,6 +1404,12 @@ static s32 btf_array_check_meta(struct btf_verifier_env *env,
|
|||||||
return -EINVAL;
|
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)) {
|
if (btf_type_vlen(t)) {
|
||||||
btf_verifier_log_type(env, t, "vlen != 0");
|
btf_verifier_log_type(env, t, "vlen != 0");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -1557,6 +1586,13 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
|||||||
return -EINVAL;
|
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);
|
btf_verifier_log_type(env, t, NULL);
|
||||||
|
|
||||||
last_offset = 0;
|
last_offset = 0;
|
||||||
@@ -1568,6 +1604,12 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
|||||||
return -EINVAL;
|
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 */
|
/* A member cannot be in type void */
|
||||||
if (!member->type || !BTF_TYPE_ID_VALID(member->type)) {
|
if (!member->type || !BTF_TYPE_ID_VALID(member->type)) {
|
||||||
btf_verifier_log_member(env, t, member,
|
btf_verifier_log_member(env, t, member,
|
||||||
@@ -1755,6 +1797,13 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
|
|||||||
return -EINVAL;
|
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);
|
btf_verifier_log_type(env, t, NULL);
|
||||||
|
|
||||||
for (i = 0; i < nr_enums; i++) {
|
for (i = 0; i < nr_enums; i++) {
|
||||||
@@ -1764,6 +1813,14 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
|
|||||||
return -EINVAL;
|
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_verifier_log(env, "\t%s val=%d\n",
|
||||||
btf_name_by_offset(btf, enums[i].name_off),
|
btf_name_by_offset(btf, enums[i].name_off),
|
||||||
enums[i].val);
|
enums[i].val);
|
||||||
|
|||||||
Reference in New Issue
Block a user