Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tun: Assign missing bpf_net_context.

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.")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://patch.msgid.link/20240704144815.j8xQda5r@linutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Sebastian Andrzej Siewior and committed by
Jakub Kicinski
fecef4cd 3b2aef99

+12
+7
drivers/net/tun.c
··· 1661 1661 int len, int *skb_xdp) 1662 1662 { 1663 1663 struct page_frag *alloc_frag = &current->task_frag; 1664 + struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx; 1664 1665 struct bpf_prog *xdp_prog; 1665 1666 int buflen = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 1666 1667 char *buf; ··· 1701 1700 1702 1701 local_bh_disable(); 1703 1702 rcu_read_lock(); 1703 + bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx); 1704 1704 xdp_prog = rcu_dereference(tun->xdp_prog); 1705 1705 if (xdp_prog) { 1706 1706 struct xdp_buff xdp; ··· 1730 1728 pad = xdp.data - xdp.data_hard_start; 1731 1729 len = xdp.data_end - xdp.data; 1732 1730 } 1731 + bpf_net_ctx_clear(bpf_net_ctx); 1733 1732 rcu_read_unlock(); 1734 1733 local_bh_enable(); 1735 1734 1736 1735 return __tun_build_skb(tfile, alloc_frag, buf, buflen, len, pad); 1737 1736 1738 1737 out: 1738 + bpf_net_ctx_clear(bpf_net_ctx); 1739 1739 rcu_read_unlock(); 1740 1740 local_bh_enable(); 1741 1741 return NULL; ··· 2570 2566 2571 2567 if (m->msg_controllen == sizeof(struct tun_msg_ctl) && 2572 2568 ctl && ctl->type == TUN_MSG_PTR) { 2569 + struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx; 2573 2570 struct tun_page tpage; 2574 2571 int n = ctl->num; 2575 2572 int flush = 0, queued = 0; ··· 2579 2574 2580 2575 local_bh_disable(); 2581 2576 rcu_read_lock(); 2577 + bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx); 2582 2578 2583 2579 for (i = 0; i < n; i++) { 2584 2580 xdp = &((struct xdp_buff *)ctl->ptr)[i]; ··· 2594 2588 if (tfile->napi_enabled && queued > 0) 2595 2589 napi_schedule(&tfile->napi); 2596 2590 2591 + bpf_net_ctx_clear(bpf_net_ctx); 2597 2592 rcu_read_unlock(); 2598 2593 local_bh_enable(); 2599 2594
+5
net/core/dev.c
··· 5126 5126 5127 5127 int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff **pskb) 5128 5128 { 5129 + struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx; 5130 + 5129 5131 if (xdp_prog) { 5130 5132 struct xdp_buff xdp; 5131 5133 u32 act; 5132 5134 int err; 5133 5135 5136 + bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx); 5134 5137 act = netif_receive_generic_xdp(pskb, &xdp, xdp_prog); 5135 5138 if (act != XDP_PASS) { 5136 5139 switch (act) { ··· 5147 5144 generic_xdp_tx(*pskb, xdp_prog); 5148 5145 break; 5149 5146 } 5147 + bpf_net_ctx_clear(bpf_net_ctx); 5150 5148 return XDP_DROP; 5151 5149 } 5152 5150 } 5153 5151 return XDP_PASS; 5154 5152 out_redir: 5153 + bpf_net_ctx_clear(bpf_net_ctx); 5155 5154 kfree_skb_reason(*pskb, SKB_DROP_REASON_XDP); 5156 5155 return XDP_DROP; 5157 5156 }