CVE-2024-0582 / Linux Kernel Zero-Day

CVE-2024-0582: Linux Kernel io_uring UAF Privilege Escalation Teardown

How an asynchronous ring buffer registration race in fs/io_uring.c freed active kernel pages, allowing unprivileged local attackers to overwrite cred structures and achieve root.

💡 Explicación en Lenguaje Sencillo (ELI5)

Imagine a shared bank safety deposit box where two clerks share a ledger. Clerk A decides to close the box and shred the paperwork, but Clerk B continues writing checks against the box's memory address. The bank immediately rents that exact box to the town mayor. Clerk B then writes their name onto the mayor's documents, walking out with the keys to the entire city.

Conceptos Centrales y Términos del Subsistema

io_uring Subsystem
Linux's high-performance asynchronous I/O framework that avoids expensive context switches between user and kernel space via shared memory rings.
Use-After-Free (UAF)
A memory corruption flaw occurring when memory is accessed after being deallocated, allowing attackers to hijack newly allocated objects at the same address.
IORING_REGISTER_BUFFERS
The kernel syscall operation that registers and locks an array of user memory buffers into the kernel's address space for zero-copy I/O.
struct cred
The internal Linux kernel structure storing a process's effective UID, GID, and capability sets. Overwriting this yields instant root privileges.

Mecánica del Ataque Paso a Paso

Step 1

1. Initial Unprivileged Setup

An unprivileged attacker thread registers a fixed buffer ring via io_uring_register().

Step 2

2. Triggering Premature Free

The attacker issues IORING_REGISTER_BUFFERS_UPDATE with an out-of-bounds index, triggering a reference count underflow that frees the underlying page table.

Step 3

3. Slab Spraying with Pipe Buffers

The attacker sprays pipe_buffer objects across kernel memory, landing directly in the newly freed slab cache.

Step 4

4. Target Privilege Overwrite

The stale io_uring reference writes to the reallocated memory, rewriting the process credentials to uid=0, gid=0.

Código Fuente: Fallo Fatal vs. Corrección Segura

Entregado en código fuente legible de alto nivel (sin ensamblador ni diffs binarios).

FALLO SIN CORREGIR
// VULNERABLE: Linux kernel fs/io_uring.c before patch
int io_sqe_buffers_update(struct io_ring_ctx *ctx, void __user *arg, unsigned int nr_args) {
    struct io_rsrc_data *data = ctx->buf_data;
    
    // ROOT CAUSE: Incomplete reference accounting when updating buffer rings
    for (i = 0; i < nr_args; i++) {
        // Releases resource node prematurely while still mapped in current task!
        io_rsrc_node_switch(ctx, data);
        
        // Destroys node before awaiting concurrent ring completions!
        io_queue_rsrc_removal(data, i, ctx->rsrc_node, (void *)tag);
    }
    return 0;
}
PARCHE SEGURO
// SECURE: Hardened reference counting in fs/io_uring.c
int io_sqe_buffers_update(struct io_ring_ctx *ctx, void __user *arg, unsigned int nr_args) {
    struct io_rsrc_data *data = ctx->buf_data;
    
    // 1. Lock context to guarantee atomic resource state transition
    mutex_lock(&ctx->uring_lock);
    
    for (i = 0; i < nr_args; i++) {
        // 2. Validate explicit boundary bounds on buffer array
        if (unlikely(i >= data->nr)) {
            mutex_unlock(&ctx->uring_lock);
            return -EINVAL;
        }
        
        // 3. Atomically switch node only after verifying zero in-flight references
        io_rsrc_node_switch(ctx, data);
        io_queue_rsrc_removal(data, i, ctx->rsrc_node, (void *)tag);
    }
    
    mutex_unlock(&ctx->uring_lock);
    return 0;
}

Lista de Verificación para Ingeniería y Mitigación

← Explorar Directorio de Seguridad Todas las Actualizaciones de Seguridad →