3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-26 10:39:23 +01:00

station/network: avoid use-after-free

ConnectHiddenNetwork creates a temporary network object and initiates a
connection with it.  If the connection fails (due to an incorrect
passphrase or other reasons), then this temporary object is destroyed.
Delay its destruction until network_disconnected() since
network_connect_failed is called too early.  Also, re-order the sequence
in station_reset_connection_state() in order to avoid using the network
object after it has been freed by network_disconnected().

Fixes: 85d9d6461f ("network: Hide hidden networks on connection error")
This commit is contained in:
Denis Kenzior 2022-04-08 13:18:09 -05:00
parent 867c68c05b
commit 8a877d8692
2 changed files with 14 additions and 9 deletions

View File

@ -198,6 +198,9 @@ void network_disconnected(struct network *network)
network_settings_close(network); network_settings_close(network);
l_queue_clear(network->blacklist, NULL); l_queue_clear(network->blacklist, NULL);
if (network->provisioning_hidden)
station_hide_network(network->station, network);
} }
/* First 64 entries calculated by 1 / pow(n, 0.3) for n >= 1 */ /* First 64 entries calculated by 1 / pow(n, 0.3) for n >= 1 */
@ -983,9 +986,6 @@ void network_connect_failed(struct network *network, bool in_handshake)
l_queue_destroy(network->secrets, eap_secret_info_free); l_queue_destroy(network->secrets, eap_secret_info_free);
network->secrets = NULL; network->secrets = NULL;
if (network->provisioning_hidden)
station_hide_network(network->station, network);
} }
static bool hotspot_info_matches(struct network *network, static bool hotspot_info_matches(struct network *network,

View File

@ -1616,12 +1616,6 @@ static void station_reset_connection_state(struct station *station)
if (!network) if (!network)
return; return;
if (station->state == STATION_STATE_CONNECTED ||
station->state == STATION_STATE_CONNECTING ||
station->state == STATION_STATE_CONNECTING_AUTO ||
station->state == STATION_STATE_ROAMING)
network_disconnected(network);
station_roam_state_clear(station); station_roam_state_clear(station);
/* Refresh the ordered network list */ /* Refresh the ordered network list */
@ -1639,6 +1633,17 @@ static void station_reset_connection_state(struct station *station)
IWD_NETWORK_INTERFACE, "Connected"); IWD_NETWORK_INTERFACE, "Connected");
l_dbus_object_remove_interface(dbus, netdev_get_path(station->netdev), l_dbus_object_remove_interface(dbus, netdev_get_path(station->netdev),
IWD_STATION_DIAGNOSTIC_INTERFACE); IWD_STATION_DIAGNOSTIC_INTERFACE);
/*
* Perform this step last since calling network_disconnected() might
* result in the removal of the network (for example if provisioning
* a new hidden network fails with an incorrect pasword).
*/
if (station->state == STATION_STATE_CONNECTED ||
station->state == STATION_STATE_CONNECTING ||
station->state == STATION_STATE_CONNECTING_AUTO ||
station->state == STATION_STATE_ROAMING)
network_disconnected(network);
} }
static void station_disassociated(struct station *station) static void station_disassociated(struct station *station)