summaryrefslogtreecommitdiff
path: root/include/linux/bpf_verifier.h
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2026-10-19 01:13:27 +0000
committerKumar Kartikeya Dwivedi <memxor@gmail.com>2026-10-19 04:23:55 +0200
commit4f842631f178f41baa2d2d444a277d54c07666a1 (patch)
tree35a25665f0e089829a9ac9b537ca1c636a68411c /include/linux/bpf_verifier.h
parente2c978ad415ce223e71f6ddaa92778225eca0bef (diff)
bpf: Refuse the prologue for an extension if callers keep packet pointers
An extension that writes to the packet of a tc, lwt_xmit or sk_skb program starts with bpf_unclone_prologue(). If the skb is cloned, that gives it a new head. It does not count as changing packet data. changes_pkt_data goes by the helpers and kfuncs that a program calls, and whether it gets a prologue is known only after it has been compared with its target. So the extension can replace a global function that leaves the packet alone, and the callers of that function keep their packet pointers across the call. These point into the old head, which is left to the other clone. Once that is freed, by the reader of a packet socket for example: BUG: KASAN: slab-use-after-free in bpf_prog_53bc21b9810cadbc_t_read+0x2e8/0x36e Read of size 1 at addr ffff888107bfe73c by task tt11/102 Freed by task 112: kfree+0x161/0x500 skb_release_data+0x2dc/0x340 consume_skb+0xa6/0x1c0 packet_recvmsg+0x4b3/0xa20 Nothing is wrong if the target program writes to the packet too: its own prologue has uncloned the skb, and that of the extension does nothing. Nor if the callers hold no packet pointers, like a dispatcher, or if the main function is replaced. Note for every global function that leaves the packet alone if it is called while packet pointers, or slices of the dynptr of a packet, are held. What the callers of a global function hold is not known while it is verified, so the functions that it calls are taken for such as well. Refuse an extension with a prologue for such a function, unless the target program has a prologue, both when the extension is loaded and when it is attached to another target. Functions can share a type id in func_info. The first of them is the one that is replaced, so look it up in one place. Fixes: 7e40781cc8b7 ("bpf: verifier: Use target program's type for access verifications") Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20261019011328.1843764-1-alexei.starovoitov@gmail.com Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Diffstat (limited to 'include/linux/bpf_verifier.h')
-rw-r--r--include/linux/bpf_verifier.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 7a72bb06fe56..951a90458d18 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -1381,6 +1381,8 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
const struct bpf_prog *tgt_prog,
u32 btf_id,
struct bpf_attach_target_info *tgt_info);
+int bpf_check_ext_prologue(struct bpf_verifier_log *log,
+ const struct bpf_prog *tgt_prog, u32 btf_id);
void bpf_free_kfunc_btf_tab(struct bpf_kfunc_btf_tab *tab);
int mark_chain_precision(struct bpf_verifier_env *env, int regno);