• Brian Norris's avatar
    mwifiex: resolve races between async FW init (failure) and device removal · 4a79aa17
    Brian Norris authored
    It's possible for the FW init sequence to fail, which will trigger a
    device cleanup sequence in mwifiex_fw_dpc(). This sequence can race with
    device suspend() or remove() (e.g., reboot or unbind), and can trigger
    use-after-free issues. Currently, this driver attempts (poorly) to
    synchronize remove() using a semaphore, but it doesn't protect some of
    the critical sections properly. Particularly, we grab a pointer to the
    adapter struct (card->adapter) without checking if it's being freed or
    not. We later do a NULL check on the adapter, but that doesn't work if
    the adapter was freed.
    
    Also note that the PCIe interface driver doesn't ever set card->adapter
    to NULL, so even if we get the synchronization right, we still might try
    to redo the cleanup in ->remove(), even if the FW init failure sequence
    already did it.
    
    This patch replaces the static semaphore with a per-device completion
    struct, and uses that completion to synchronize the remove() thread with
    the mwifiex_fw_dpc(). A future patch will utilize this completion to
    synchronize the suspend() thread as well.
    Signed-off-by: default avatarBrian Norris <briannorris@chromium.org>
    Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
    4a79aa17
main.c 50.5 KB