Patchwork vlan: fix a race in egress prio management

login
register
mail settings
Submitter Eric Dumazet
Date July 18, 2013, 4:35 p.m.
Message ID <1374165310.6097.39.camel@edumazet-glaptop>
Download mbox | patch
Permalink /patch/260091/
State Accepted
Delegated to: David Miller
Headers show

Comments

Eric Dumazet - July 18, 2013, 4:35 p.m.
From: Eric Dumazet <edumazet@google.com>

egress_priority_map[] hash table updates are protected by rtnl,
and we never remove elements until device is dismantled.

We have to make sure that before inserting an new element in hash table,
all its fields are committed to memory or else another cpu could
find corrupt values and crash.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Patrick McHardy <kaber@trash.net>
---
 net/8021q/vlan_dev.c |    7 +++++++
 1 file changed, 7 insertions(+)



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller - July 18, 2013, 8:07 p.m.
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 18 Jul 2013 09:35:10 -0700

> From: Eric Dumazet <edumazet@google.com>
> 
> egress_priority_map[] hash table updates are protected by rtnl,
> and we never remove elements until device is dismantled.
> 
> We have to make sure that before inserting an new element in hash table,
> all its fields are committed to memory or else another cpu could
> find corrupt values and crash.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied and queued up for -stable, thanks.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 3a8c8fd..1cd3d2a 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -73,6 +73,8 @@  vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb)
 {
 	struct vlan_priority_tci_mapping *mp;
 
+	smp_rmb(); /* coupled with smp_wmb() in vlan_dev_set_egress_priority() */
+
 	mp = vlan_dev_priv(dev)->egress_priority_map[(skb->priority & 0xF)];
 	while (mp) {
 		if (mp->priority == skb->priority) {
@@ -249,6 +251,11 @@  int vlan_dev_set_egress_priority(const struct net_device *dev,
 	np->next = mp;
 	np->priority = skb_prio;
 	np->vlan_qos = vlan_qos;
+	/* Before inserting this element in hash table, make sure all its fields
+	 * are committed to memory.
+	 * coupled with smp_rmb() in vlan_dev_get_egress_qos_mask()
+	 */
+	smp_wmb();
 	vlan->egress_priority_map[skb_prio & 0xF] = np;
 	if (vlan_qos)
 		vlan->nr_egress_mappings++;