# HG changeset patch
# User Laszlo Ersek <lersek@xxxxxxxxxx>
# Date 1306393625 -3600
# Node ID e7c536b81b6ae4d61069922d65fe2bf5e2b77d29
# Parent 415a9b435fef2ac85ad9aebe1c3c534f6b40dc8a
netfront: plug a theoretical leak on setup_device()'s error path
Suppose the frontend is in XenbusStateInitialising and the backend
advances to XenbusStateInitWait. backend_changed() will call
network_connect() -> talk_to_backend() -> setup_device().
If bind_listening_port_to_irqhandler() fails (due to event channel
allocation failure, dynamic IRQ allocation failure etc), then the
grant references and the shared ring pages remain allocated. The error
percolates back to backend_changed() without any cleanup.
backend_changed() will not change the frontend state; it will stay in
XenbusStateInitialising. If the backend retries XenbusStateInitWait
(possibly through a fake, no-op mediate state, like
XenbusStateClosed), then the frontend repeats the above call chain and
leaks the previously unreleased ring pages and grant references.
If setup_device() fails to grant access to the RX page before it tries
to call bind_listening_port_to_irqhandler(), then only the TX page /
grant reference are leaked in the next round.
I'm not sure what happens when the RX page allocation fails:
xenbus_dev_fatal() is called then, which changes the frontend's state
and seems to preclude a second immediate call to network_connect(). I
think this patch shouldn't hurt in that case either (or after
earlier failures in setup_device() for that matter).
Signed-off-by: Laszlo Ersek <lersek@xxxxxxxxxx>
---
diff -r 415a9b435fef -r e7c536b81b6a drivers/xen/netfront/netfront.c
--- a/drivers/xen/netfront/netfront.c Mon May 23 18:36:33 2011 +0100
+++ b/drivers/xen/netfront/netfront.c Thu May 26 08:07:05 2011 +0100
@@ -215,6 +215,7 @@
static struct net_device *create_netdev(struct xenbus_device *);
static void end_access(int, void *);
+static void netif_release_rings(struct netfront_info *);
static void netif_disconnect_backend(struct netfront_info *);
static int network_connect(struct net_device *);
@@ -522,6 +523,7 @@
return 0;
fail:
+ netif_release_rings(info);
return err;
}
@@ -2152,6 +2154,15 @@
};
#endif
+static void netif_release_rings(struct netfront_info *info)
+{
+ end_access(info->tx_ring_ref, info->tx.sring);
+ end_access(info->rx_ring_ref, info->rx.sring);
+ info->tx_ring_ref = GRANT_INVALID_REF;
+ info->rx_ring_ref = GRANT_INVALID_REF;
+ info->tx.sring = NULL;
+ info->rx.sring = NULL;
+}
static void netif_disconnect_backend(struct netfront_info *info)
{
@@ -2166,12 +2177,7 @@
unbind_from_irqhandler(info->irq, info->netdev);
info->irq = 0;
- end_access(info->tx_ring_ref, info->tx.sring);
- end_access(info->rx_ring_ref, info->rx.sring);
- info->tx_ring_ref = GRANT_INVALID_REF;
- info->rx_ring_ref = GRANT_INVALID_REF;
- info->tx.sring = NULL;
- info->rx.sring = NULL;
+ netif_release_rings(info);
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|