Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Wei Liu <wei.liu2@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Wei Liu and committed by
David S. Miller
1ca2983a 6dffbe53

+21 -12
+21 -12
drivers/net/xen-netfront.c
··· 1532 1532 FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE); 1533 1533 1534 1534 err = xenbus_grant_ring(dev, virt_to_mfn(txs)); 1535 - if (err < 0) { 1536 - free_page((unsigned long)txs); 1537 - goto fail; 1538 - } 1535 + if (err < 0) 1536 + goto grant_tx_ring_fail; 1539 1537 1540 1538 info->tx_ring_ref = err; 1541 1539 rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH); 1542 1540 if (!rxs) { 1543 1541 err = -ENOMEM; 1544 1542 xenbus_dev_fatal(dev, err, "allocating rx ring page"); 1545 - goto fail; 1543 + goto alloc_rx_ring_fail; 1546 1544 } 1547 1545 SHARED_RING_INIT(rxs); 1548 1546 FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE); 1549 1547 1550 1548 err = xenbus_grant_ring(dev, virt_to_mfn(rxs)); 1551 - if (err < 0) { 1552 - free_page((unsigned long)rxs); 1553 - goto fail; 1554 - } 1549 + if (err < 0) 1550 + goto grant_rx_ring_fail; 1555 1551 info->rx_ring_ref = err; 1556 1552 1557 1553 err = xenbus_alloc_evtchn(dev, &info->evtchn); 1558 1554 if (err) 1559 - goto fail; 1555 + goto alloc_evtchn_fail; 1560 1556 1561 1557 err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt, 1562 1558 0, netdev->name, netdev); 1563 1559 if (err < 0) 1564 - goto fail; 1560 + goto bind_fail; 1565 1561 netdev->irq = err; 1566 1562 return 0; 1567 1563 1568 - fail: 1564 + /* If we fail to setup netfront, it is safe to just revoke access to 1565 + * granted pages because backend is not accessing it at this point. 1566 + */ 1567 + bind_fail: 1568 + xenbus_free_evtchn(dev, info->evtchn); 1569 + alloc_evtchn_fail: 1570 + gnttab_end_foreign_access_ref(info->rx_ring_ref, 0); 1571 + grant_rx_ring_fail: 1572 + free_page((unsigned long)rxs); 1573 + alloc_rx_ring_fail: 1574 + gnttab_end_foreign_access_ref(info->tx_ring_ref, 0); 1575 + grant_tx_ring_fail: 1576 + free_page((unsigned long)txs); 1577 + fail: 1569 1578 return err; 1570 1579 } 1571 1580