mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-23 07:29:28 +01:00
scan: Cancel CMD_TRIGGER_SCAN when removing scan context
Save the ids of the netlink trigger scan commands that we send and cancel them in scan_ifindex_remove to fix a race leading to a segfault. The segfault would happen every time if scan_ifindex_remove was called in the same main loop iteration in which we sent the command, on shutdown: ^CTerminate src/netdev.c:netdev_free() Freeing netdev wlan3[6] src/device.c:device_disassociated() 6 src/device.c:device_enter_state() Old State: connected, new state: disconnected src/device.c:device_enter_state() Old State: disconnected, new state: autoconnect src/scan.c:scan_periodic_start() Starting periodic scan for ifindex: 6 src/device.c:device_free() src/device.c:bss_free() Freeing BSS 02:00:00:00:00:00 src/device.c:bss_free() Freeing BSS 02:00:00:00:01:00 Removing scan context for ifindex: 6 src/scan.c:scan_context_free() sc: 0x5555557ca290 src/scan.c:scan_notify() Scan notification 33 src/netdev.c:netdev_operstate_down_cb() netdev: 6, success: 1 src/scan.c:scan_periodic_done() src/scan.c:scan_periodic_done() Periodic scan triggered for ifindex: 1434209520 Program received signal SIGSEGV, Segmentation fault. 0x0000000000000064 in ?? () (gdb) bt #0 0x0000000000000064 in ?? () #1 0x0000555555583560 in process_unicast (nlmsg=0x7fffffffc1a0, genl=0x5555557c1d60) at ell/genl.c:390 #2 received_data (io=<optimized out>, user_data=0x5555557c1d60) at ell/genl.c:506 #3 0x0000555555580d45 in io_callback (fd=<optimized out>, events=1, user_data=0x5555557c1e60) at ell/io.c:120 #4 0x000055555558005f in l_main_run () at ell/main.c:381 #5 0x00005555555599c1 in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:259
This commit is contained in:
parent
701e5dabb9
commit
4e9dc77b2d
35
src/scan.c
35
src/scan.c
@ -74,6 +74,7 @@ struct scan_context {
|
|||||||
enum scan_state state;
|
enum scan_state state;
|
||||||
struct scan_periodic sp;
|
struct scan_periodic sp;
|
||||||
struct l_queue *requests;
|
struct l_queue *requests;
|
||||||
|
unsigned int start_cmd_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scan_results {
|
struct scan_results {
|
||||||
@ -160,25 +161,27 @@ bool scan_ifindex_remove(uint32_t ifindex)
|
|||||||
if (!sc)
|
if (!sc)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (sc->start_cmd_id)
|
||||||
|
l_genl_family_cancel(nl80211, sc->start_cmd_id);
|
||||||
|
|
||||||
l_info("Removing scan context for ifindex: %u", ifindex);
|
l_info("Removing scan context for ifindex: %u", ifindex);
|
||||||
scan_context_free(sc);
|
scan_context_free(sc);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool scan_send_start(struct l_genl_msg **msg,
|
static unsigned int scan_send_start(struct l_genl_msg **msg,
|
||||||
scan_func_t callback, void *user_data)
|
scan_func_t callback, void *user_data)
|
||||||
{
|
{
|
||||||
if (!l_genl_family_send(nl80211, *msg, callback,
|
unsigned int id = l_genl_family_send(nl80211, *msg, callback,
|
||||||
user_data, NULL)) {
|
user_data, NULL);
|
||||||
|
|
||||||
|
if (id)
|
||||||
|
*msg = NULL;
|
||||||
|
else
|
||||||
l_error("Sending NL80211_CMD_TRIGGER_SCAN failed");
|
l_error("Sending NL80211_CMD_TRIGGER_SCAN failed");
|
||||||
|
|
||||||
return false;
|
return id;
|
||||||
}
|
|
||||||
|
|
||||||
*msg = NULL;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_next_scan_request(void *userdata)
|
static void start_next_scan_request(void *userdata)
|
||||||
@ -195,7 +198,9 @@ static void start_next_scan_request(void *userdata)
|
|||||||
|
|
||||||
sr = l_queue_peek_head(sc->requests);
|
sr = l_queue_peek_head(sc->requests);
|
||||||
|
|
||||||
if (!scan_send_start(&sr->start_cmd, scan_done, sc)) {
|
sc->start_cmd_id = scan_send_start(&sr->start_cmd, scan_done, sc);
|
||||||
|
|
||||||
|
if (!sc->start_cmd_id) {
|
||||||
if (sr->destroy)
|
if (sr->destroy)
|
||||||
sr->destroy(sr->userdata);
|
sr->destroy(sr->userdata);
|
||||||
|
|
||||||
@ -216,6 +221,8 @@ static void scan_done(struct l_genl_msg *msg, void *userdata)
|
|||||||
|
|
||||||
l_debug("");
|
l_debug("");
|
||||||
|
|
||||||
|
sc->start_cmd_id = 0;
|
||||||
|
|
||||||
err = l_genl_msg_get_error(msg);
|
err = l_genl_msg_get_error(msg);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* Scan in progress, defer */
|
/* Scan in progress, defer */
|
||||||
@ -352,7 +359,8 @@ static uint32_t scan_common(uint32_t ifindex, bool passive,
|
|||||||
if (sc->state != SCAN_STATE_NOT_RUNNING)
|
if (sc->state != SCAN_STATE_NOT_RUNNING)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (scan_send_start(&sr->start_cmd, scan_done, sc))
|
sc->start_cmd_id = scan_send_start(&sr->start_cmd, scan_done, sc);
|
||||||
|
if (!sc->start_cmd_id)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -457,6 +465,8 @@ static void scan_periodic_done(struct l_genl_msg *msg, void *user_data)
|
|||||||
l_debug("");
|
l_debug("");
|
||||||
sc->sp.rearm = true;
|
sc->sp.rearm = true;
|
||||||
|
|
||||||
|
sc->start_cmd_id = 0;
|
||||||
|
|
||||||
err = l_genl_msg_get_error(msg);
|
err = l_genl_msg_get_error(msg);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* Scan already in progress */
|
/* Scan already in progress */
|
||||||
@ -485,7 +495,8 @@ static bool scan_periodic_send_start(struct scan_context *sc)
|
|||||||
if (!msg)
|
if (!msg)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!scan_send_start(&msg, scan_periodic_done, sc)) {
|
sc->start_cmd_id = scan_send_start(&msg, scan_periodic_done, sc);
|
||||||
|
if (!sc->start_cmd_id) {
|
||||||
l_genl_msg_unref(msg);
|
l_genl_msg_unref(msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user