[3.13.y.z extended stable] Patch "macvtap: Fix race between device delete and open." has been added to staging queue

Kamal Mostafa kamal at canonical.com
Fri Oct 31 20:53:23 UTC 2014


This is a note to let you know that I have just added a patch titled

    macvtap: Fix race between device delete and open.

to the linux-3.13.y-queue branch of the 3.13.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.13.y-queue

This patch is scheduled to be released in version 3.13.11.11.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.13.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

------

>From 7eaa5736087709ad59d555fdefb1d356d4d61a8f Mon Sep 17 00:00:00 2001
From: Vlad Yasevich <vyasevich at gmail.com>
Date: Mon, 22 Sep 2014 16:34:17 -0400
Subject: macvtap: Fix race between device delete and open.

[ Upstream commit 40b8fe45d1f094e3babe7b2dc2b71557ab71401d ]

In macvtap device delete and open calls can race and
this causes a list curruption of the vlan queue_list.

The race intself is triggered by the idr accessors
that located the vlan device.  The device is stored
into and removed from the idr under both an rtnl and
a mutex.  However, when attempting to locate the device
in idr, only a mutex is taken.  As a result, once cpu
perfoming a delete may take an rtnl and wait for the mutex,
while another cput doing an open() will take the idr
mutex first to fetch the device pointer and later take
an rtnl to add a queue for the device which may have
just gotten deleted.

With this patch, we now hold the rtnl for the duration
of the macvtap_open() call thus making sure that
open will not race with delete.

CC: Michael S. Tsirkin <mst at redhat.com>
CC: Jason Wang <jasowang at redhat.com>
Signed-off-by: Vladislav Yasevich <vyasevic at redhat.com>
Acked-by: Jason Wang <jasowang at redhat.com>
Acked-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
 drivers/net/macvtap.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 73ffad8..eed7544 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -108,17 +108,15 @@ out:
 	return err;
 }

+/* Requires RTNL */
 static int macvtap_set_queue(struct net_device *dev, struct file *file,
 			     struct macvtap_queue *q)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
-	int err = -EBUSY;

-	rtnl_lock();
 	if (vlan->numqueues == MAX_MACVTAP_QUEUES)
-		goto out;
+		return -EBUSY;

-	err = 0;
 	rcu_assign_pointer(q->vlan, vlan);
 	rcu_assign_pointer(vlan->taps[vlan->numvtaps], q);
 	sock_hold(&q->sk);
@@ -132,9 +130,7 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file,
 	vlan->numvtaps++;
 	vlan->numqueues++;

-out:
-	rtnl_unlock();
-	return err;
+	return 0;
 }

 static int macvtap_disable_queue(struct macvtap_queue *q)
@@ -450,11 +446,12 @@ static void macvtap_sock_destruct(struct sock *sk)
 static int macvtap_open(struct inode *inode, struct file *file)
 {
 	struct net *net = current->nsproxy->net_ns;
-	struct net_device *dev = dev_get_by_macvtap_minor(iminor(inode));
+	struct net_device *dev;
 	struct macvtap_queue *q;
-	int err;
+	int err = -ENODEV;

-	err = -ENODEV;
+	rtnl_lock();
+	dev = dev_get_by_macvtap_minor(iminor(inode));
 	if (!dev)
 		goto out;

@@ -494,6 +491,7 @@ out:
 	if (dev)
 		dev_put(dev);

+	rtnl_unlock();
 	return err;
 }

--
1.9.1





More information about the kernel-team mailing list