diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 79b4f9ce194f1eb8b56b4369097d6c4256ac8c16..168c671de612f4ceb0a355f2bc3b2ec01d0cecea 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -702,6 +702,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean) rcu_assign_pointer(tun->tfiles[index], tun->tfiles[tun->numqueues - 1]); ntfile = rtnl_dereference(tun->tfiles[index]); + rcu_assign_pointer(tun->tfiles[tun->numqueues - 1], NULL); ntfile->queue_index = index; --tun->numqueues; @@ -1085,7 +1086,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) tfile = rcu_dereference(tun->tfiles[txq]); /* Drop packet if interface is not attached */ - if (txq >= tun->numqueues) + if (!tfile) goto drop; if (!rcu_dereference(tun->steering_prog)) @@ -1266,7 +1267,6 @@ static int tun_xdp_xmit(struct net_device *dev, int n, { struct tun_struct *tun = netdev_priv(dev); struct tun_file *tfile; - u32 numqueues; int drops = 0; int cnt = n; int i; @@ -1276,15 +1276,13 @@ static int tun_xdp_xmit(struct net_device *dev, int n, rcu_read_lock(); - numqueues = READ_ONCE(tun->numqueues); - if (!numqueues) { + tfile = rcu_dereference(tun->tfiles[smp_processor_id() % + tun->numqueues]); + if (!tfile) { rcu_read_unlock(); return -ENXIO; /* Caller will free/return all frames */ } - tfile = rcu_dereference(tun->tfiles[smp_processor_id() % - numqueues]); - spin_lock(&tfile->tx_ring.producer_lock); for (i = 0; i < n; i++) { struct xdp_frame *xdp = frames[i];