mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 05:44:11 +00:00
bpf: btf: Ensure the member->offset is in the right order
This patch ensures the member->offset of a struct
is in the correct order (i.e the later member's offset cannot
go backward).
The current "pahole -J" BTF encoder does not generate something
like this. However, checking this can ensure future encoder
will not violate this.
Fixes: 69b693f0ae
("bpf: btf: Introduce BPF Type Format (BTF)")
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
1a4f14bab1
commit
6283fa38dc
2 changed files with 41 additions and 1 deletions
|
@ -1519,9 +1519,9 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
||||||
{
|
{
|
||||||
bool is_union = BTF_INFO_KIND(t->info) == BTF_KIND_UNION;
|
bool is_union = BTF_INFO_KIND(t->info) == BTF_KIND_UNION;
|
||||||
const struct btf_member *member;
|
const struct btf_member *member;
|
||||||
|
u32 meta_needed, last_offset;
|
||||||
struct btf *btf = env->btf;
|
struct btf *btf = env->btf;
|
||||||
u32 struct_size = t->size;
|
u32 struct_size = t->size;
|
||||||
u32 meta_needed;
|
|
||||||
u16 i;
|
u16 i;
|
||||||
|
|
||||||
meta_needed = btf_type_vlen(t) * sizeof(*member);
|
meta_needed = btf_type_vlen(t) * sizeof(*member);
|
||||||
|
@ -1534,6 +1534,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
||||||
|
|
||||||
btf_verifier_log_type(env, t, NULL);
|
btf_verifier_log_type(env, t, NULL);
|
||||||
|
|
||||||
|
last_offset = 0;
|
||||||
for_each_member(i, t, member) {
|
for_each_member(i, t, member) {
|
||||||
if (!btf_name_offset_valid(btf, member->name_off)) {
|
if (!btf_name_offset_valid(btf, member->name_off)) {
|
||||||
btf_verifier_log_member(env, t, member,
|
btf_verifier_log_member(env, t, member,
|
||||||
|
@ -1555,6 +1556,16 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ">" instead of ">=" because the last member could be
|
||||||
|
* "char a[0];"
|
||||||
|
*/
|
||||||
|
if (last_offset > member->offset) {
|
||||||
|
btf_verifier_log_member(env, t, member,
|
||||||
|
"Invalid member bits_offset");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (BITS_ROUNDUP_BYTES(member->offset) > struct_size) {
|
if (BITS_ROUNDUP_BYTES(member->offset) > struct_size) {
|
||||||
btf_verifier_log_member(env, t, member,
|
btf_verifier_log_member(env, t, member,
|
||||||
"Memmber bits_offset exceeds its struct size");
|
"Memmber bits_offset exceeds its struct size");
|
||||||
|
@ -1562,6 +1573,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
||||||
}
|
}
|
||||||
|
|
||||||
btf_verifier_log_member(env, t, member, NULL);
|
btf_verifier_log_member(env, t, member, NULL);
|
||||||
|
last_offset = member->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return meta_needed;
|
return meta_needed;
|
||||||
|
|
|
@ -247,6 +247,34 @@ static struct btf_raw_test raw_tests[] = {
|
||||||
.max_entries = 4,
|
.max_entries = 4,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.descr = "struct test #3 Invalid member offset",
|
||||||
|
.raw_types = {
|
||||||
|
/* int */ /* [1] */
|
||||||
|
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
|
||||||
|
/* int64 */ /* [2] */
|
||||||
|
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8),
|
||||||
|
|
||||||
|
/* struct A { */ /* [3] */
|
||||||
|
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 16),
|
||||||
|
BTF_MEMBER_ENC(NAME_TBD, 1, 64), /* int m; */
|
||||||
|
BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* int64 n; */
|
||||||
|
/* } */
|
||||||
|
BTF_END_RAW,
|
||||||
|
},
|
||||||
|
.str_sec = "\0A\0m\0n\0",
|
||||||
|
.str_sec_size = sizeof("\0A\0m\0n\0"),
|
||||||
|
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||||
|
.map_name = "struct_test3_map",
|
||||||
|
.key_size = sizeof(int),
|
||||||
|
.value_size = 16,
|
||||||
|
.key_type_id = 1,
|
||||||
|
.value_type_id = 3,
|
||||||
|
.max_entries = 4,
|
||||||
|
.btf_load_err = true,
|
||||||
|
.err_str = "Invalid member bits_offset",
|
||||||
|
},
|
||||||
|
|
||||||
/* Test member exceeds the size of struct.
|
/* Test member exceeds the size of struct.
|
||||||
*
|
*
|
||||||
* struct A {
|
* struct A {
|
||||||
|
|
Loading…
Reference in a new issue