tun: Multicast handling in tun_chr_ioctl() needs proper locking.

Since these operations don't go through the normal
device calls, we have to ensure we synchronize with
those paths.

Noticed by Alan Cox.

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2008-04-24 03:44:43 -07:00
parent 5e659e4cb0
commit 9edb74cc6c
1 changed files with 10 additions and 0 deletions

View File

@ -741,7 +741,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
case SIOCADDMULTI: case SIOCADDMULTI:
/** Add the specified group to the character device's multicast filter /** Add the specified group to the character device's multicast filter
* list. */ * list. */
rtnl_lock();
netif_tx_lock_bh(tun->dev);
add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data); add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
netif_tx_unlock_bh(tun->dev);
rtnl_unlock();
DBG(KERN_DEBUG "%s: add multi: %s\n", DBG(KERN_DEBUG "%s: add multi: %s\n",
tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data)); tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
return 0; return 0;
@ -749,7 +754,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
case SIOCDELMULTI: case SIOCDELMULTI:
/** Remove the specified group from the character device's multicast /** Remove the specified group from the character device's multicast
* filter list. */ * filter list. */
rtnl_lock();
netif_tx_lock_bh(tun->dev);
del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data); del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
netif_tx_unlock_bh(tun->dev);
rtnl_unlock();
DBG(KERN_DEBUG "%s: del multi: %s\n", DBG(KERN_DEBUG "%s: del multi: %s\n",
tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data)); tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
return 0; return 0;