Skip to content

Commit

Permalink
macvtap: Fix race between device delete and open.
Browse files Browse the repository at this point in the history
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 <[email protected]>
CC: Jason Wang <[email protected]>
Signed-off-by: Vladislav Yasevich <[email protected]>
Acked-by: Jason Wang <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
vyasevich authored and davem330 committed Sep 26, 2014
1 parent 2b07f0d commit 40b8fe4
Showing 1 changed file with 8 additions and 10 deletions.
18 changes: 8 additions & 10 deletions drivers/net/macvtap.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,15 @@ static int macvtap_enable_queue(struct net_device *dev, struct file *file,
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);
Expand All @@ -136,9 +134,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)
Expand Down Expand Up @@ -454,11 +450,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;

Expand Down Expand Up @@ -498,6 +495,7 @@ static int macvtap_open(struct inode *inode, struct file *file)
if (dev)
dev_put(dev);

rtnl_unlock();
return err;
}

Expand Down

0 comments on commit 40b8fe4

Please sign in to comment.