FlawOpen

flawopen.com/Teardowns/cve-2024-26585-linux-tls-tx-work-close-race

● CVE-2024-26585 · CVSS 4.7 · Média
Pesquisa · FlawOpen

CVE-2024-26585: corrida TLS no Linux

No kTLS do Linux, a conclusão podia acordar sendmsg/recvmsg antes de enfileirar o trabalho TX. A correção agenda o trabalho primeiro.

💡 Explicação em Linguagem Simples (ELI5)

Um trabalhador avisa a um colega “terminei” antes de colocar sua última tarefa na fila compartilhada. Nesse intervalo, o colega pode fechar a loja e cancelar as tarefas existentes; depois, o trabalhador ainda adiciona uma tarefa. A correção do kernel enfileira o trabalho de transmissão TLS antes de sinalizar a conclusão.

Conceitos Centrais e Termos

kTLS
TLS no kernel Linux, que processa registros TLS no caminho de rede do kernel.
Conclusão de cripto assíncrona
Callback executado depois que uma operação assíncrona de criptografia TLS termina.
`complete()`
Primitiva de conclusão do Linux que desperta uma thread aguardando o fim de uma operação.
Trabalho TX atrasado
Trabalho enfileirado no kernel que continua a transmissão do registro TLS após a criptografia.

Mapeamentos de frameworks

  • Referência CWE para a fraqueza descrita neste guia: CWE-362

Análise de Causa Raiz

Em net/tls/tls_sw.c, tls_encrypt_done() podia chamar complete() para a thread que enviou sendmsg()/recvmsg() antes de agendar o trabalho TX atrasado para o registro no início da fila. A thread acordada pode retornar e fechar o socket enquanto o callback ainda está prestes a enfileirar o trabalho, criando uma corrida entre o encerramento do socket e o agendamento TX. O commit upstream e01e3934a1b2 inverte a ordem: se o registro estiver no início de ctx->tx_list, agenda ctx->tx_work antes de chamar complete(). O aviso descreve uma corrida; as fontes citadas não sustentam as antigas alegações sobre MSG_ZEROCOPY, páginas de rede liberadas, sobrescrita ou correção com refcount_inc_not_zero().

Fluxo de Ataque Passo a Paso

Passo 1

1. Início da transmissão TLS

Um processo usa o caminho de transmissão kTLS, no qual a criptografia do registro pode terminar de forma assíncrona.

Passo 2

2. Callback verifica a ordem

tls_encrypt_done() verifica se o registro concluído está no início de ctx->tx_list.

Passo 3

3. Despertar concorre com fechamento

Antes do patch, o callback podia despertar a thread com complete() e só depois enfileirar o trabalho TX; nesse intervalo, a thread podia fechar o socket.

Passo 4

4. Patch ordena a transferência

A correção enfileira o trabalho TX atrasado primeiro e só então sinaliza a conclusão, impedindo que a thread avance antes do agendamento.

Código-Fonte: Vulnerável vs. Seguro

IMPLEMENTAÇÃO VULNERÁVEL
// Ordem relevante em net/tls/tls_sw.c antes de e01e3934a1b2
bool ready = false;

if (rec == first_rec)
    ready = true;

if (atomic_dec_and_test(&ctx->encrypt_pending))
    complete(&ctx->async_wait.completion);

if (!ready)
    return;

if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
    schedule_delayed_work(&ctx->tx_work.work, 1);
PATCH SEGURO E ROBUSTO
// Ordem relevante em net/tls/tls_sw.c depois de e01e3934a1b2
if (rec == first_rec) {
    // Enfileire o trabalho de transmissão antes de despertar a thread que o enviou.
    if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
        schedule_delayed_work(&ctx->tx_work.work, 1);
}

if (atomic_dec_and_test(&ctx->encrypt_pending))
    complete(&ctx->async_wait.completion);

Lista de Verificação de Segurança para Engenharia

Fontes