mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-29 13:59:24 +01:00
manager: Fix iteration over wiphy setup states
manager_interface_dump_done would use manager_create_interfaces() at the end of the loop iterating over pending_wiphys. To prevent it from crashing make sure manager_create_interfaces never frees the pending wiphy state and instead make the caller check whether it needs to be freed so it can be done safely inside loops.
This commit is contained in:
parent
8db47ed21d
commit
7ce8d9d8b6
@ -66,8 +66,6 @@ static void wiphy_setup_state_free(void *data)
|
|||||||
{
|
{
|
||||||
struct wiphy_setup_state *state = data;
|
struct wiphy_setup_state *state = data;
|
||||||
|
|
||||||
l_queue_remove(pending_wiphys, state);
|
|
||||||
|
|
||||||
if (state->setup_timeout)
|
if (state->setup_timeout)
|
||||||
l_timeout_remove(state->setup_timeout);
|
l_timeout_remove(state->setup_timeout);
|
||||||
|
|
||||||
@ -78,6 +76,12 @@ static void wiphy_setup_state_free(void *data)
|
|||||||
l_free(state);
|
l_free(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wiphy_setup_state_destroy(struct wiphy_setup_state *state)
|
||||||
|
{
|
||||||
|
l_queue_remove(pending_wiphys, state);
|
||||||
|
wiphy_setup_state_free(state);
|
||||||
|
}
|
||||||
|
|
||||||
static bool manager_use_default(struct wiphy_setup_state *state)
|
static bool manager_use_default(struct wiphy_setup_state *state)
|
||||||
{
|
{
|
||||||
l_debug("");
|
l_debug("");
|
||||||
@ -85,12 +89,10 @@ static bool manager_use_default(struct wiphy_setup_state *state)
|
|||||||
if (!state->default_if_msg) {
|
if (!state->default_if_msg) {
|
||||||
l_error("No default interface for wiphy %u",
|
l_error("No default interface for wiphy %u",
|
||||||
(unsigned int) state->id);
|
(unsigned int) state->id);
|
||||||
wiphy_setup_state_free(state);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev_create_from_genl(state->default_if_msg);
|
netdev_create_from_genl(state->default_if_msg);
|
||||||
wiphy_setup_state_free(state);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +124,7 @@ static void manager_new_interface_done(void *user_data)
|
|||||||
struct wiphy_setup_state *state = user_data;
|
struct wiphy_setup_state *state = user_data;
|
||||||
|
|
||||||
state->pending_cmd_count--;
|
state->pending_cmd_count--;
|
||||||
wiphy_setup_state_free(state);
|
wiphy_setup_state_destroy(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_create_interfaces(struct wiphy_setup_state *state)
|
static void manager_create_interfaces(struct wiphy_setup_state *state)
|
||||||
@ -132,10 +134,8 @@ static void manager_create_interfaces(struct wiphy_setup_state *state)
|
|||||||
uint32_t iftype = NL80211_IFTYPE_STATION;
|
uint32_t iftype = NL80211_IFTYPE_STATION;
|
||||||
unsigned cmd_id;
|
unsigned cmd_id;
|
||||||
|
|
||||||
if (state->aborted) {
|
if (state->aborted)
|
||||||
wiphy_setup_state_free(state);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (state->use_default) {
|
if (state->use_default) {
|
||||||
manager_use_default(state);
|
manager_use_default(state);
|
||||||
@ -166,7 +166,6 @@ static void manager_create_interfaces(struct wiphy_setup_state *state)
|
|||||||
|
|
||||||
if (!cmd_id) {
|
if (!cmd_id) {
|
||||||
l_error("Sending NEW_INTERFACE for %s", ifname);
|
l_error("Sending NEW_INTERFACE for %s", ifname);
|
||||||
wiphy_setup_state_free(state);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,8 +178,13 @@ static void manager_setup_cmd_done(void *user_data)
|
|||||||
|
|
||||||
state->pending_cmd_count--;
|
state->pending_cmd_count--;
|
||||||
|
|
||||||
if (!state->pending_cmd_count)
|
if (state->pending_cmd_count)
|
||||||
|
return;
|
||||||
|
|
||||||
manager_create_interfaces(state);
|
manager_create_interfaces(state);
|
||||||
|
|
||||||
|
if (!state->pending_cmd_count)
|
||||||
|
wiphy_setup_state_destroy(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_del_interface_cb(struct l_genl_msg *msg, void *user_data)
|
static void manager_del_interface_cb(struct l_genl_msg *msg, void *user_data)
|
||||||
@ -363,7 +367,7 @@ static void manager_wiphy_dump_interfaces(struct wiphy_setup_state *state)
|
|||||||
if (!cmd_id) {
|
if (!cmd_id) {
|
||||||
l_error("Querying interface information for wiphy %u failed",
|
l_error("Querying interface information for wiphy %u failed",
|
||||||
(unsigned int) state->id);
|
(unsigned int) state->id);
|
||||||
wiphy_setup_state_free(state);
|
wiphy_setup_state_destroy(state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,7 +537,7 @@ static void manager_del_wiphy_event(struct l_genl_msg *msg)
|
|||||||
if (state->pending_cmd_count)
|
if (state->pending_cmd_count)
|
||||||
state->aborted = true;
|
state->aborted = true;
|
||||||
else
|
else
|
||||||
wiphy_setup_state_free(state);
|
wiphy_setup_state_destroy(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
wiphy = wiphy_find(id);
|
wiphy = wiphy_find(id);
|
||||||
@ -608,26 +612,33 @@ static void manager_interface_dump_callback(struct l_genl_msg *msg,
|
|||||||
manager_get_interface_cb(msg, state);
|
manager_get_interface_cb(msg, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_interface_dump_done(void *user_data)
|
static bool manager_check_create_interfaces(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
const struct l_queue_entry *entry;
|
struct wiphy_setup_state *state = (void *) a;
|
||||||
|
|
||||||
for (entry = l_queue_get_entries(pending_wiphys);
|
|
||||||
entry; entry = entry->next) {
|
|
||||||
struct wiphy_setup_state *state = entry->data;
|
|
||||||
|
|
||||||
/* phy might have been detected after the initial dump */
|
/* phy might have been detected after the initial dump */
|
||||||
if (state->setup_timeout)
|
if (state->setup_timeout)
|
||||||
continue;
|
return false;
|
||||||
|
|
||||||
wiphy_create_complete(state->wiphy);
|
wiphy_create_complete(state->wiphy);
|
||||||
|
|
||||||
if (state->pending_cmd_count)
|
if (state->pending_cmd_count)
|
||||||
continue;
|
return false;
|
||||||
|
|
||||||
/* If we are here, then there are no interfaces for this phy */
|
/* If we are here, then there are no interfaces for this phy */
|
||||||
manager_create_interfaces(state);
|
manager_create_interfaces(state);
|
||||||
|
|
||||||
|
if (state->pending_cmd_count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wiphy_setup_state_free(state);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void manager_interface_dump_done(void *user_data)
|
||||||
|
{
|
||||||
|
l_queue_remove_if(pending_wiphys,
|
||||||
|
manager_check_create_interfaces, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_wiphy_dump_callback(struct l_genl_msg *msg, void *user_data)
|
static void manager_wiphy_dump_callback(struct l_genl_msg *msg, void *user_data)
|
||||||
|
Loading…
Reference in New Issue
Block a user