Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 573201f3 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

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: default avatarHerbert Xu <herbert@gondor.apana.org.au>

Thanks,
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 45e77d31
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -217,14 +217,6 @@ static bool br_devices_support_netpoll(struct net_bridge *br)
	return count != 0 && ret;
}

static void br_poll_controller(struct net_device *br_dev)
{
	struct netpoll *np = br_dev->npinfo->netpoll;

	if (np->real_dev != br_dev)
		netpoll_poll_dev(np->real_dev);
}

void br_netpoll_cleanup(struct net_device *dev)
{
	struct net_bridge *br = netdev_priv(dev);
@@ -295,7 +287,6 @@ static const struct net_device_ops br_netdev_ops = {
	.ndo_do_ioctl		 = br_dev_ioctl,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_netpoll_cleanup	 = br_netpoll_cleanup,
	.ndo_poll_controller	 = br_poll_controller,
#endif
};

+1 −22
Original line number Diff line number Diff line
@@ -50,13 +50,6 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
			kfree_skb(skb);
		else {
			skb_push(skb, ETH_HLEN);

#ifdef CONFIG_NET_POLL_CONTROLLER
			if (unlikely(skb->dev->priv_flags & IFF_IN_NETPOLL)) {
				netpoll_send_skb(skb->dev->npinfo->netpoll, skb);
				skb->dev->priv_flags &= ~IFF_IN_NETPOLL;
			} else
#endif
			dev_queue_xmit(skb);
		}
	}
@@ -73,23 +66,9 @@ int br_forward_finish(struct sk_buff *skb)

static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
{
#ifdef CONFIG_NET_POLL_CONTROLLER
	struct net_bridge *br = to->br;
	if (unlikely(br->dev->priv_flags & IFF_IN_NETPOLL)) {
		struct netpoll *np;
		to->dev->npinfo = skb->dev->npinfo;
		np = skb->dev->npinfo->netpoll;
		np->real_dev = np->dev = to->dev;
		to->dev->priv_flags |= IFF_IN_NETPOLL;
	}
#endif
	skb->dev = to->dev;
	NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
		br_forward_finish);
#ifdef CONFIG_NET_POLL_CONTROLLER
	if (skb->dev->npinfo)
		skb->dev->npinfo->netpoll->dev = br->dev;
#endif
}

static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)