Commit 9871a9e4 authored by Jason Wang's avatar Jason Wang Committed by David S. Miller
Browse files

tuntap: synchronize through tfiles array instead of tun->numqueues

When a queue(tfile) is detached through __tun_detach(), we move the
last enabled tfile to the position where detached one sit but don't
NULL out last position. We expect to synchronize the datapath through
tun->numqueues. Unfortunately, this won't work since we're lacking
sufficient mechanism to order or synchronize the access to

To fix this, NULL out the last position during detaching and check
RCU protected tfile against NULL instead of checking tun->numqueues in

Cc: YueHaibing <>
Cc: Cong Wang <>
Cc: weiyongjun (A) <>
Cc: Eric Dumazet <>
Fixes: c8d68e6b

 ("tuntap: multiqueue support")
Signed-off-by: default avatarJason Wang <>
Reviewed-by: default avatarWei Yongjun <>
Signed-off-by: default avatarDavid S. Miller <>
parent a35d310f
......@@ -704,6 +704,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
tun->tfiles[tun->numqueues - 1]);
ntfile = rtnl_dereference(tun->tfiles[index]);
ntfile->queue_index = index;
rcu_assign_pointer(tun->tfiles[tun->numqueues - 1],
if (clean) {
......@@ -1086,7 +1088,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))
......@@ -1309,6 +1311,7 @@ static int tun_xdp_xmit(struct net_device *dev, int n,
numqueues = READ_ONCE(tun->numqueues);
if (!numqueues) {
......@@ -1317,6 +1320,8 @@ static int tun_xdp_xmit(struct net_device *dev, int n,
tfile = rcu_dereference(tun->tfiles[smp_processor_id() %
if (unlikely(!tfile))
goto resample;
for (i = 0; i < n; i++) {
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment