Commit f19caf57 authored by Kui-Feng Lee's avatar Kui-Feng Lee Committed by Alexei Starovoitov

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: default avatarEduard Zingerman <eddyz87@gmail.com>
Signed-off-by: default avatarKui-Feng Lee <thinker.li@gmail.com>
Link: https://lore.kernel.org/r/20240523174202.461236-7-thinker.li@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 64e8ee81
...@@ -3536,7 +3536,8 @@ static int btf_repeat_fields(struct btf_field_info *info, ...@@ -3536,7 +3536,8 @@ static int btf_repeat_fields(struct btf_field_info *info,
static int btf_find_struct_field(const struct btf *btf, static int btf_find_struct_field(const struct btf *btf,
const struct btf_type *t, u32 field_mask, 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. /* Find special fields in the struct type of a field.
* *
...@@ -3547,11 +3548,15 @@ static int btf_find_struct_field(const struct btf *btf, ...@@ -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, static int btf_find_nested_struct(const struct btf *btf, const struct btf_type *t,
u32 off, u32 nelems, u32 off, u32 nelems,
u32 field_mask, struct btf_field_info *info, u32 field_mask, struct btf_field_info *info,
int info_cnt) int info_cnt, u32 level)
{ {
int ret, err, i; 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) if (ret <= 0)
return ret; return ret;
...@@ -3579,7 +3584,8 @@ static int btf_find_field_one(const struct btf *btf, ...@@ -3579,7 +3584,8 @@ static int btf_find_field_one(const struct btf *btf,
int var_idx, int var_idx,
u32 off, u32 expected_size, u32 off, u32 expected_size,
u32 field_mask, u32 *seen_mask, 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; int ret, align, sz, field_type;
struct btf_field_info tmp; struct btf_field_info tmp;
...@@ -3607,7 +3613,7 @@ static int btf_find_field_one(const struct btf *btf, ...@@ -3607,7 +3613,7 @@ static int btf_find_field_one(const struct btf *btf,
if (expected_size && expected_size != sz * nelems) if (expected_size && expected_size != sz * nelems)
return 0; return 0;
ret = btf_find_nested_struct(btf, var_type, off, nelems, field_mask, ret = btf_find_nested_struct(btf, var_type, off, nelems, field_mask,
&info[0], info_cnt); &info[0], info_cnt, level);
return ret; return ret;
} }
...@@ -3668,7 +3674,8 @@ static int btf_find_field_one(const struct btf *btf, ...@@ -3668,7 +3674,8 @@ static int btf_find_field_one(const struct btf *btf,
static int btf_find_struct_field(const struct btf *btf, static int btf_find_struct_field(const struct btf *btf,
const struct btf_type *t, u32 field_mask, 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; int ret, idx = 0;
const struct btf_member *member; const struct btf_member *member;
...@@ -3687,7 +3694,7 @@ static int btf_find_struct_field(const struct btf *btf, ...@@ -3687,7 +3694,7 @@ static int btf_find_struct_field(const struct btf *btf,
ret = btf_find_field_one(btf, t, member_type, i, ret = btf_find_field_one(btf, t, member_type, i,
off, 0, off, 0,
field_mask, &seen_mask, field_mask, &seen_mask,
&info[idx], info_cnt - idx); &info[idx], info_cnt - idx, level);
if (ret < 0) if (ret < 0)
return ret; return ret;
idx += ret; idx += ret;
...@@ -3697,7 +3704,7 @@ static int btf_find_struct_field(const struct btf *btf, ...@@ -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, static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
u32 field_mask, struct btf_field_info *info, u32 field_mask, struct btf_field_info *info,
int info_cnt) int info_cnt, u32 level)
{ {
int ret, idx = 0; int ret, idx = 0;
const struct btf_var_secinfo *vsi; 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, ...@@ -3710,7 +3717,8 @@ static int btf_find_datasec_var(const struct btf *btf, const struct btf_type *t,
off = vsi->offset; off = vsi->offset;
ret = btf_find_field_one(btf, var, var_type, -1, off, vsi->size, ret = btf_find_field_one(btf, var, var_type, -1, off, vsi->size,
field_mask, &seen_mask, field_mask, &seen_mask,
&info[idx], info_cnt - idx); &info[idx], info_cnt - idx,
level);
if (ret < 0) if (ret < 0)
return ret; return ret;
idx += ret; idx += ret;
...@@ -3723,9 +3731,9 @@ static int btf_find_field(const struct btf *btf, const struct btf_type *t, ...@@ -3723,9 +3731,9 @@ static int btf_find_field(const struct btf *btf, const struct btf_type *t,
int info_cnt) int info_cnt)
{ {
if (__btf_type_is_struct(t)) 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)) 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; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment