[RFC PATCH 5/9] bpf: Add bpf_prog_for_each_used_map()

Tejun Heo
2026-04-27T10:51:15Z

Wrap the prog->aux->used_maps[] walk and its used_maps_mutex behind a
helper. Existing in-tree callers open-code the same lock + iterate pattern
(e.g. bpf_check_tail_call in core.c, the verifier and syscall paths); a
sched_ext follow-up needs the same loop and would otherwise reach into
bpf_prog_aux directly.

Signed-off-by: Tejun Heo <tj@kernel.org>
---
include/linux/bpf.h | 3 +++
kernel/bpf/core.c | 29 +++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index f4e4360b81f6..587e5ff387bf 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2338,6 +2338,9 @@ static inline bool map_type_contains_progs(struct bpf_map *map)

bool bpf_prog_map_compatible(struct bpf_map *map, const struct bpf_prog *fp);
int bpf_prog_calc_tag(struct bpf_prog *fp);
+int bpf_prog_for_each_used_map(struct bpf_prog *prog,
+ int (*cb)(struct bpf_map *map, void *data),
+ void *data);

const struct bpf_func_proto *bpf_get_trace_printk_proto(void);
const struct bpf_func_proto *bpf_get_trace_vprintk_proto(void);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 066b86e7233c..aa590a817176 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2510,6 +2510,35 @@ static int bpf_check_tail_call(const struct bpf_prog *fp)
return ret;
}

+/**
+ * bpf_prog_for_each_used_map - Invoke @cb for each map @prog references
+ * @prog: BPF program whose used_maps to walk
+ * @cb: callback invoked once per map; non-zero return stops iteration
+ * @data: opaque argument passed to @cb
+ *
+ * Holds prog->aux->used_maps_mutex across the walk.
+ *
+ * Return 0 if iteration completed, otherwise the first non-zero @cb return.
+ */
+int bpf_prog_for_each_used_map(struct bpf_prog *prog,
+ int (*cb)(struct bpf_map *map, void *data),
+ void *data)
+{
+ struct bpf_prog_aux *aux = prog->aux;
+ int ret = 0;
+ u32 i;
+
+ mutex_lock(&aux->used_maps_mutex);
+ for (i = 0; i < aux->used_map_cnt; i++) {
+ ret = cb(aux->used_maps[i], data);
+ if (ret)
+ break;
+ }
+ mutex_unlock(&aux->used_maps_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(bpf_prog_for_each_used_map);
+
static bool bpf_prog_select_interpreter(struct bpf_prog *fp)
{
bool select_interpreter = false;
--
2.53.0