Re: [BUG] Crash in network_info_get_roam_frequencies() when a neighbor report completes with -ENOTCONN during disconnect teardown

James Prestwood <[email protected]> Tue, 28 Jul 2026 06:17:56 -0700
Newsgroups dev.linux.lists.iwd
Message-ID <[email protected]>
Hi Muhammed,

On 7/27/26 1:03 PM, Muhammed Izzet Saglam wrote:
> Hi,
>
> iwd 3.12 crashes with SIGSEGV while roaming, when a pending 802.11k
> neighbor report request completes during connection teardown. The
> neighbor report callback only bails out on -ENODEV, so an -ENOTCONN
> completion falls through to a roam scan that dereferences the connection
> state netdev_connect_free() has just torn down.
>
> I hit this twice within one minute on 2026-07-25 and captured both core
> dumps. The backtraces are identical, so this looks deterministic rather
> than memory corruption.
>
> Backtrace (both dumps, identical):
>
>    #0  network_info_get_roam_frequencies (info=0x0, current_freq=2462,
>            max=max@entry=5 '\005') at src/knownnetworks.c:391
>    #1  station_roam_scan_known_freqs (station=station@entry=0x564903a82b50)
>            at src/station.c:3088
>    #2  station_neighbor_report_cb (netdev=<optimized out>, err=-107,
>            reports=<optimized out>, reports_len=0,
>            user_data=0x564903a82b50) at src/station.c:3129
>    #3  netdev_connect_free (netdev=netdev@entry=0x564903a77c40)
>            at src/netdev.c:867
>    #4  netdev_connect_failed (netdev=0x564903a77c40, result=<optimized out>,
>            status_or_reason=<optimized out>) at src/netdev.c:937
>    #5  netdev_disconnected (netdev=0x564903a77c40, result=<optimized out>,
>            event=NETDEV_EVENT_DISCONNECT_BY_SME,
>            status_or_reason=<optimized out>) at src/netdev.c:1004
>    #6  netdev_disconnect_by_sme_cb (msg=<optimized out>,
>            user_data=0x564903a77c40) at src/netdev.c:1019
>    #7  process_unicast (genl=<optimized out>, nlmsg=0x7ffffcf571d0)
>            at ell/genl.c:860
>    #8  received_data (io=<optimized out>, user_data=0x564903a69bb0)
>            at ell/genl.c:972
>    #9  io_callback (fd=<optimized out>, events=1, user_data=0x564903a69b00)
>            at ell/io.c:105
>    #10 l_main_iterate (timeout=<optimized out>) at ell/main.c:463
>    #11 l_main_run () at ell/main.c:511
>    #12 l_main_run () at ell/main.c:492
>    #13 l_main_run_with_signal (callback=0x5648f3df5bc0 <signal_handler>,
>            user_data=0x0) at ell/main.c:633
>    #14 main (argc=<optimized out>, argv=<optimized out>) at src/main.c:610
>
> The faulting line is knownnetworks.c:391, with info == NULL:
>
>    for (entry = l_queue_get_entries(info->known_frequencies); entry && max;
>
> Sequence, as I read it:
>
>    1. The AP disconnects us, so netdev_disconnect_by_sme_cb() runs
>       (NETDEV_EVENT_DISCONNECT_BY_SME).
>    2. netdev_connect_failed() -> netdev_connect_free() tears the
>       connection down and completes the outstanding neighbor report
>       request with an error.
>    3. station_neighbor_report_cb() is invoked with err = -107
>       (-ENOTCONN).
>    4. The guard at the top of that callback only returns early for
>       -ENODEV:
>
>          if (!station->preparing_roam || err == -ENODEV)
>                  return;
>
>       so -ENOTCONN continues to:
>
>          if (!reports || err) {
>                  r = station_roam_scan_known_freqs(station);
>
>    5. station_roam_scan_known_freqs() then reaches
>       network_info_get_roam_frequencies() with the network info already
>       gone, and dereferences NULL.
>
> Commit 155c266 ("station: add checks to prevent multiple roam scans",
> Jan 2023) fixed a different path to the same crash signature and is of
> course already in 3.12. This one arrives through the disconnect teardown
> rather than the roam rearm timer, and the code in master still looks
> affected: station_neighbor_report_cb() special-cases -ENODEV only, and
> station_roam_scan_known_freqs() has no NULL check on the connected
> network.
>
> I have not written a patch because I do not know which fix you would
> prefer -- treating any err as terminal in the callback, checking
> station->connected_network before the fallback scan, or cancelling the
> neighbor report request earlier in netdev_connect_free(). Happy to test
> a patch on this hardware.
>
> System:
>
>    iwd            3.12 (Arch Linux, iwd 3.12-1)
>    kernel         7.1.5-zen1-1-zen (x86_64)
>    device         Intel Wi-Fi 6E AX210/AX1675 2x2 [Typhoon Peak]
>                   [8086:2725] rev 1a, iwlwifi
>    firmware       89.735b75a4.0 ty-a0-gf-a0-89.ucode, op_mode iwlmvm
>    band at crash  2462 MHz (2.4 GHz, channel 11), roaming on a weak link
>
> Both core dumps are still on disk if anything else would help.
>
> Thanks,
> Muhammed Izzet Saglam

Thanks for reporting this. A quick fix is certainly to just add 
-ENOTCONN to station_neighbor_report_cb(). The only thing that makes me 
nervous is if -ENOTCONN is a possible return from netlink. I'm also 
questioning why netdev needs to call the callback in the first place 
(e.g. with -ENODEV). We just bail out and ignore it. I can see the 
argument for netdev completing the API contract with the caller, but it 
also feels like a waste of cycles to me.

Thanks,

James