From ed0f3e87ca5ec1d51855c6345bd12cc9d1ca487e Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 29 Jan 2021 14:53:00 -0600 Subject: [PATCH] netdev: Fix re-entrancy bug in netdev_shutdown netdev_shutdown calls queue_destroy on the netdev_list, which in turn calls netdev_free. netdev_free invokes the watches to notify them about the netdev being removed. Those clients, or anything downstream can still invoke netdev_find. Unfortunately queue_destroy is not re-entrant safe, so netdev_find might return stale data. Fix that by using l_queue_peek_head / l_queue_pop_head instead. src/station.c:station_enter_state() Old State: connecting, new state: connected ^CTerminate src/netdev.c:netdev_free() Freeing netdev wlan1[6] src/device.c:device_free() Removing scan context for wdev 100000001 src/scan.c:scan_context_free() sc: 0x4ae9ca0 src/netdev.c:netdev_free() Freeing netdev wlan0[48] src/device.c:device_free() src/station.c:station_free() src/netconfig.c:netconfig_destroy() ==103174== Invalid read of size 8 ==103174== at 0x467AA9: l_queue_find (queue.c:346) ==103174== by 0x43ACFF: netconfig_reset (netconfig.c:1027) ==103174== by 0x43AFFC: netconfig_destroy (netconfig.c:1123) ==103174== by 0x414379: station_free (station.c:3369) ==103174== by 0x414379: station_destroy_interface (station.c:3466) ==103174== by 0x47C80C: interface_instance_free (dbus-service.c:510) ==103174== by 0x47C80C: _dbus_object_tree_remove_interface (dbus-service.c:1694) ==103174== by 0x47C99C: _dbus_object_tree_object_destroy (dbus-service.c:795) ==103174== by 0x409A87: netdev_free (netdev.c:770) ==103174== by 0x4677AE: l_queue_clear (queue.c:107) ==103174== by 0x4677F8: l_queue_destroy (queue.c:82) ==103174== by 0x40CDC1: netdev_shutdown (netdev.c:5089) ==103174== by 0x404736: iwd_shutdown (main.c:78) ==103174== by 0x404736: iwd_shutdown (main.c:65) ==103174== by 0x46BD61: handle_callback (signal.c:78) ==103174== by 0x46BD61: signalfd_read_cb (signal.c:104) --- src/netdev.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/netdev.c b/src/netdev.c index afcafa8e..8ea9236f 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -5082,12 +5082,19 @@ static void netdev_exit(void) void netdev_shutdown(void) { + struct netdev *netdev; + if (!rtnl) return; l_queue_foreach(netdev_list, netdev_shutdown_one, NULL); - l_queue_destroy(netdev_list, netdev_free); + while ((netdev = l_queue_peek_head(netdev_list))) { + netdev_free(netdev); + l_queue_pop_head(netdev_list); + } + + l_queue_destroy(netdev_list, NULL); netdev_list = NULL; }