diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2014-06-30 21:37:52 +0400 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2014-06-30 21:37:52 +0400 |
commit | a79b3fb7c894cd5a8eddac5679a986722390ff59 (patch) | |
tree | 052c01c927ba13e5cc05dcb65790db4fc5315ce6 /drivers | |
parent | d2b65bb7c8f0e6689682daadd47770c5c40cd85d (diff) | |
download | accel-ppp-xebd-a79b3fb7c894cd5a8eddac5679a986722390ff59.tar.gz accel-ppp-xebd-a79b3fb7c894cd5a8eddac5679a986722390ff59.zip |
ipoe: driver: fixed locking and rcu semantics
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ipoe/ipoe.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c index eb8f8de..987c5e7 100644 --- a/drivers/ipoe/ipoe.c +++ b/drivers/ipoe/ipoe.c @@ -860,12 +860,16 @@ static int vlan_pt_recv(struct sk_buff *skb, struct net_device *dev, struct pack if (!dev->ml_priv) goto out; - d = dev->ml_priv; - if (d->magic != IPOE_MAGIC2 || d->ifindex != dev->ifindex) + if (!vlan_tx_tag_present(skb)) goto out; - if (!vlan_tx_tag_present(skb)) + rcu_read_lock(); + + d = rcu_dereference(dev->ml_priv); + if (!d || d->magic != IPOE_MAGIC2 || d->ifindex != dev->ifindex) { + rcu_read_unlock(); goto out; + } vid = skb->vlan_tci & VLAN_VID_MASK; //pr_info("vid %i\n", vid); @@ -1627,14 +1631,17 @@ static int ipoe_nl_cmd_add_vlan_mon(struct sk_buff *skb, struct genl_info *info) if (!dev) return -ENODEV; - + + down(&ipoe_wlock); if (dev->ml_priv) { + up(&ipoe_wlock); dev_put(dev); return -EBUSY; } - + d = kzalloc(sizeof(*d), GFP_KERNEL); if (!d) { + up(&ipoe_wlock); dev_put(dev); return -ENOMEM; } @@ -1643,8 +1650,6 @@ static int ipoe_nl_cmd_add_vlan_mon(struct sk_buff *skb, struct genl_info *info) d->ifindex = ifindex; spin_lock_init(&d->lock); - dev->ml_priv = d; - if (info->attrs[IPOE_ATTR_VLAN_MASK]) { memcpy(d->vid, nla_data(info->attrs[IPOE_ATTR_VLAN_MASK]), min((int)nla_len(info->attrs[IPOE_ATTR_VLAN_MASK]), (int)sizeof(d->vid))); @@ -1665,12 +1670,13 @@ static int ipoe_nl_cmd_add_vlan_mon(struct sk_buff *skb, struct genl_info *info) #endif } - dev_put(dev); + rcu_assign_pointer(dev->ml_priv, d); - down(&ipoe_wlock); list_add_tail_rcu(&d->entry, &vlan_devices); up(&ipoe_wlock); + dev_put(dev); + return 0; } @@ -1697,14 +1703,17 @@ static int ipoe_nl_cmd_add_vlan_mon_vid(struct sk_buff *skb, struct genl_info *i if (!dev) return -ENODEV; - + + down(&ipoe_wlock); + if (!dev->ml_priv) { + up(&ipoe_wlock); dev_put(dev); return -EINVAL; } d = dev->ml_priv; - + spin_lock_irqsave(&d->lock, flags); d->vid[vid / (8*sizeof(long))] &= ~(1lu << (vid % (8*sizeof(long)))); spin_unlock_irqrestore(&d->lock, flags); @@ -1715,7 +1724,9 @@ static int ipoe_nl_cmd_add_vlan_mon_vid(struct sk_buff *skb, struct genl_info *i if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) dev->netdev_ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q), vid); #endif - + + up(&ipoe_wlock); + dev_put(dev); return 0; @@ -1749,7 +1760,7 @@ static int ipoe_nl_cmd_del_vlan_mon(struct sk_buff *skb, struct genl_info *info) if (dev) { if (dev->ml_priv == d) - dev->ml_priv = NULL; + rcu_assign_pointer(dev->ml_priv, NULL); dev_put(dev); } @@ -1924,7 +1935,7 @@ static int __init ipoe_init(void) { int err, i; - printk("IPoE session driver v1.8.0.1\n"); + printk("IPoE session driver v1.8.0.2\n"); /*err = register_pernet_device(&ipoe_net_ops); if (err < 0) |