A vulnerability was recently found and resolved within the Linux kernel. The vulnerability exists in the wifi: cfg80211 subsystem where the link ID is removed from the bitmap during link deletion, before the completion of clean-up operations. This can result in the WARN_ON() function being triggered as some clean-up operations require the link ID to remain in the valid_links bitmap. The patch for this issue ensures that the link ID is cleared from the bitmap only after completing the clean-up process.

Exploit Details

The issue arises during the removal of a link ID by the nl80211_remove_link() function. The problematic function call order is as follows:

nl80211_remove_link()
    cfg80211_remove_link()
        ieee80211_del_intf_link()
            ieee80211_vif_set_links()
                ieee80211_vif_update_links()
                    ieee80211_link_stop()
                        cfg80211_cac_event()

In this flow, the cfg80211_remove_link() function clears the link ID from the valid_links bitmap, but when cfg80211_cac_event() is called, it requires the link ID to be present in the bitmap. This ultimately results in the WARN_ON() function being triggered.

Code Snippet

void cfg80211_remove_link(struct cfg80211_registered_device *rdev,
                         struct cfg80211_link *link)
{
    struct cfg80211_link_int *link_int;
    struct cfg80211_registered_device *other_rdev;

    spin_lock_bh(&rdev->links_lock);
    other_rdev = link->other_rdev;
    link_int = link->int_link;
    __cleanup_link(link);
    spin_unlock_bh(&rdev->links_lock);

    call_cfg80211_unregister_link(rdev, other_rdev, link_int);
}

This is a code snippet of the cfg80211_remove_link() function that removes the link ID from the valid_links bitmap before performing any other clean-up operations.

Patch
=====

The patch for this vulnerability ensures that the link ID is not removed from the valid_links bitmap until after all the relevant clean-up operations have been completed. This is done by modifying the cfg80211_remove_link() function as shown below:

void cfg80211_remove_link(struct cfg80211_registered_device *rdev,
                         struct cfg80211_link *link)
{
    struct cfg80211_link_int *link_int;
    struct cfg80211_registered_device *other_rdev;

    spin_lock_bh(&rdev->links_lock);
    other_rdev = link->other_rdev;
    link_int = link->int_link;
    __cleanup_link(link);

    // Clear the link ID from the bitmap after completing the link clean-up
    clear_bit(link->id, rdev->valid_links);
    spin_unlock_bh(&rdev->links_lock);

    call_cfg80211_unregister_link(rdev, other_rdev, link_int);
}

Here, the function clear_bit(link->id, rdev->valid_links); is moved after the call to __cleanup_link(link);, and placed before spin_unlock_bh(&rdev->links_lock);. This change ensures that the link ID is not removed from the valid_links bitmap until all necessary clean-up operations have been completed.

Original References

Linux Kernel Git Commit: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ff37d5e6f92428a3c60df8107526c214dabb19a3

Conclusion

The CVE-2024-57898 vulnerability found in the Linux kernel's wifi: cfg80211 subsystem has been resolved with a patch that ensures the link ID is cleared from the bitmap only after completing all necessary clean-up operations. By making this change, the WARN_ON() function is no longer triggered improperly, and the Linux kernel's handling of link deletion is more robust.

Timeline

Published on: 01/15/2025 13:15:14 UTC
Last modified on: 01/20/2025 06:29:08 UTC