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

Commit 1ca2983a authored by Wei Liu's avatar Wei Liu Committed by David S. Miller
Browse files

xen-netfront: avoid leaking resources when setup_netfront fails



We should correctly free related resources (grant ref, memory page, evtchn)
when setup_netfront fails.

Signed-off-by: default avatarWei Liu <wei.liu2@citrix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6dffbe53
Loading
Loading
Loading
Loading
+21 −12
Original line number Original line Diff line number Diff line
@@ -1532,39 +1532,48 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
	FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
	FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);


	err = xenbus_grant_ring(dev, virt_to_mfn(txs));
	err = xenbus_grant_ring(dev, virt_to_mfn(txs));
	if (err < 0) {
	if (err < 0)
		free_page((unsigned long)txs);
		goto grant_tx_ring_fail;
		goto fail;
	}


	info->tx_ring_ref = err;
	info->tx_ring_ref = err;
	rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
	rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
	if (!rxs) {
	if (!rxs) {
		err = -ENOMEM;
		err = -ENOMEM;
		xenbus_dev_fatal(dev, err, "allocating rx ring page");
		xenbus_dev_fatal(dev, err, "allocating rx ring page");
		goto fail;
		goto alloc_rx_ring_fail;
	}
	}
	SHARED_RING_INIT(rxs);
	SHARED_RING_INIT(rxs);
	FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
	FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);


	err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
	err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
	if (err < 0) {
	if (err < 0)
		free_page((unsigned long)rxs);
		goto grant_rx_ring_fail;
		goto fail;
	}
	info->rx_ring_ref = err;
	info->rx_ring_ref = err;


	err = xenbus_alloc_evtchn(dev, &info->evtchn);
	err = xenbus_alloc_evtchn(dev, &info->evtchn);
	if (err)
	if (err)
		goto fail;
		goto alloc_evtchn_fail;


	err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt,
	err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt,
					0, netdev->name, netdev);
					0, netdev->name, netdev);
	if (err < 0)
	if (err < 0)
		goto fail;
		goto bind_fail;
	netdev->irq = err;
	netdev->irq = err;
	return 0;
	return 0;


	/* If we fail to setup netfront, it is safe to just revoke access to
	 * granted pages because backend is not accessing it at this point.
	 */
bind_fail:
	xenbus_free_evtchn(dev, info->evtchn);
alloc_evtchn_fail:
	gnttab_end_foreign_access_ref(info->rx_ring_ref, 0);
grant_rx_ring_fail:
	free_page((unsigned long)rxs);
alloc_rx_ring_fail:
	gnttab_end_foreign_access_ref(info->tx_ring_ref, 0);
grant_tx_ring_fail:
	free_page((unsigned long)txs);
fail:
fail:
	return err;
	return err;
}
}