aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-01-30 07:23:03 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-03 23:20:32 -0500
commit8a83a00b0735190384a348156837918271034144 (patch)
treef69d903405e2424c196d8648bb6cb18443359373
parent6884b348ed759184032306c9435a727741a72298 (diff)
net: maintain namespace isolation between vlan and real device
In the vlan and macvlan drivers, the start_xmit function forwards data to the dev_queue_xmit function for another device, which may potentially belong to a different namespace. To make sure that classification stays within a single namespace, this resets the potentially critical fields. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/macvlan.c2
-rw-r--r--include/linux/netdevice.h9
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/core/dev.c35
4 files changed, 42 insertions, 6 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index fa0dc514dbaf..d32e0bdfc5e9 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -269,7 +269,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
269 } 269 }
270 270
271xmit_world: 271xmit_world:
272 skb->dev = vlan->lowerdev; 272 skb_set_dev(skb, vlan->lowerdev);
273 return dev_queue_xmit(skb); 273 return dev_queue_xmit(skb);
274} 274}
275 275
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 93a32a5ca74f..622ba5aa93c4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1004,6 +1004,15 @@ static inline bool netdev_uses_dsa_tags(struct net_device *dev)
1004 return 0; 1004 return 0;
1005} 1005}
1006 1006
1007#ifndef CONFIG_NET_NS
1008static inline void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
1009{
1010 skb->dev = dev;
1011}
1012#else /* CONFIG_NET_NS */
1013void skb_set_dev(struct sk_buff *skb, struct net_device *dev);
1014#endif
1015
1007static inline bool netdev_uses_trailer_tags(struct net_device *dev) 1016static inline bool netdev_uses_trailer_tags(struct net_device *dev)
1008{ 1017{
1009#ifdef CONFIG_NET_DSA_TAG_TRAILER 1018#ifdef CONFIG_NET_DSA_TAG_TRAILER
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index a9e1f1785614..9e83272fc5b0 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -322,7 +322,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
322 } 322 }
323 323
324 324
325 skb->dev = vlan_dev_info(dev)->real_dev; 325 skb_set_dev(skb, vlan_dev_info(dev)->real_dev);
326 len = skb->len; 326 len = skb->len;
327 ret = dev_queue_xmit(skb); 327 ret = dev_queue_xmit(skb);
328 328
diff --git a/net/core/dev.c b/net/core/dev.c
index 2cba5c521e56..94c1eeed25e5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1448,13 +1448,10 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
1448 if (skb->len > (dev->mtu + dev->hard_header_len)) 1448 if (skb->len > (dev->mtu + dev->hard_header_len))
1449 return NET_RX_DROP; 1449 return NET_RX_DROP;
1450 1450
1451 skb_dst_drop(skb); 1451 skb_set_dev(skb, dev);
1452 skb->tstamp.tv64 = 0; 1452 skb->tstamp.tv64 = 0;
1453 skb->pkt_type = PACKET_HOST; 1453 skb->pkt_type = PACKET_HOST;
1454 skb->protocol = eth_type_trans(skb, dev); 1454 skb->protocol = eth_type_trans(skb, dev);
1455 skb->mark = 0;
1456 secpath_reset(skb);
1457 nf_reset(skb);
1458 return netif_rx(skb); 1455 return netif_rx(skb);
1459} 1456}
1460EXPORT_SYMBOL_GPL(dev_forward_skb); 1457EXPORT_SYMBOL_GPL(dev_forward_skb);
@@ -1614,6 +1611,36 @@ static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
1614 return false; 1611 return false;
1615} 1612}
1616 1613
1614/**
1615 * skb_dev_set -- assign a new device to a buffer
1616 * @skb: buffer for the new device
1617 * @dev: network device
1618 *
1619 * If an skb is owned by a device already, we have to reset
1620 * all data private to the namespace a device belongs to
1621 * before assigning it a new device.
1622 */
1623#ifdef CONFIG_NET_NS
1624void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
1625{
1626 skb_dst_drop(skb);
1627 if (skb->dev && !net_eq(dev_net(skb->dev), dev_net(dev))) {
1628 secpath_reset(skb);
1629 nf_reset(skb);
1630 skb_init_secmark(skb);
1631 skb->mark = 0;
1632 skb->priority = 0;
1633 skb->nf_trace = 0;
1634 skb->ipvs_property = 0;
1635#ifdef CONFIG_NET_SCHED
1636 skb->tc_index = 0;
1637#endif
1638 }
1639 skb->dev = dev;
1640}
1641EXPORT_SYMBOL(skb_set_dev);
1642#endif /* CONFIG_NET_NS */
1643
1617/* 1644/*
1618 * Invalidate hardware checksum when packet is to be mangled, and 1645 * Invalidate hardware checksum when packet is to be mangled, and
1619 * complete checksum manually on outgoing path. 1646 * complete checksum manually on outgoing path.