mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 21:22:37 +01:00
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)
This commit is contained in:
parent
bd6d19e084
commit
ed0f3e87ca
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user