浏览代码

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>
David S. Miller 17 年之前
父节点
当前提交
9edb74cc6c
共有 1 个文件被更改,包括 10 次插入0 次删除
  1. 10 0
      drivers/net/tun.c

+ 10 - 0
drivers/net/tun.c

@@ -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;