[PATCH bpf-next v3 13/17] bpf, verifier: Propagate packet access flags to gen_prologue
From: Jakub Sitnicki <jakub@cloudflare.com>
Date: 2026-01-07 14:28:26
Also in:
bpf
Subsystem:
bpf [core], bpf [general] (safe dynamic programs and tools), bpf [networking] (tcx & tc bpf, sock_addr), bpf [selftests] (test runners & infrastructure), kernel selftest framework, networking [general], tc subsystem, the rest · Maintainers:
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Shuah Khan, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Jamal Hadi Salim, Jiri Pirko, Linus Torvalds
Change gen_prologue() to accept the packet access flags bitmap. This allows gen_prologue() to inspect multiple access patterns when needed. No functional change. Reviewed-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> --- include/linux/bpf.h | 2 +- kernel/bpf/cgroup.c | 2 +- kernel/bpf/verifier.c | 6 ++---- net/core/filter.c | 15 ++++++++------- net/sched/bpf_qdisc.c | 3 ++- tools/testing/selftests/bpf/test_kmods/bpf_testmod.c | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 5936f8e2996f..1dba2caee09c 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h@@ -1106,7 +1106,7 @@ struct bpf_verifier_ops { bool (*is_valid_access)(int off, int size, enum bpf_access_type type, const struct bpf_prog *prog, struct bpf_insn_access_aux *info); - int (*gen_prologue)(struct bpf_insn *insn, bool direct_write, + int (*gen_prologue)(struct bpf_insn *insn, u32 pkt_access_flags, const struct bpf_prog *prog); int (*gen_epilogue)(struct bpf_insn *insn, const struct bpf_prog *prog, s16 ctx_stack_off);
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 69988af44b37..d96465cd7d43 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c@@ -2694,7 +2694,7 @@ static u32 cg_sockopt_convert_ctx_access(enum bpf_access_type type, } static int cg_sockopt_get_prologue(struct bpf_insn *insn_buf, - bool direct_write, + u32 pkt_access_flags, const struct bpf_prog *prog) { /* Nothing to do for sockopt argument. The data is kzalloc'ated.
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 95818a7eedff..daa90c81d802 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c@@ -21768,7 +21768,6 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) struct bpf_prog *new_prog; enum bpf_access_type type; bool is_narrower_load; - bool seen_direct_write; int epilogue_idx = 0; if (ops->gen_epilogue) {
@@ -21796,13 +21795,12 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) } } - seen_direct_write = env->seen_packet_access & PA_F_DIRECT_WRITE; - if (ops->gen_prologue || seen_direct_write) { + if (ops->gen_prologue || (env->seen_packet_access & PA_F_DIRECT_WRITE)) { if (!ops->gen_prologue) { verifier_bug(env, "gen_prologue is null"); return -EFAULT; } - cnt = ops->gen_prologue(insn_buf, seen_direct_write, env->prog); + cnt = ops->gen_prologue(insn_buf, env->seen_packet_access, env->prog); if (cnt >= INSN_BUF_SIZE) { verifier_bug(env, "prologue is too long"); return -EFAULT;
diff --git a/net/core/filter.c b/net/core/filter.c
index d43df98e1ded..07af2a94cc9a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c@@ -9052,7 +9052,7 @@ static bool sock_filter_is_valid_access(int off, int size, prog->expected_attach_type); } -static int bpf_noop_prologue(struct bpf_insn *insn_buf, bool direct_write, +static int bpf_noop_prologue(struct bpf_insn *insn_buf, u32 pkt_access_flags, const struct bpf_prog *prog) { /* Neither direct read nor direct write requires any preliminary
@@ -9061,12 +9061,12 @@ static int bpf_noop_prologue(struct bpf_insn *insn_buf, bool direct_write, return 0; } -static int bpf_unclone_prologue(struct bpf_insn *insn_buf, bool direct_write, +static int bpf_unclone_prologue(struct bpf_insn *insn_buf, u32 pkt_access_flags, const struct bpf_prog *prog, int drop_verdict) { struct bpf_insn *insn = insn_buf; - if (!direct_write) + if (!(pkt_access_flags & PA_F_DIRECT_WRITE)) return 0; /* if (!skb->cloned)
@@ -9135,10 +9135,11 @@ static int bpf_gen_ld_abs(const struct bpf_insn *orig, return insn - insn_buf; } -static int tc_cls_act_prologue(struct bpf_insn *insn_buf, bool direct_write, +static int tc_cls_act_prologue(struct bpf_insn *insn_buf, u32 pkt_access_flags, const struct bpf_prog *prog) { - return bpf_unclone_prologue(insn_buf, direct_write, prog, TC_ACT_SHOT); + return bpf_unclone_prologue(insn_buf, pkt_access_flags, prog, + TC_ACT_SHOT); } static bool tc_cls_act_is_valid_access(int off, int size,
@@ -9476,10 +9477,10 @@ static bool sock_ops_is_valid_access(int off, int size, return true; } -static int sk_skb_prologue(struct bpf_insn *insn_buf, bool direct_write, +static int sk_skb_prologue(struct bpf_insn *insn_buf, u32 pkt_access_flags, const struct bpf_prog *prog) { - return bpf_unclone_prologue(insn_buf, direct_write, prog, SK_DROP); + return bpf_unclone_prologue(insn_buf, pkt_access_flags, prog, SK_DROP); } static bool sk_skb_is_valid_access(int off, int size,
diff --git a/net/sched/bpf_qdisc.c b/net/sched/bpf_qdisc.c
index b9771788b9b3..dc7b9db7e785 100644
--- a/net/sched/bpf_qdisc.c
+++ b/net/sched/bpf_qdisc.c@@ -132,7 +132,8 @@ static int bpf_qdisc_btf_struct_access(struct bpf_verifier_log *log, BTF_ID_LIST_SINGLE(bpf_qdisc_init_prologue_ids, func, bpf_qdisc_init_prologue) -static int bpf_qdisc_gen_prologue(struct bpf_insn *insn_buf, bool direct_write, +static int bpf_qdisc_gen_prologue(struct bpf_insn *insn_buf, + u32 direct_access_flags, const struct bpf_prog *prog) { struct bpf_insn *insn = insn_buf;
diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
index 1c41d03bd5a1..d698e45783e3 100644
--- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
+++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c@@ -1397,7 +1397,7 @@ static int bpf_test_mod_st_ops__test_pro_epilogue(struct st_ops_args *args) static int bpf_cgroup_from_id_id; static int bpf_cgroup_release_id; -static int st_ops_gen_prologue_with_kfunc(struct bpf_insn *insn_buf, bool direct_write, +static int st_ops_gen_prologue_with_kfunc(struct bpf_insn *insn_buf, const struct bpf_prog *prog) { struct bpf_insn *insn = insn_buf;
@@ -1473,7 +1473,7 @@ static int st_ops_gen_epilogue_with_kfunc(struct bpf_insn *insn_buf, const struc } #define KFUNC_PRO_EPI_PREFIX "test_kfunc_" -static int st_ops_gen_prologue(struct bpf_insn *insn_buf, bool direct_write, +static int st_ops_gen_prologue(struct bpf_insn *insn_buf, u32 pkt_access_flags, const struct bpf_prog *prog) { struct bpf_insn *insn = insn_buf;
@@ -1483,7 +1483,7 @@ static int st_ops_gen_prologue(struct bpf_insn *insn_buf, bool direct_write, return 0; if (!strncmp(prog->aux->name, KFUNC_PRO_EPI_PREFIX, strlen(KFUNC_PRO_EPI_PREFIX))) - return st_ops_gen_prologue_with_kfunc(insn_buf, direct_write, prog); + return st_ops_gen_prologue_with_kfunc(insn_buf, prog); /* r6 = r1[0]; // r6 will be "struct st_ops *args". r1 is "u64 *ctx". * r7 = r6->a;
--
2.43.0