FlawOpen

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

● CVE-2024-26585 · CVSS 4.7 · Moyenne
Recherche · FlawOpen

CVE-2024-26585 : course TLS Linux

Dans kTLS sous Linux, la fin pouvait réveiller sendmsg/recvmsg avant la mise en file du travail TX. Le correctif planifie le travail avant.

💡 Explication en Langage Simple (ELI5)

Un employé dit à son collègue « j’ai fini » avant de placer sa dernière tâche dans la file partagée. Entre-temps, le collègue peut fermer l’atelier et annuler les tâches en attente ; l’employé ajoute alors une tâche trop tard. Le correctif du noyau met le travail d’émission TLS en file avant de signaler la fin.

Concepts Clés et Termes

kTLS
TLS dans le noyau Linux, qui traite les enregistrements TLS dans la pile réseau du noyau.
Fin de chiffrement asynchrone
Callback exécuté après la fin d’une opération asynchrone de chiffrement TLS.
`complete()`
Primitive de completion Linux qui réveille un thread attendant la fin d’une opération.
Travail TX différé
Travail mis en file dans le noyau qui poursuit l’émission TLS après le chiffrement.

Correspondances de référentiels

  • Référence CWE pour la faiblesse décrite dans ce guide : CWE-362

Analyse de Cause Racine

Dans net/tls/tls_sw.c, tls_encrypt_done() pouvait appeler complete() pour le thread sendmsg()/recvmsg() avant de planifier le travail TX différé du premier enregistrement. Le thread réveillé peut revenir et fermer le socket alors que le callback s’apprête encore à mettre ce travail en file, ce qui crée une course entre la fermeture et la planification TX. Le commit upstream e01e3934a1b2 inverse l’ordre : si l’enregistrement est en tête de ctx->tx_list, il planifie ctx->tx_work avant d’appeler complete(). L’avis décrit une course ; les sources citées ne justifient pas les anciennes affirmations sur MSG_ZEROCOPY, des pages réseau libérées, une écriture mémoire ou un correctif par refcount_inc_not_zero().

Déroulement de l'Attaque Étape par Étape

Étape 1

1. Début de l’émission TLS

Un processus utilise le chemin d’émission kTLS, où le chiffrement des enregistrements peut être asynchrone.

Étape 2

2. Le callback vérifie l’ordre

tls_encrypt_done() vérifie si l’enregistrement terminé est en tête de ctx->tx_list.

Étape 3

3. Le réveil entre en course avec la fermeture

Avant le patch, le callback pouvait réveiller le thread avec complete() puis mettre le travail TX en file ; le thread pouvait fermer le socket entre les deux.

Étape 4

4. Le patch ordonne le transfert

Le correctif met d’abord le travail TX différé en file, puis signale la fin, empêchant le thread d’avancer avant la planification.

Code Source : Vulnérable vs Sécurisé

IMPLÉMENTATION VULNÉRABLE
// Ordre pertinent dans net/tls/tls_sw.c avant 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 SÉCURISÉ ET ROBUSTE
// Ordre pertinent dans net/tls/tls_sw.c après e01e3934a1b2
if (rec == first_rec) {
    // Planifiez le travail de transmission avant de réveiller le thread émetteur.
    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);

Liste de Contrôle de Sécurité pour l'Ingénierie

Sources