diff options
| author | Herbert Xu <herbert@gondor.apana.org.au> | 2010-07-19 15:26:45 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-07-20 02:28:25 -0400 |
| commit | 573201f36fd9c7c6d5218cdcd9948cee700b277d (patch) | |
| tree | 3fdd5cd05e26fdfe38d5d1a72b4d4aa41ecd181f | |
| parent | 45e77d314585869dfe43c82679f7e08c9b35b898 (diff) | |
bridge: Partially disable netpoll support
The new netpoll code in bridging contains use-after-free bugs
that are non-trivial to fix.
This patch fixes this by removing the code that uses skbs after
they're freed.
As a consequence, this means that we can no longer call bridge
from the netpoll path, so this patch also removes the controller
function in order to disable netpoll.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Thanks,
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/bridge/br_device.c | 9 | ||||
| -rw-r--r-- | net/bridge/br_forward.c | 23 |
2 files changed, 1 insertions, 31 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index eedf2c94820e..753fc4221f3c 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
| @@ -217,14 +217,6 @@ static bool br_devices_support_netpoll(struct net_bridge *br) | |||
| 217 | return count != 0 && ret; | 217 | return count != 0 && ret; |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | static void br_poll_controller(struct net_device *br_dev) | ||
| 221 | { | ||
| 222 | struct netpoll *np = br_dev->npinfo->netpoll; | ||
| 223 | |||
| 224 | if (np->real_dev != br_dev) | ||
| 225 | netpoll_poll_dev(np->real_dev); | ||
| 226 | } | ||
| 227 | |||
| 228 | void br_netpoll_cleanup(struct net_device *dev) | 220 | void br_netpoll_cleanup(struct net_device *dev) |
| 229 | { | 221 | { |
| 230 | struct net_bridge *br = netdev_priv(dev); | 222 | struct net_bridge *br = netdev_priv(dev); |
| @@ -295,7 +287,6 @@ static const struct net_device_ops br_netdev_ops = { | |||
| 295 | .ndo_do_ioctl = br_dev_ioctl, | 287 | .ndo_do_ioctl = br_dev_ioctl, |
| 296 | #ifdef CONFIG_NET_POLL_CONTROLLER | 288 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 297 | .ndo_netpoll_cleanup = br_netpoll_cleanup, | 289 | .ndo_netpoll_cleanup = br_netpoll_cleanup, |
| 298 | .ndo_poll_controller = br_poll_controller, | ||
| 299 | #endif | 290 | #endif |
| 300 | }; | 291 | }; |
| 301 | 292 | ||
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index a4e72a89e4ff..595da45f9088 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
| @@ -50,14 +50,7 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) | |||
| 50 | kfree_skb(skb); | 50 | kfree_skb(skb); |
| 51 | else { | 51 | else { |
| 52 | skb_push(skb, ETH_HLEN); | 52 | skb_push(skb, ETH_HLEN); |
| 53 | 53 | dev_queue_xmit(skb); | |
| 54 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 55 | if (unlikely(skb->dev->priv_flags & IFF_IN_NETPOLL)) { | ||
| 56 | netpoll_send_skb(skb->dev->npinfo->netpoll, skb); | ||
| 57 | skb->dev->priv_flags &= ~IFF_IN_NETPOLL; | ||
| 58 | } else | ||
| 59 | #endif | ||
| 60 | dev_queue_xmit(skb); | ||
| 61 | } | 54 | } |
| 62 | } | 55 | } |
| 63 | 56 | ||
| @@ -73,23 +66,9 @@ int br_forward_finish(struct sk_buff *skb) | |||
| 73 | 66 | ||
| 74 | static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | 67 | static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) |
| 75 | { | 68 | { |
| 76 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 77 | struct net_bridge *br = to->br; | ||
| 78 | if (unlikely(br->dev->priv_flags & IFF_IN_NETPOLL)) { | ||
| 79 | struct netpoll *np; | ||
| 80 | to->dev->npinfo = skb->dev->npinfo; | ||
| 81 | np = skb->dev->npinfo->netpoll; | ||
| 82 | np->real_dev = np->dev = to->dev; | ||
| 83 | to->dev->priv_flags |= IFF_IN_NETPOLL; | ||
| 84 | } | ||
| 85 | #endif | ||
| 86 | skb->dev = to->dev; | 69 | skb->dev = to->dev; |
| 87 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, | 70 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
| 88 | br_forward_finish); | 71 | br_forward_finish); |
| 89 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 90 | if (skb->dev->npinfo) | ||
| 91 | skb->dev->npinfo->netpoll->dev = br->dev; | ||
| 92 | #endif | ||
| 93 | } | 72 | } |
| 94 | 73 | ||
| 95 | static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | 74 | static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) |
