diff mbox series

[net-net] tun: Assign missing bpf_net_context.

Message ID 20240703122758.i6lt_jii@linutronix.de (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net-net] tun: Assign missing bpf_net_context. | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 856 this patch: 22
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 4 maintainers not CCed: jasowang@redhat.com willemdebruijn.kernel@gmail.com pabeni@redhat.com edumazet@google.com
netdev/build_clang fail Errors and warnings before: 860 this patch: 25
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes fail Problems with Fixes tag: 1
netdev/build_allmodconfig_warn fail Errors and warnings before: 860 this patch: 22
netdev/checkpatch warning WARNING: Please use correct Fixes: style 'Fixes: <12 chars of sha1> ("<title line>")' - ie: 'Fixes: ("net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.")' WARNING: Unknown commit id '401cb7dae8130', maybe rebased or not pulled?
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Sebastian Andrzej Siewior July 3, 2024, 12:27 p.m. UTC
During the introduction of struct bpf_net_context handling for
XDP-redirect, the tun driver has been missed.

Set the bpf_net_context before invoking BPF XDP program within the TUN
driver.

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>
---
 drivers/net/tun.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

Comments

Jakub Kicinski July 3, 2024, 7:01 p.m. UTC | #1
On Wed, 3 Jul 2024 14:27:58 +0200 Sebastian Andrzej Siewior wrote:
> During the introduction of struct bpf_net_context handling for
> XDP-redirect, the tun driver has been missed.
> 
> Set the bpf_net_context before invoking BPF XDP program within the TUN
> driver.

Sorry if I'm missing the point but I think this is insufficient.
You've covered the NAPI-like entry point to the Rx stack in your
initial work, but there's also netif_receive_skb() which drivers 
may call outside of NAPI, simply disabling BH before the call.

The only concern in that case is that we end up in do_xdp_generic(),
and there's no bpf_net_set_ctx() anywhere on the way. So my intuition
would be to add the bpf_net_set_ctx() inside the if(xdp_prog) in
do_xdp_generic(). "XDP generic" has less stringent (more TC-like) 
perf requirements, so setting context once per packet should be fine.
And it will also cover drivers like TUN which use both
netif_receive_skb() and call do_xdp_generic(), in a single place.
Sebastian Andrzej Siewior July 3, 2024, 7:21 p.m. UTC | #2
On 2024-07-03 12:01:43 [-0700], Jakub Kicinski wrote:
> On Wed, 3 Jul 2024 14:27:58 +0200 Sebastian Andrzej Siewior wrote:
> > During the introduction of struct bpf_net_context handling for
> > XDP-redirect, the tun driver has been missed.
> > 
> > Set the bpf_net_context before invoking BPF XDP program within the TUN
> > driver.
> 
> Sorry if I'm missing the point but I think this is insufficient.
> You've covered the NAPI-like entry point to the Rx stack in your
> initial work, but there's also netif_receive_skb() which drivers 
> may call outside of NAPI, simply disabling BH before the call.

Ah okay. I've been looking at a few callers and they ended up in NAPI
but if you say and I also noticed the one in TUN…

> The only concern in that case is that we end up in do_xdp_generic(),
> and there's no bpf_net_set_ctx() anywhere on the way. So my intuition
> would be to add the bpf_net_set_ctx() inside the if(xdp_prog) in
> do_xdp_generic(). "XDP generic" has less stringent (more TC-like) 
> perf requirements, so setting context once per packet should be fine.
> And it will also cover drivers like TUN which use both
> netif_receive_skb() and call do_xdp_generic(), in a single place.

Yeah, sounds good. I would remove the wrapper in tun_get_user() and then
add one to do_xdp_generic().

Sebastian
diff mbox series

Patch

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 9254bca2813dc..df4dd6b7479e1 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1661,6 +1661,7 @@  static struct sk_buff *tun_build_skb(struct tun_struct *tun,
 				     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(struct tun_struct *tun,
 
 	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(struct tun_struct *tun,
 		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;
@@ -1914,20 +1918,24 @@  static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 	skb_record_rx_queue(skb, tfile->queue_index);
 
 	if (skb_xdp) {
+		struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
 		struct bpf_prog *xdp_prog;
 		int ret;
 
 		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) {
 			ret = do_xdp_generic(xdp_prog, &skb);
 			if (ret != XDP_PASS) {
+				bpf_net_ctx_clear(bpf_net_ctx);
 				rcu_read_unlock();
 				local_bh_enable();
 				goto unlock_frags;
 			}
 		}
+		bpf_net_ctx_clear(bpf_net_ctx);
 		rcu_read_unlock();
 		local_bh_enable();
 	}
@@ -2566,6 +2574,7 @@  static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
 
 	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 +2583,7 @@  static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
 
 		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 +2598,7 @@  static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
 		if (tfile->napi_enabled && queued > 0)
 			napi_schedule(&tfile->napi);
 
+		bpf_net_ctx_clear(bpf_net_ctx);
 		rcu_read_unlock();
 		local_bh_enable();