From ba5d5430e108f6783bed48b9a14172614f322fa3 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Mon, 13 Mar 2017 16:30:46 +0100 Subject: [PATCH] scan: Update current request on NL80211_CMD_SCAN_ABORTED If the current request is not freed when we receive the NL80211_CMD_SCAN_ABORTED event, device.c will keep thinking that we're still scanning and the scan.c logic also gets confused and may resend the current request at some point and call sr->trigger again causing a segfault in device.c. I pass an empty bss_list to the callback, another possibility would be to pass NULL to let the callback know not to replace old results yet. The callbacks would need to handle a NULL first. --- src/scan.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/scan.c b/src/scan.c index c43dfaec..bd0134b8 100644 --- a/src/scan.c +++ b/src/scan.c @@ -1150,9 +1150,38 @@ static void scan_notify(struct l_genl_msg *msg, void *user_data) break; case NL80211_CMD_SCAN_ABORTED: + { + struct scan_request *sr = l_queue_peek_head(sc->requests); + + if (!sr || !sr->triggered) { + sc->state = SCAN_STATE_NOT_RUNNING; + break; + } + + if (sr->callback) { + bool new_owner; + struct l_queue *bss_list = l_queue_new(); + + new_owner = sr->callback(attr_wiphy, attr_ifindex, + bss_list, sr->userdata); + if (!new_owner) + l_queue_destroy(bss_list, NULL); + } + + if (sr->destroy) + sr->destroy(sr->userdata); + + scan_request_free(sr); + l_queue_pop_head(sc->requests); + sc->state = SCAN_STATE_NOT_RUNNING; + + if (!start_next_scan_request(sc) && sc->sp.rearm) + scan_periodic_rearm(sc); + break; } + } } uint8_t scan_freq_to_channel(uint32_t freq, enum scan_band *out_band)