This post is part of a regular series on Oracle Ksplice’s Known Exploit Detection. For selected security vulnerabilities, not only will Ksplice fix the code error, but it will also lay down tripwires to detect exploit attempts.

Known Exploit Detection allows system administrators to report and alarm on future attempts to exploit that vulnerability even after the system has been patched.

Why Exploit Detection Matters

In many cases, a code fix for a security vulnerability is indistinguishable from a bug fix or logic change. Around half of Linux kernel security vulnerabilities are identified retroactively and assigned to patches that are already part of the kernel.

Once the bug is fixed, the program works “correctly” and won’t trigger an alarm if a malicious user tests a known exploit.

For example, the Linux: nf_tables: locking issue in the nf_tables_abort() function lets a local user escalate to root privileges by exploiting a race condition between nftables’ garbage collection thread and the transaction abort path, which results in a double-free of a set element.

When this is fixed, an exploit attempt won’t grant unauthorized access, but the system admin won’t be alerted. With Known Exploit Detection, Ksplice fixes the race condition and sets a tripwire to detect double-free attempts.

Here’s how the warning message for CVE-2024-0193 appears in systemd’s logs when Ksplice detects an attack from the binary a.out:

Oct 21 01:52:03 localhost.localdomain /log-known-exploit[13821]: exploit attempt
detected; id=CVE-2024-0193 pid=13821 uid=0 comm=a.out lost=0

We apply Known Exploit Detection selectively: only for vulnerabilities that are significant and likely to be exploited. Not every patched flaw gets this treatment, it’s reserved for high-profile threats.

Latest Known Exploit Detection Tripwires Added

Here’s a selection of our most recent Known Exploit Detection capabilities in Oracle Ksplice:

  • CVE-2024-26925: This is a race condition between the abort path and the garbage collector (GC) thread, where a set element can be freed by both.

    The creation of sets, set elements, objects, rules, chains, etc., is represented by messages (e.g., NFT_MSG_NEWSET, NFT_MSG_NEWSETELEM, etc.). These messages can be sent in a batch, with a commit occurring only after all are successfully processed.

    When a user adds an element (using NFT_MSG_NEWSETELEM) with the NFT_SETELEM_TIMEOUT flag to a set, they request that the element expire after a timeout. The garbage collector thread removes expired elements and schedules them for deletion.

    The messages to create netfilter objects are stored in nft_trans (a transaction data type) and protected by nft_net->commit_mutex. When a batch is processed, each message is saved in nft_trans and added to nft_net->commit_list. At the end of the batch, nft_net->commit_mutex is acquired, and nft_net->commit_list is processed.

    If a new object type requires loading a module via request_module, nft_net->commit_mutex is released to avoid long holds. Releasing the mutex breaks the atomicity of the batch, so the transaction is aborted, the mutex is released, the module is loaded, and the transaction is retried.

    During this abort, the GC thread may wake up. It does not acquire nft_net->commit_mutex to avoid ABBA deadlock with application threads. Instead, it adds the expired set elements tagged with the current GC sequence number in a GC transaction to a separate list to be processed for deletion in a work-queue, that can acquire nft_net->commit_mutex safely.

    The UAF issue is fixed by ensuring that nft_net->commit_mutex is released only after the GC sequence is incremented twice – once before processing the transaction and once after the transaction ends. Since the work-queue acquires nft_net->commit_mutex before checking the current GC sequence against the GC sequence in the GC transaction, it fails to match if the application thread has already incremented the current GC sequence number in commit or in abort path, and the work-queue won’t process the elements.

  • CVE-2024-0193: This is a Use-After-Free (UAF) in nftables’ chain, referenced from a set element belonging to a pipapo set.

    The UAF occurs when an element in a pipapo set expires quickly. Expired elements with CATCHALL flag are added to set->catchall_list. When a chain is referenced from an element, chain->use is incremented. NFT_DELCHAIN does not delete a chain unless chain->use is 0.

    If both a set element and a rule reference the same chain, chain->use becomes 2. NFT_DELSET starts dereferencing set elements and decrements chain->use of an element if the set element references any chain. Without the fix, NFT_DELSET calls pipapo_gc, which processes the expired elements and decrements chain->use again and chain->use incorrectly reaches zero.

    If NFT_DELCHAIN is called afterward, it sees chain->use is 0 and deletes the chain while a rule still holds a dangling pointer. A malicious user could exploit this to trigger a UAF.

  • CVE-2023-4244: This is a Use-After-Free in nftables, similar to CVE-2024-0193, but involving the GC thread.

    Here, NFT_DELSET decrements chain->use, and concurrently, the GC thread processes set->catchall_list for expired set elements and decrements it again and incorrectly causes chain->use to reach zero.

    If NFT_DELCHAIN is called afterward, it sees chain->use is 0, deletes the chain, and leaves a rule with a dangling pointer. An attacker can exploit this to create a UAF vulnerability.

On a non-Ksplice-patched system, the kernel fix prevents the vulnerability but does not alert the admin to an attack attempt. With Ksplice, the intrusion is prevented and logged.

Ksplice lets you patch vulnerabilities and critical bugs on running systems without rebooting. Find out what patches you can apply with Ksplice Inspector. Learn more at ksplice.oracle.com.

If this work interests you, consider applying to the Ksplice team! Reach us at ksplice-support_ww@oracle.com.