Re: [PATCH bpf 05/11] bpf: Reject pkt arguments in mutating subprogs
From: Amery Hung <hidden>
Date: 2026-09-16 05:57:33
Also in:
bpf
On Tue, Sep 15, 2026 at 10:10 PM Emil Tsalapatis [off-list ref] wrote:
The verifier tracks changes in how PTR_TO_PACKET registers' bounds are modified across subprog boundaries. PTR_TO_PACKET registers are actually passed as PTR_TO_MEM, which is assumed valid for the entire call. This is not the case with packet memory, where a pskb_* call may invalidate its memory region. Reject BPF code that passes PTR_TO_PACKET pointers to subprogs that may mutate a packet. We cannot pass the pointer as a true PTR_TO_PACKET because we would also need to somehow pass the PTR_TO_PACKET_META or PTR_TO_PACKET_END to the subprog. Since we cannot avoid representing the pointer in the subprog as PTR_TO_MEM, only permit it if the subprog is guaranteed not to mutate the packet.
CC Mahe.
Hi Emil,
There is a related but separate issue [1] addressed by 8fe994c80af2
(“bpf: Consolidate function call pkt_access validation”). I think a
long-term solution could be supporting ARG_PTR_TO_PACKET for global
subprograms. For example:
int parse_something(struct __sk_buff *skb, __u16 off,
char *data_start __arg_packet, ...);
The verifier could require a real PTR_TO_PACKET at the call site and
verify the global subprogram with a real PTR_TO_PACKET, rather than
converting it to PTR_TO_MEM. This would preserve packet access rules,
allow reads from cgroup_skb programs while rejecting writes in the
callee, and automatically invalidate the argument after calls such as
bpf_skb_pull_data().
[1] https://lore.kernel.org/bpf/aqkhifLvyAhw66jg@gmail.com/#t (local)
quoted hunk ↗ jump to hunk
Fixes: 80f281664f5a ("bpf: Support pointers in global func args") Reported-by: Nicholas Carlini <redacted> Suggested-by: Nicholas Carlini <redacted> Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com> --- kernel/bpf/verifier.c | 10 ++++++++++ 1 file changed, 10 insertions(+)diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 6c6b8d852..507bc14b4 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c@@ -10375,6 +10375,16 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog, if (check_mem_reg(env, reg, argno, arg->mem_size, BPF_READ | BPF_WRITE, NULL, NULL)) return -EINVAL; + /* + * PTR_TO_PACKET get passed as PTR_TO_MEM, preventing + * us from adjusting bounds tracking info. + */ + if ((reg_is_pkt_pointer_any(reg) || reg_is_dynptr_slice_pkt(reg)) && + sub->changes_pkt_data) { + bpf_log(log, "%s is a packet pointer, but func#%d may change packet data\n", + reg_arg_name(env, argno), subprog); + return -EINVAL; + } if (!(arg->arg_type & PTR_MAYBE_NULL) && (type_may_be_null(reg->type) || bpf_register_is_null(reg))) { bpf_log(log, "%s is expected to be non-NULL\n", --2.54.0