diff options
author | Arnd Bergmann <arnd@arndb.de> | 2010-01-30 07:23:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-03 23:20:32 -0500 |
commit | 8a83a00b0735190384a348156837918271034144 (patch) | |
tree | f69d903405e2424c196d8648bb6cb18443359373 | |
parent | 6884b348ed759184032306c9435a727741a72298 (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.c | 2 | ||||
-rw-r--r-- | include/linux/netdevice.h | 9 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 2 | ||||
-rw-r--r-- | net/core/dev.c | 35 |
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 | ||
271 | xmit_world: | 271 | xmit_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 | ||
1008 | static inline void skb_set_dev(struct sk_buff *skb, struct net_device *dev) | ||
1009 | { | ||
1010 | skb->dev = dev; | ||
1011 | } | ||
1012 | #else /* CONFIG_NET_NS */ | ||
1013 | void skb_set_dev(struct sk_buff *skb, struct net_device *dev); | ||
1014 | #endif | ||
1015 | |||
1007 | static inline bool netdev_uses_trailer_tags(struct net_device *dev) | 1016 | static 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 | } |
1460 | EXPORT_SYMBOL_GPL(dev_forward_skb); | 1457 | EXPORT_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 | ||
1624 | void 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 | } | ||
1641 | EXPORT_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. |