Skip to content

Commit 496ddd1

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
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 <[email protected]> Acked-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 01ac89d commit 496ddd1

File tree

2 files changed

+41
-14
lines changed

2 files changed

+41
-14
lines changed

include/linux/btf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
580580
int get_kern_ctx_btf_id(struct bpf_verifier_log *log, enum bpf_prog_type prog_type);
581581
bool btf_types_are_same(const struct btf *btf1, u32 id1,
582582
const struct btf *btf2, u32 id2);
583+
int btf_check_iter_arg(struct btf *btf, const struct btf_type *func, int arg_idx);
583584
#else
584585
static inline const struct btf_type *btf_type_by_id(const struct btf *btf,
585586
u32 type_id)
@@ -654,6 +655,10 @@ static inline bool btf_types_are_same(const struct btf *btf1, u32 id1,
654655
{
655656
return false;
656657
}
658+
static inline int btf_check_iter_arg(struct btf *btf, const struct btf_type *func, int arg_idx)
659+
{
660+
return -EOPNOTSUPP;
661+
}
657662
#endif
658663

659664
static inline bool btf_type_is_struct_ptr(struct btf *btf, const struct btf_type *t)

kernel/bpf/btf.c

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8047,15 +8047,44 @@ BTF_ID_LIST_GLOBAL(btf_tracing_ids, MAX_BTF_TRACING_TYPE)
80478047
BTF_TRACING_TYPE_xxx
80488048
#undef BTF_TRACING_TYPE
80498049

8050+
/* Validate well-formedness of iter argument type.
8051+
* On success, return positive BTF ID of iter state's STRUCT type.
8052+
* On error, negative error is returned.
8053+
*/
8054+
int btf_check_iter_arg(struct btf *btf, const struct btf_type *func, int arg_idx)
8055+
{
8056+
const struct btf_param *arg;
8057+
const struct btf_type *t;
8058+
const char *name;
8059+
int btf_id;
8060+
8061+
if (btf_type_vlen(func) <= arg_idx)
8062+
return -EINVAL;
8063+
8064+
arg = &btf_params(func)[arg_idx];
8065+
t = btf_type_skip_modifiers(btf, arg->type, NULL);
8066+
if (!t || !btf_type_is_ptr(t))
8067+
return -EINVAL;
8068+
t = btf_type_skip_modifiers(btf, t->type, &btf_id);
8069+
if (!t || !__btf_type_is_struct(t))
8070+
return -EINVAL;
8071+
8072+
name = btf_name_by_offset(btf, t->name_off);
8073+
if (!name || strncmp(name, ITER_PREFIX, sizeof(ITER_PREFIX) - 1))
8074+
return -EINVAL;
8075+
8076+
return btf_id;
8077+
}
8078+
80508079
static int btf_check_iter_kfuncs(struct btf *btf, const char *func_name,
80518080
const struct btf_type *func, u32 func_flags)
80528081
{
80538082
u32 flags = func_flags & (KF_ITER_NEW | KF_ITER_NEXT | KF_ITER_DESTROY);
8054-
const char *name, *sfx, *iter_name;
8055-
const struct btf_param *arg;
8083+
const char *sfx, *iter_name;
80568084
const struct btf_type *t;
80578085
char exp_name[128];
80588086
u32 nr_args;
8087+
int btf_id;
80598088

80608089
/* exactly one of KF_ITER_{NEW,NEXT,DESTROY} can be set */
80618090
if (!flags || (flags & (flags - 1)))
@@ -8066,28 +8095,21 @@ static int btf_check_iter_kfuncs(struct btf *btf, const char *func_name,
80668095
if (nr_args < 1)
80678096
return -EINVAL;
80688097

8069-
arg = &btf_params(func)[0];
8070-
t = btf_type_skip_modifiers(btf, arg->type, NULL);
8071-
if (!t || !btf_type_is_ptr(t))
8072-
return -EINVAL;
8073-
t = btf_type_skip_modifiers(btf, t->type, NULL);
8074-
if (!t || !__btf_type_is_struct(t))
8075-
return -EINVAL;
8076-
8077-
name = btf_name_by_offset(btf, t->name_off);
8078-
if (!name || strncmp(name, ITER_PREFIX, sizeof(ITER_PREFIX) - 1))
8079-
return -EINVAL;
8098+
btf_id = btf_check_iter_arg(btf, func, 0);
8099+
if (btf_id < 0)
8100+
return btf_id;
80808101

80818102
/* sizeof(struct bpf_iter_<type>) should be a multiple of 8 to
80828103
* fit nicely in stack slots
80838104
*/
8105+
t = btf_type_by_id(btf, btf_id);
80848106
if (t->size == 0 || (t->size % 8))
80858107
return -EINVAL;
80868108

80878109
/* validate bpf_iter_<type>_{new,next,destroy}(struct bpf_iter_<type> *)
80888110
* naming pattern
80898111
*/
8090-
iter_name = name + sizeof(ITER_PREFIX) - 1;
8112+
iter_name = btf_name_by_offset(btf, t->name_off) + sizeof(ITER_PREFIX) - 1;
80918113
if (flags & KF_ITER_NEW)
80928114
sfx = "new";
80938115
else if (flags & KF_ITER_NEXT)

0 commit comments

Comments
 (0)