CVE-2024-36971: Linux Kernel Vulnerability Resolved - net: fix __dst_negative_advice() race

A newly resolved vulnerability in the Linux kernel can potentially lead to Use-After-Free (UAF) attacks. The vulnerability, identified as CVE-2024-36971, affected the __dst_negative_advice() function in the kernel's network subsystem, causing a race condition due to improper handling of RCU (Read-Copy-Update) rules.

Description

The __dst_negative_advice() function fails to enforce the correct RCU rules when sk->dst_cache needs to be cleared, leading to a possible UAF vulnerability. Ideally, RCU rules stipulate that sk->sk_dst_cache should be cleared first, followed by a call to dst_release(old_dst). However, the vulnerable code had these operations in reverse order.

The proper protocol is implemented correctly in the function sk_dst_reset(sk), while __dst_negative_advice() contained this bug. In the patched code, each of the three ->negative_advice() existing methods performs the sk_dst_reset() themselves to prevent this issue from occurring in the future.

Exploit Details

This vulnerability was found after the introduction of a specific commit that affected UDP sockets, making the old bug more visible and easier to exploit. Attackers could potentially take advantage of this UAF vulnerability by attempting to access memory after it has been freed, causing undefined behavior, data corruption, and ultimately, a possible arbitrary code execution.

Code Snippet

// Vulnerable code
void __dst_negative_advice(struct sock *sk)
{
    struct dst_entry *old_dst;
    old_dst = sk->sk_dst_cache;           // Wrong order
    sk->sk_dst_cache = NULL;

    if (old_dst) {
        if (old_dst->negative_advice)
            old_dst = old_dst->negative_advice(old_dst);

        dst_release(old_dst);               // dst_release() should be called first
    }
}
// Corrected code
void __dst_negative_advice(struct sock *sk)
{
    struct dst_entry *old_dst;
	old_dst = sk_dst_reset(sk);           // Correct order

    if (old_dst) {
        if (old_dst->negative_advice)
            old_dst = old_dst->negative_advice(old_dst);

        dst_release(old_dst);               // dst_release() called correctly
    }
}

Credits

Many thanks to Clement Lecigne for discovering and tracking this issue, as well as providing valuable insights into the possible consequences of this vulnerability in the Linux kernel.

Linux kernel source code repository

- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/

Patch submission (part of the net tree)

- https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/

CVE-2024-36971 - Official entry in the MITRE CVE database

- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-36971

Conclusion

The resolution of CVE-2024-36971 is an essential step in maintaining the security and stability of the Linux kernel. Users, system administrators, and developers should apply the appropriate patches to their systems as soon as possible to mitigate any potential risks that stem from this vulnerability.

Timeline

Published on: 06/10/2024 09:15:09 UTC
Last modified on: 08/08/2024 14:49:52 UTC