CVE-2024-1086 / Netfilter Zero-Day

CVE-2024-1086: Linux Netfilter nf_tables Double Free Teardown

How an improper verdict handling bug in net/netfilter/nf_tables_api.c caused double reference drops on network packets, enabling container root breakouts.

💡 Plain English Explainer (ELI5)

Think of a ticket inspector on a train. A passenger hands over a ticket. The first inspector punches the ticket and marks it as used. Then, because the passenger sneezes, an unhandled rule causes a second inspector to grab the exact same ticket and punch it again. In Linux networking, dropping a packet twice freed its memory twice, allowing malicious code to masquerade as the train conductor.

Core Concepts & Subsystem Terms

Netfilter / nf_tables
The Linux kernel's modern packet filtering, network address translation (NAT), and packet mangling framework.
NF_DROP Verdict
A netfilter rule evaluation outcome instructing the kernel to drop and deallocate the incoming network packet (`sk_buff`).
sk_buff (Socket Buffer)
The core kernel data structure representing every network packet traveling through the Linux networking stack.
User Namespaces (unshare)
A Linux security isolation feature allowing unprivileged users to obtain root inside a sandbox, commonly abused to access nf_tables.

Step-by-Step Exploit Mechanics

Step 1

1. Namespace Creation

An unprivileged user creates an isolated network namespace via unshare(CLONE_NEWUSER | CLONE_NEWNET).

Step 2

2. Injecting Malformed Rule

The attacker loads a custom nftables rule returning a negative verdict code mismanaged by the hook pipeline.

Step 3

3. Triggering Double Free

The packet processing engine drops the sk_buff, but the error return path drops the exact same packet a second time.

Step 4

4. Spraying Heap Allocations

The attacker sprays fake Page Middle Directory (PMD) entries into the freed memory, achieving full arbitrary physical memory write.

Source Code: Fatal Flaw vs. High-Level Fix

Delivered in clean, readable high-level source code (no raw assembly or binary diffs).

UNPATCHED FLAW
// VULNERABLE: net/netfilter/nf_tables_api.c before patch
static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, ...) {
    // ROOT CAUSE:
    // If verdict evaluation returns an invalid negative integer,
    // the evaluation loop treats it as both NF_DROP and an internal error!
    if (verdict < 0) {
        kfree_skb(skb); // First free of socket buffer!
        return verdict; // Calling hook also invokes kfree_skb(), triggering DOUBLE FREE!
    }
    return 0;
}
HARDENED PATCH
// SECURE: net/netfilter/nf_tables_api.c patch
static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, ...) {
    // 1. Strict verdict assertion
    if (verdict < 0) {
        // Clear ownership flags to guarantee only one caller deallocates skb
        nf_tables_rule_destroy(rule);
        
        // Let the upper caller handle the single, orderly drop:
        return -EINVAL; 
    }
    return 0;
}

Engineering & System Hardening Checklist

← Browse Full Security Directory Explore All Source Teardowns →