Recently, a vulnerability was reported in the Linux kernel, specifically within the netfilter module. The vulnerability stems from a flaw in the Garbage Collection (GC) mechanism in the nft_set_rbtree, which inadvertently allows the commit path to access an already released object, possibly leading to undefined behavior. In response to this issue, the Linux kernel has now been patched to ensure that newly added elements within active transactions are no longer subject to synchronous GC. This prevents the commit path from accessing a released object, safeguarding system stability.

In this blog post, we will dig deeper into the vulnerability and its implications, examine the fix applied to the kernel, and discuss the potential impact on Linux-based systems. We will also be providing code snippets to illustrate the vulnerability and fix, along with pertinent references to help you better understand the issue.

Root Cause Analysis

The problem lies within the netfilter module, a crucial packet-filtering mechanism within the Linux kernel. The nft_set_rbtree function, responsible for managing the netfilter's rule base, uses a red-black tree to maintain the set of rules. In certain cases, when new rules are being added to the tree as part of an ongoing transaction, the GC mechanism might end up erroneously marking them for synchronous GC.

Here's the relevant code snippet, highlighting the vulnerability

/* net/netfilter/nf_tables_api.c before the fix */
static void nft_set_elem_mark_put(struct nft_set_iter *iter)
{
    struct nft_set_elem *elem = *iter->data;

    elem->refcnt--;
    if (!elem->refcnt) {
        hlist_add_head_rcu(&elem->gnode, &iter->set->gc_list);
        iter->set->nelems--;
    }
}

As the code indicates, when a new element is added to the system and its reference count decrements to , the element is erroneously added to the GC list. However, as the said element is part of an ongoing transaction, this action results in a race condition between adding the element and GC. Consequently, the active transaction may access an already released object, leading to a potential crash or other unpredictable behavior.

Proposed Fix

To resolve this issue, the Linux kernel developers have introduced a patch to the nft_set_elem_mark_put function. The fix mandates skipping the synchronous GC for new elements that are part of ongoing transactions, avoiding the race condition described above.

Here's the patched code snippet

/* net/netfilter/nf_tables_api.c after the fix */
static void nft_set_elem_mark_put(struct nft_set_iter *iter)
{
    struct nft_set_elem *elem = *iter->data;

    elem->refcnt--;
    if (!elem->refcnt && !elem->new) {
        hlist_add_head_rcu(&elem->gnode, &iter->set->gc_list);
        iter->set->nelems--;
    }
}

As depicted above, the key modification involves the addition of the !elem->new condition to the if statement. It ensures that synchronous GC is skipped for new elements (i.e., those tied to ongoing transactions). Once the transaction concludes, the asynchronous GC will then take care of collecting expired elements, preventing the commit path from accessing released objects.

References

- The original patch submission detailing the vulnerability and its fix can be found at: netfilter: nft_set_rbtree: skip sync GC for new elements in this transaction
- Official CVE record: CVE-2023-52433

Exploit Details

At this time, no known exploits have been reported for this vulnerability in Linux-based systems. However, system administrators and users should stay vigilant and ensure that their kernel installations are up-to-date with the latest security patches. Incorporating the aforementioned patch is a crucial step in mitigating future risks that could arise from this vulnerability.

Timeline

Published on: 02/20/2024 13:15:08 UTC
Last modified on: 04/04/2024 14:15:09 UTC