From: Jonah Palmer <[email protected]>
Makes the net_hub_port_cleanup function idempotent to avoid double
removals by guarding its QLIST_REMOVE with a flag.
When using a Xen networking device with hubport backends, e.g.:
-accel kvm,xen-version=0x40011
-netdev hubport,...
-device xen-net-device,...
the shutdown order starts with net_cleanup, which walks the list and
deletes netdevs (including hubports). Then Xen's xen_device_unrealize is
called, which eventually leads to a second net_hub_port_cleanup call,
resulting in a segfault.
Fixes: e7891c57 ("net: move backend cleanup to NIC cleanup")
Reported-by: David Woodhouse <[email protected]>
Signed-off-by: Jonah Palmer <[email protected]>
Signed-off-by: Jason Wang <[email protected]>
---
net/hub.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/hub.c b/net/hub.c
index e3b58b1c4f..ee5881f6d5 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -34,6 +34,7 @@ typedef struct NetHubPort {
QLIST_ENTRY(NetHubPort) next;
NetHub *hub;
int id;
+ bool listed;
} NetHubPort;
struct NetHub {
@@ -129,7 +130,10 @@ static void net_hub_port_cleanup(NetClientState *nc)
{
NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
- QLIST_REMOVE(port, next);
+ if (port->listed) {
+ QLIST_REMOVE(port, next);
+ port->listed = false;
+ }
}
static NetClientInfo net_hub_port_info = {
@@ -159,8 +163,10 @@ static NetHubPort *net_hub_port_new(NetHub *hub, const
char *name,
port = DO_UPCAST(NetHubPort, nc, nc);
port->id = id;
port->hub = hub;
+ port->listed = false;
QLIST_INSERT_HEAD(&hub->ports, port, next);
+ port->listed = true;
return port;
}
--
2.42.0