bpf: limit the number of levels of a nested struct type.
Limit the number of levels looking into struct types to avoid running out of stack space. Acked-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com> Link: https://lore.kernel.org/r/20240523174202.461236-7-thinker.li@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
64e8ee8148
commit
f19caf57d8
@ -3536,7 +3536,8 @@ static int btf_repeat_fields(struct btf_field_info *info,
|
||||
|
||||
static int btf_find_struct_field(const struct btf *btf,
|
||||
const struct btf_type *t, u32 field_mask,
|
||||
struct btf_field_info *info, int info_cnt);
|
||||
struct btf_field_info *info, int info_cnt,
|
||||
u32 level);
|
||||
|
||||
/* Find special fields in the struct type of a field.
|
||||
*
|
||||
@ -3547,11 +3548,15 @@ static int btf_find_struct_field(const struct btf *btf,
|
||||
static int btf_find_nested_struct(const struct btf *btf, const struct btf_type *t,
|
||||
u32 off, u32 nelems,
|
||||
u32 field_mask, struct btf_field_info *info,
|
||||
int info_cnt)
|
||||
int info_cnt, u32 level)
|
||||
{
|
||||
int ret, err, i;
|
||||
|
||||
ret = btf_find_struct_field(btf, t, field_mask, info, info_cnt);
|
||||
level++;
|
||||
if (level >= MAX_RESOLVE_DEPTH)
|
||||
return -E2BIG;
|
||||
|
||||
ret = btf_find_struct_field(btf, t, field_mask, info, info_cnt, level);
|
||||
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
@ -3579,7 +3584,8 @@ static int btf_find_field_one(const struct btf *btf,
|
||||
int var_idx,
|
||||
u32 off, u32 expected_size,
|
||||
u32 field_mask, u32 *seen_mask,
|
||||
struct btf_field_info *info, int info_cnt)
|
||||
struct btf_field_info *info, int info_cnt,
|
||||
u32 level)
|
||||
{
|
||||
int ret, align, sz, field_type;
|
||||
struct btf_field_info tmp;
|
||||
@ -3607,7 +3613,7 @@ static int btf_find_field_one(const struct btf *btf,
|
||||
if (expected_size && expected_size != sz * nelems)
|
||||
return 0;
|
||||
ret = btf_find_nested_struct(btf, var_type, off, nelems, field_mask,
|
||||
&info[0], info_cnt);
|
||||
&info[0], info_cnt, level);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3668,7 +3674,8 @@ static int btf_find_field_one(const struct btf *btf,
|
||||
|
||||
static int btf_find_struct_field(const struct btf *btf,
|
||||
const struct btf_type *t, u32 field_mask,
|
||||
struct btf_field_info *info, int info_cnt)
|
||||
struct btf_field_info *info, int info_cnt,
|
||||
u32 level)
|
||||
{
|
||||
int ret, idx = 0;
|
||||
const struct btf_member *member;
|
||||
@ -3687,7 +3694,7 @@ static int btf_find_struct_field(const struct btf *btf,
|
||||
ret = btf_find_field_one(btf, t, member_type, i,
|
||||
off, 0,
|
||||
field_mask, &seen_mask,
|
||||
&info[idx], info_cnt - idx);
|
||||
&info[idx], info_cnt - idx, level);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
idx += ret;
|
||||
@ -3697,7 +3704,7 @@ static int btf_find_struct_field(const struct btf *btf,
|
||||
|
||||
static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
|
||||
u32 field_mask, struct btf_field_info *info,
|
||||
int info_cnt)
|
||||
int info_cnt, u32 level)
|
||||
{
|
||||
int ret, idx = 0;
|
||||
const struct btf_var_secinfo *vsi;
|
||||
@ -3710,7 +3717,8 @@ static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
|
||||
off = vsi->offset;
|
||||
ret = btf_find_field_one(btf, var, var_type, -1, off, vsi->size,
|
||||
field_mask, &seen_mask,
|
||||
&info[idx], info_cnt - idx);
|
||||
&info[idx], info_cnt - idx,
|
||||
level);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
idx += ret;
|
||||
@ -3723,9 +3731,9 @@ static int btf_find_field(const struct btf *btf, const struct btf_type *t,
|
||||
int info_cnt)
|
||||
{
|
||||
if (__btf_type_is_struct(t))
|
||||
return btf_find_struct_field(btf, t, field_mask, info, info_cnt);
|
||||
return btf_find_struct_field(btf, t, field_mask, info, info_cnt, 0);
|
||||
else if (btf_type_is_datasec(t))
|
||||
return btf_find_datasec_var(btf, t, field_mask, info, info_cnt);
|
||||
return btf_find_datasec_var(btf, t, field_mask, info, info_cnt, 0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user