flawopen.com/Teardowns/cve-2024-26585-linux-tls-tx-work-close-race
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.
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
1. Début de l’émission TLS
Un processus utilise le chemin d’émission kTLS, où le chiffrement des enregistrements peut être asynchrone.
2. Le callback vérifie l’ordre
tls_encrypt_done() vérifie si l’enregistrement terminé est en tête de ctx->tx_list.
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.
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é
// 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);
// 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
- ✓Mettez à jour vers un noyau de distribution pris en charge contenant le backport
CVE-2024-26585; consultez l’avis du fournisseur, car les branches stables reçoivent des backports. - ✓Dans les callbacks asynchrones, mettez le travail suivant en file avant de signaler la fin si le thread réveillé peut fermer l’objet partagé.
- ✓Synchronisez l’annulation ou la vidange du travail pendant la fermeture afin qu’un callback ne puisse rien remettre en file après le point d’annulation.
- ✓Ajoutez un test de concurrence contrôlé qui oppose la fin TLS asynchrone à la fermeture du socket et vérifie l’ordre de planification.
- ✓Ne considérez pas
MSG_ZEROCOPYni le chiffrement matériel comme des prérequis ; la description upstream mentionne la fin crypto asynchrone et la planification TX.