FlawOpen

flawopen.com/Teardowns/cve-2025-39682-linux-ktls-zero-length-record-mishandling

● CVE-2025-39682 · CVSS 9.8 · Crítica
Investigación · FlawOpen

Linux CVE-2025-39682: fallo de registro vacío en kTLS

Un registro TLS no-DATA de longitud cero en la cola de recepción kTLS de Linux podía eludir la comprobación de tipo por recvmsg. La corrección comprueba el tipo procesado aunque no se hayan copiado bytes. La evaluación CVSS de Linux describe una posible exposición del heap del kernel al espacio de usuario, corrupción de memoria y bloqueos remotos del kernel; son consecuencias evaluadas, no una afirmación de que todos los sistemas afectados sufran cada resultado.

Vector CVSSCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
💡 Explicación en Lenguaje Sencillo (ELI5)

Imagina un clasificador de correo que solo puede poner cartas de una categoría en cada bandeja. Un sobre vacío sigue teniendo categoría, pero el clasificador antiguo decidía cambiar de bandeja contando las cartas. Con cero cartas, ignoraba la categoría y mezclaba el tipo siguiente. La corrección del kernel comprueba el marcador de categoría aunque el sobre no tenga datos.

Conceptos Clave y Términos

kTLS
TLS del kernel: Linux puede procesar registros TLS en el kernel para un socket TCP asociado.
recvmsg()
Llamada de recepción de socket usada por la aplicación y la ruta de recepción kTLS.
Tipo de contenido TLS
Campo que clasifica el registro, como datos de aplicación o un registro de control.
rx_list
Cola de registros de recepción pendientes procesados por llamadas recvmsg posteriores.
CWE-754
Comprobación incorrecta de condiciones inusuales o excepcionales. NVD incluye CWE-754 y atribuye la clasificación a CISA-ADP; el registro CVE de Linux no asigna un CWE.

Mapeos de marcos

Análisis de Causa Raíz

La recepción kTLS de Linux debe devolver registros DATA contiguos o un solo registro no-DATA por llamada recvmsg(). Si process_rx_list() procesaba un registro inicial no-DATA de longitud cero, podía establecer el tipo TLS y devolver err == 0. tls_sw_recvmsg() copiaba ese cero en copied y usaba (copied && control != TLS_RECORD_TYPE_DATA) en la condición de parada. Como copied era cero, ignoraba el tipo ya procesado y continuaba con los datos siguientes. El parche upstream comprueba control directamente: si hay un tipo y no es DATA, se detiene; cero sigue siendo el marcador de “aún no se informó un tipo”. La exposición requiere que se habilite y utilice la recepción TLS del kernel Linux (kTLS); no es un defecto de todos los parsers TLS de espacio de usuario. El vector CVSS 3.1 publicado por Linux es 9,8 Crítico (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H). Evalúe la exposición según el uso real de kTLS y el estado del kernel del proveedor.

Flujo de Ataque Paso a Paso

Paso 1

kTLS recibe registros

Una aplicación usa un socket TCP con la recepción TLS del kernel habilitada.

Paso 2

Se procesa un registro no-DATA vacío pendiente

El caso aparece cuando el primer registro de rx_list no tiene carga útil. El procesamiento puede informar un tipo y devolver cero bytes copiados.

Paso 3

La condición antigua depende de los bytes copiados

Como copied vale cero, la condición antigua no comprueba si el tipo procesado era no-DATA.

Paso 4

El bucle cruza el límite de tipo

Los datos siguientes pueden procesarse en la misma llamada recvmsg, contra la regla de tipo único. La evaluación CVSS de Linux describe una posible exposición del heap del kernel al espacio de usuario, corrupción de memoria y bloqueos remotos del kernel; son consecuencias evaluadas, no una afirmación de que todos los sistemas afectados sufran cada resultado.

Paso 5

La corrección comprueba el marcador semántico

La condición corregida se detiene si control indica un tipo no-DATA, sin depender de los bytes copiados.

Código Fuente: Vulnerable vs. Seguro

Fragmento de net/tls/tls_sw.c, no una función completa. Upstream cambió la condición de parada para usar el marcador del tipo informado, en lugar de comprobar si se copiaron bytes. control == 0 significa que no se informó ningún tipo; un valor no cero distinto de DATA detiene esta llamada recvmsg. Este es el cambio lógico exacto del parche upstream.

Fragmento de origen: net/tls/tls_sw.c — función tls_sw_recvmsg

IMPLEMENTACIÓN VULNERABLE
copied = err;
if (len <= copied ||
    (copied && control != TLS_RECORD_TYPE_DATA) || rx_more)
    goto end;
PARCHE SEGURO Y ROBUSTO
copied = err;
if (len <= copied || rx_more ||
    (control && control != TLS_RECORD_TYPE_DATA))
    goto end;

Lista de Verificación de Seguridad para Ingeniería

Fuentes