mirror of
https://github.com/torvalds/linux.git
synced 2024-10-22 21:20:52 +00:00
bpf: extract iterator argument type and name validation logic
Verifier enforces that all iterator structs are named `bpf_iter_<name>` and that whenever iterator is passed to a kfunc it's passed as a valid PTR -> STRUCT chain (with potentially const modifiers in between). We'll need this check for upcoming changes, so instead of duplicating the logic, extract it into a helper function. Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20240808232230.2848712-2-andrii@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
01ac89d0a5
commit
496ddd19a0
|
@ -580,6 +580,7 @@ bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
|
|||
int get_kern_ctx_btf_id(struct bpf_verifier_log *log, enum bpf_prog_type prog_type);
|
||||
bool btf_types_are_same(const struct btf *btf1, u32 id1,
|
||||
const struct btf *btf2, u32 id2);
|
||||
int btf_check_iter_arg(struct btf *btf, const struct btf_type *func, int arg_idx);
|
||||
#else
|
||||
static inline const struct btf_type *btf_type_by_id(const struct btf *btf,
|
||||
u32 type_id)
|
||||
|
@ -654,6 +655,10 @@ static inline bool btf_types_are_same(const struct btf *btf1, u32 id1,
|
|||
{
|
||||
return false;
|
||||
}
|
||||
static inline int btf_check_iter_arg(struct btf *btf, const struct btf_type *func, int arg_idx)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool btf_type_is_struct_ptr(struct btf *btf, const struct btf_type *t)
|
||||
|
|
|
@ -8047,15 +8047,44 @@ BTF_ID_LIST_GLOBAL(btf_tracing_ids, MAX_BTF_TRACING_TYPE)
|
|||
BTF_TRACING_TYPE_xxx
|
||||
#undef BTF_TRACING_TYPE
|
||||
|
||||
/* Validate well-formedness of iter argument type.
|
||||
* On success, return positive BTF ID of iter state's STRUCT type.
|
||||
* On error, negative error is returned.
|
||||
*/
|
||||
int btf_check_iter_arg(struct btf *btf, const struct btf_type *func, int arg_idx)
|
||||
{
|
||||
const struct btf_param *arg;
|
||||
const struct btf_type *t;
|
||||
const char *name;
|
||||
int btf_id;
|
||||
|
||||
if (btf_type_vlen(func) <= arg_idx)
|
||||
return -EINVAL;
|
||||
|
||||
arg = &btf_params(func)[arg_idx];
|
||||
t = btf_type_skip_modifiers(btf, arg->type, NULL);
|
||||
if (!t || !btf_type_is_ptr(t))
|
||||
return -EINVAL;
|
||||
t = btf_type_skip_modifiers(btf, t->type, &btf_id);
|
||||
if (!t || !__btf_type_is_struct(t))
|
||||
return -EINVAL;
|
||||
|
||||
name = btf_name_by_offset(btf, t->name_off);
|
||||
if (!name || strncmp(name, ITER_PREFIX, sizeof(ITER_PREFIX) - 1))
|
||||
return -EINVAL;
|
||||
|
||||
return btf_id;
|
||||
}
|
||||
|
||||
static int btf_check_iter_kfuncs(struct btf *btf, const char *func_name,
|
||||
const struct btf_type *func, u32 func_flags)
|
||||
{
|
||||
u32 flags = func_flags & (KF_ITER_NEW | KF_ITER_NEXT | KF_ITER_DESTROY);
|
||||
const char *name, *sfx, *iter_name;
|
||||
const struct btf_param *arg;
|
||||
const char *sfx, *iter_name;
|
||||
const struct btf_type *t;
|
||||
char exp_name[128];
|
||||
u32 nr_args;
|
||||
int btf_id;
|
||||
|
||||
/* exactly one of KF_ITER_{NEW,NEXT,DESTROY} can be set */
|
||||
if (!flags || (flags & (flags - 1)))
|
||||
|
@ -8066,28 +8095,21 @@ static int btf_check_iter_kfuncs(struct btf *btf, const char *func_name,
|
|||
if (nr_args < 1)
|
||||
return -EINVAL;
|
||||
|
||||
arg = &btf_params(func)[0];
|
||||
t = btf_type_skip_modifiers(btf, arg->type, NULL);
|
||||
if (!t || !btf_type_is_ptr(t))
|
||||
return -EINVAL;
|
||||
t = btf_type_skip_modifiers(btf, t->type, NULL);
|
||||
if (!t || !__btf_type_is_struct(t))
|
||||
return -EINVAL;
|
||||
|
||||
name = btf_name_by_offset(btf, t->name_off);
|
||||
if (!name || strncmp(name, ITER_PREFIX, sizeof(ITER_PREFIX) - 1))
|
||||
return -EINVAL;
|
||||
btf_id = btf_check_iter_arg(btf, func, 0);
|
||||
if (btf_id < 0)
|
||||
return btf_id;
|
||||
|
||||
/* sizeof(struct bpf_iter_<type>) should be a multiple of 8 to
|
||||
* fit nicely in stack slots
|
||||
*/
|
||||
t = btf_type_by_id(btf, btf_id);
|
||||
if (t->size == 0 || (t->size % 8))
|
||||
return -EINVAL;
|
||||
|
||||
/* validate bpf_iter_<type>_{new,next,destroy}(struct bpf_iter_<type> *)
|
||||
* naming pattern
|
||||
*/
|
||||
iter_name = name + sizeof(ITER_PREFIX) - 1;
|
||||
iter_name = btf_name_by_offset(btf, t->name_off) + sizeof(ITER_PREFIX) - 1;
|
||||
if (flags & KF_ITER_NEW)
|
||||
sfx = "new";
|
||||
else if (flags & KF_ITER_NEXT)
|
||||
|
|
Loading…
Reference in New Issue
Block a user