netdev: use l_idle_create for disconnect idle

The chances were extremely low, but using l_idle_oneshot
could end up causing a invalid memory access if the netdev
went down while waiting for the disconnect idle callback.

Instead netdev can keep track of the idle with l_idle_create
and remove it if the netdev goes down prior to the idle callback.
This commit is contained in:
James Prestwood 2021-04-06 09:58:26 -07:00 committed by Denis Kenzior
parent 51fc2453ba
commit 6c9f72380d
1 changed files with 13 additions and 3 deletions

View File

@ -148,6 +148,8 @@ struct netdev {
void *get_station_data;
netdev_destroy_func_t get_station_destroy;
struct l_idle *disconnect_idle;
struct watchlist station_watches;
struct l_io *pae_io; /* for drivers without EAPoL over NL80211 */
@ -811,6 +813,11 @@ static void netdev_free(void *data)
if (netdev->fw_roam_bss)
scan_bss_free(netdev->fw_roam_bss);
if (netdev->disconnect_idle) {
l_idle_remove(netdev->disconnect_idle);
netdev->disconnect_idle = NULL;
}
if (netdev->events_ready)
WATCHLIST_NOTIFY(&netdev_watches, netdev_watch_func_t,
netdev, NETDEV_WATCH_EVENT_DEL);
@ -3182,10 +3189,13 @@ build_cmd_connect:
event_filter, cb, user_data);
}
static void disconnect_idle(void *user_data)
static void disconnect_idle(struct l_idle *idle, void *user_data)
{
struct netdev *netdev = user_data;
l_idle_remove(idle);
netdev->disconnect_idle = NULL;
netdev->disconnect_cb(netdev, true, netdev->user_data);
}
@ -3249,8 +3259,8 @@ int netdev_disconnect(struct netdev *netdev,
} else if (cb) {
netdev->disconnect_cb = cb;
netdev->user_data = user_data;
l_idle_oneshot(disconnect_idle, netdev, NULL);
netdev->disconnect_idle = l_idle_create(disconnect_idle,
netdev, NULL);
}
return 0;