summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/tun-Assign-missing-bpf_net_context.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/tun-Assign-missing-bpf_net_context.patch')
-rw-r--r--debian/patches-rt/tun-Assign-missing-bpf_net_context.patch114
1 files changed, 114 insertions, 0 deletions
diff --git a/debian/patches-rt/tun-Assign-missing-bpf_net_context.patch b/debian/patches-rt/tun-Assign-missing-bpf_net_context.patch
new file mode 100644
index 0000000000..1d16417b19
--- /dev/null
+++ b/debian/patches-rt/tun-Assign-missing-bpf_net_context.patch
@@ -0,0 +1,114 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 4 Jul 2024 16:48:15 +0200
+Subject: [PATCH] tun: Assign missing bpf_net_context.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.10/older/patches-6.10.2-rt14.tar.xz
+
+During the introduction of struct bpf_net_context handling for
+XDP-redirect, the tun driver has been missed.
+Jakub also pointed out that there is another call chain to
+do_xdp_generic() originating from netif_receive_skb() and drivers may
+use it outside from the NAPI context.
+
+Set the bpf_net_context before invoking BPF XDP program within the TUN
+driver. Set the bpf_net_context also in do_xdp_generic() if a xdp
+program is available.
+
+Reported-by: syzbot+0b5c75599f1d872bea6f@syzkaller.appspotmail.com
+Reported-by: syzbot+5ae46b237278e2369cac@syzkaller.appspotmail.com
+Reported-by: syzbot+c1e04a422bbc0f0f2921@syzkaller.appspotmail.com
+Fixes: 401cb7dae8130 ("net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.")
+Link: https://lore.kernel.org/r/20240704144815.j8xQda5r@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/net/tun.c | 7 +++++++
+ net/core/dev.c | 5 +++++
+ 2 files changed, 12 insertions(+)
+
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -1661,6 +1661,7 @@ static struct sk_buff *tun_build_skb(str
+ int len, int *skb_xdp)
+ {
+ struct page_frag *alloc_frag = &current->task_frag;
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ struct bpf_prog *xdp_prog;
+ int buflen = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ char *buf;
+@@ -1700,6 +1701,7 @@ static struct sk_buff *tun_build_skb(str
+
+ local_bh_disable();
+ rcu_read_lock();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+ xdp_prog = rcu_dereference(tun->xdp_prog);
+ if (xdp_prog) {
+ struct xdp_buff xdp;
+@@ -1728,12 +1730,14 @@ static struct sk_buff *tun_build_skb(str
+ pad = xdp.data - xdp.data_hard_start;
+ len = xdp.data_end - xdp.data;
+ }
++ bpf_net_ctx_clear(bpf_net_ctx);
+ rcu_read_unlock();
+ local_bh_enable();
+
+ return __tun_build_skb(tfile, alloc_frag, buf, buflen, len, pad);
+
+ out:
++ bpf_net_ctx_clear(bpf_net_ctx);
+ rcu_read_unlock();
+ local_bh_enable();
+ return NULL;
+@@ -2566,6 +2570,7 @@ static int tun_sendmsg(struct socket *so
+
+ if (m->msg_controllen == sizeof(struct tun_msg_ctl) &&
+ ctl && ctl->type == TUN_MSG_PTR) {
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ struct tun_page tpage;
+ int n = ctl->num;
+ int flush = 0, queued = 0;
+@@ -2574,6 +2579,7 @@ static int tun_sendmsg(struct socket *so
+
+ local_bh_disable();
+ rcu_read_lock();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+
+ for (i = 0; i < n; i++) {
+ xdp = &((struct xdp_buff *)ctl->ptr)[i];
+@@ -2588,6 +2594,7 @@ static int tun_sendmsg(struct socket *so
+ if (tfile->napi_enabled && queued > 0)
+ napi_schedule(&tfile->napi);
+
++ bpf_net_ctx_clear(bpf_net_ctx);
+ rcu_read_unlock();
+ local_bh_enable();
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -5126,11 +5126,14 @@ static DEFINE_STATIC_KEY_FALSE(generic_x
+
+ int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff **pskb)
+ {
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
++
+ if (xdp_prog) {
+ struct xdp_buff xdp;
+ u32 act;
+ int err;
+
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+ act = netif_receive_generic_xdp(pskb, &xdp, xdp_prog);
+ if (act != XDP_PASS) {
+ switch (act) {
+@@ -5144,11 +5147,13 @@ int do_xdp_generic(struct bpf_prog *xdp_
+ generic_xdp_tx(*pskb, xdp_prog);
+ break;
+ }
++ bpf_net_ctx_clear(bpf_net_ctx);
+ return XDP_DROP;
+ }
+ }
+ return XDP_PASS;
+ out_redir:
++ bpf_net_ctx_clear(bpf_net_ctx);
+ kfree_skb_reason(*pskb, SKB_DROP_REASON_XDP);
+ return XDP_DROP;
+ }