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 <dw...@infradead.org> Signed-off-by: Jonah Palmer <jonah.pal...@oracle.com> --- net/hub.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/hub.c b/net/hub.c index e3b58b1c4f8e..ee5881f6d5cb 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.47.3