3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-22 14:49:24 +01:00

frame-xchg: Fix group removal inside frame callback

When a frame registered in a given group Id triggers a callback and that
callback ends up calling frame_watch_group_remove for that group Id,
that call will happen inside WATCHLIST_NOTIFY_MATCHES and will free the
memory used by the watchlist.  watchlist.h has protection against the
watchlist being "destroyed" inside WATCHLIST_NOTIFY_MATCHES, but not
against its memory being freed -- the memory where it stores the in_notify
and destroy_pending flags.  Free the group immediately after
WATCHLIST_NOTIFY_MATCHES to avoid reads/writes to those flags triggering
valgrind warnings.
This commit is contained in:
Andrew Zaborowski 2020-07-21 02:45:39 +02:00 committed by Denis Kenzior
parent 1f4b32ff53
commit 5600c736b8

View File

@ -231,6 +231,10 @@ static void frame_watch_unicast_notify(struct l_genl_msg *msg, void *user_data)
WATCHLIST_NOTIFY_MATCHES(&group->watches, frame_watch_match_prefix, WATCHLIST_NOTIFY_MATCHES(&group->watches, frame_watch_match_prefix,
&info, frame_watch_cb_t, mpdu, &info, frame_watch_cb_t, mpdu,
info.body, info.body_len, rssi); info.body, info.body_len, rssi);
/* Has frame_watch_group_destroy been called inside a frame CB? */
if (group->watches.pending_destroy)
l_free(group);
} }
static void frame_watch_group_destroy(void *data) static void frame_watch_group_destroy(void *data)
@ -244,7 +248,16 @@ static void frame_watch_group_destroy(void *data)
l_io_destroy(group->io); l_io_destroy(group->io);
l_queue_destroy(group->write_queue, l_queue_destroy(group->write_queue,
(l_queue_destroy_func_t) l_genl_msg_unref); (l_queue_destroy_func_t) l_genl_msg_unref);
/*
* We may be inside a frame notification but even then use
* watchlist_destroy to prevent any more notifications from
* being dispatched.
*/
watchlist_destroy(&group->watches); watchlist_destroy(&group->watches);
if (group->watches.in_notify)
return;
l_free(group); l_free(group);
} }