History

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>

Herbert Xu committed 16 years ago

Commit 573201f1 parent 45e77d32 files · +1 −31Browse files

Unified · Split

2 files
  1. net/bridge/br_device.c +0 −9
  2. net/bridge/br_forward.c +1 −22
net/bridge/br_device.c+0−9
@@ -217,14 +217,6 @@ static bool br_devices_support_netpoll(struct net_bridge *br) · 216 unmodified lines
217 return count != 0 && ret;217 return count != 0 && ret;
218}218}
219 219
220static 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
228void br_netpoll_cleanup(struct net_device *dev)220void 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 = { · 64 unmodified lines
295 .ndo_do_ioctl = br_dev_ioctl,287 .ndo_do_ioctl = br_dev_ioctl,
296#ifdef CONFIG_NET_POLL_CONTROLLER288#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#endif290#endif
300};291};
301 292
net/bridge/br_forward.c+1−22
@@ -50,14 +50,7 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) · 49 unmodified lines
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) · 9 unmodified lines
73 66
74static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)67static 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
95static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)74static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)