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>
Unified · Split
| @@ -217,14 +217,6 @@ static bool br_devices_support_netpoll(struct net_bridge *br) · 216 unmodified lines | ||
| 217 | 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 | 220 | void br_netpoll_cleanup(struct net_device *dev) |
| 229 | 221 | { |
| 230 | 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 | 287 | .ndo_do_ioctl = br_dev_ioctl, |
| 296 | 288 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 297 | 289 | .ndo_netpoll_cleanup = br_netpoll_cleanup, |
| 298 | − .ndo_poll_controller = br_poll_controller, | |
| 299 | 290 | #endif |
| 300 | 291 | }; |
| 301 | 292 | |
| @@ -50,14 +50,7 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) · 49 unmodified lines | ||
| 50 | 50 | kfree_skb(skb); |
| 51 | 51 | else { |
| 52 | 52 | skb_push(skb, ETH_HLEN); |
| 53 | − | |
| 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); | |
| 53 | + 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 | |
| 74 | 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 | 69 | skb->dev = to->dev; |
| 87 | 70 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
| 88 | 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 | 74 | static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) |