[RFC PATCH bpf-next 10/12] bpf: support "__uninit" iterator arguments in generic kfuncs
Justin Suess
utilityemal77 at gmail.com
Tue Oct 6 00:20:17 UTC 2026
Iterator constructors are recognised by their KF_ITER_NEW flag, which
binds them to the bpf_iter_<type>_new() name and so to a single
constructor per type. A kfunc that initializes an iterator from inputs
that naming convention cannot express - e.g. another, already
initialized iterator - therefore cannot be a constructor.
Let such a kfunc mark its destination argument with the "__uninit"
suffix already used for dynptr out-arguments: process_iter_arg() now
decides per argument, rather than per kfunc, whether it initializes the
iterator or operates on an initialized one. Only iterator-typed
arguments are reclassified, so dynptr "__uninit" out-arguments are
unaffected.
The first user is the path ancestor iterator handover added by the next
patch.
Signed-off-by: Justin Suess <utilityemal77 at gmail.com>
---
kernel/bpf/verifier.c | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 066c4b838b85..3294b2a43167 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -8312,6 +8312,24 @@ static bool is_iter_destroy_kfunc(struct bpf_call_arg_meta *meta)
return meta->kfunc_flags & KF_ITER_DESTROY;
}
+/*
+ * An "__uninit"-suffixed iterator argument of a kfunc that is not itself an
+ * iterator method: the kfunc initializes that iterator state, as a
+ * bpf_iter_<type>_new() does, but from inputs the constructor naming
+ * convention cannot express - e.g. another, already-initialized iterator.
+ * Only iterator-typed arguments qualify, so "__uninit" dynptr out-arguments
+ * are not reclassified.
+ */
+static bool is_kfunc_arg_iter_init(struct bpf_call_arg_meta *meta, int arg_idx,
+ const struct btf_param *arg)
+{
+ if (is_iter_kfunc(meta))
+ return false;
+
+ return btf_param_match_suffix(meta->btf, arg, "__uninit") &&
+ btf_check_iter_arg(meta->btf, meta->func_proto, arg_idx) >= 0;
+}
+
static bool is_kfunc_arg_iter(struct bpf_call_arg_meta *meta, int arg_idx,
const struct btf_param *arg)
{
@@ -8322,7 +8340,11 @@ static bool is_kfunc_arg_iter(struct bpf_call_arg_meta *meta, int arg_idx,
return arg_idx == 0;
/* iter passed as an argument to a generic kfunc */
- return btf_param_match_suffix(meta->btf, arg, "__iter");
+ if (btf_param_match_suffix(meta->btf, arg, "__iter"))
+ return true;
+
+ /* iter state a generic kfunc initializes */
+ return is_kfunc_arg_iter_init(meta, arg_idx, arg);
}
static int process_iter_arg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
@@ -8332,6 +8354,7 @@ static int process_iter_arg(struct bpf_verifier_env *env, struct bpf_reg_state *
struct bpf_func_state *state = bpf_func(env, reg);
const struct btf_type *t;
int spi, err, i, nr_slots, btf_id;
+ bool init;
if (reg->type != PTR_TO_STACK) {
verbose(env, "%s expected pointer to an iterator on stack\n",
@@ -8363,8 +8386,16 @@ static int process_iter_arg(struct bpf_verifier_env *env, struct bpf_reg_state *
t = btf_type_by_id(meta->btf, btf_id);
nr_slots = t->size / BPF_REG_SIZE;
- if (is_iter_new_kfunc(meta)) {
- /* bpf_iter_<type>_new() expects pointer to uninit iter state */
+ /*
+ * Whether this argument is the iterator the call initializes, rather
+ * than an initialized one it operates on.
+ */
+ init = is_iter_new_kfunc(meta) ||
+ is_kfunc_arg_iter_init(meta, arg,
+ &btf_params(meta->func_proto)[arg]);
+
+ if (init) {
+ /* expects a pointer to uninit iter state */
if (!is_iter_reg_valid_uninit(env, reg, nr_slots)) {
verbose(env, "expected uninitialized iter_%s as %s\n",
iter_type_str(meta->btf, btf_id), reg_arg_name(env, argno));
--
2.55.0
More information about the Linux-security-module-archive
mailing list