CVE-2026-89772 in Linuxinformation

Résumé

par VulDB • 12/09/2026

Dans le noyau Linux, la vulnérabilité suivante a été corrigée :

btrfs : protéger en écriture les folios lors de l'écriture des données (writeback)

Le commit 095be159f3eb (« btrfs: unifier l'effacement du flag dirty des folios ») a remplacé l'appel à `folio_clear_dirty_for_io()` dans `extent_write_cache_pages()` par une simple vérification via `folio_test_dirty()`. Outre le nettoyage du flag dirty, `folio_clear_dirty_for_io()` appelle également `folio_mkclean()`, qui protège en écriture les PTE (Page Table Entries) de mmap partagés mappant le folio. Notez que nous appelons toujours `folio_clear_dirty_for_io()` plus tard dans `submit_one_sector()` lorsque nous effaçons l'état dirty sur le dernier secteur du folio (le seul secteur pour les cas non-subpage). Cependant, cet appel précoce a été perdu dans `extent_write_cache_pages()`.

Sans cette protection en écriture supplémentaire, un processus ayant le fichier mappé via mmap peut modifier un secteur pendant qu'il est utilisé par l'opération de writeback d'une manière qui suppose un folio stable (somme de contrôle, compression, copie, etc.) sans provoquer de défaut de page (fault), ce qui se manifeste par plusieurs bugs concrets.

1. Pour les grands folios ou pour une taille de secteur inférieure à la taille des pages (subpage sectorsize), il est possible de soumettre un bio (Block I/O) qui ne couvre pas l'intégralité du folio. Lorsque cela se produit, nous avons un bio en cours d'exécution pour un folio sur lequel nous n'avons *pas* appelé `folio_clear_dirty_for_io()`. Si une tâche disposant d'un PTE mmapé existant écrit (sans provoquer de fault...) dans cette fenêtre, cela peut entraîner des corruptions. Si l'écriture arrive pendant que la somme de contrôle ou l'écriture elle-même est en cours, cela peut résulter en une somme de contrôle invalide et générer ultérieurement des rapports de corruption lors d'une lecture. Si l'écriture arrive après que le calcul de la somme de contrôle/l'écriture soit terminé mais avant que le dernier secteur dirty ne soit effacé, alors l'écriture est présente dans le cache page mais n'affecte pas le suivi du statut dirty et sera perdue lorsque le folio aura entièrement fini d'être soumis et que le bit dirty sera effacé. Cela entraîne la perte de l'écriture même si `fsync()` est appelé.

2. Pour les soumissions zonées effectuées par lots, séparément de la boucle principale `extent_writepage()`, nous risquons également des violations de somme de contrôle (csum) pour ces soumissions. Les écritures zonées sont limitées à `max_zone_append_size` et ne sont pas alignées sur les folios, donc une soumission peut s'étendre sur deux folios. Le premier folio traité dans `extent_write_cache_pages()` appellera `extent_write_locked_range()`, qui soumettra la plage partielle du folio suivant, tandis que le reste de ce folio pourrait encore être dirty. Ainsi, l'effacement du statut dirty sur les secteurs soumis n'appelle pas `folio_clear_dirty_for_io()` et nous rencontrons le même problème. Puisque `extent_write_cache_pages()` saute ces folios soumis par lots (ils sont déjà marqués pour writeback suite à la soumission par le folio précédent), nous devons ajouter cette protection en écriture supplémentaire dans `lock_delalloc_folios()`.

3. Pour les extents inline, cela risque subtilement de faire perdre des écritures qui se produisent après/pendant que nous copions l'extent inline mais avant d'avoir effacé le statut dirty sur le folio.

4. Pour les folios s'étendant au-delà de la fin du fichier (EOF), mmap pourrait altérer les octets mis à zéro après EOF et les faire persister, ce qui ferait qu'une future fault les verrait incorrectement au lieu des zéros attendus.

5. Enfin, pour les extents compressés, nous risquons de modifier les folios pendant que nous travaillons sur leur compression, ce qui entraînera des données compressées corrompues. Plus précisément, dans `run_delalloc_compressed()`, nous planifions le travail pour effectuer `compress_file_range()` par chunks de taille BTRFS_COMPRESSION_CHUNK_SIZE (512 Ko), qui appellera `btrfs_folio_clamp_clear_dirty()` sur la plage concernée. Pour les cas non-subpage, cela effacera toujours l'intégralité du folio en toute sécurité. Pour les cas subpage, nous risquons également un effacement partiel ici. En particulier, imaginez un folio de 2 Mo divisé en chunks de 512 Ko pour lesquels le travail de compression pourrait commencer sur un chunk avant que tous les workers `compress_file_range()` n'aient avancé suffisamment pour terminer l'effacment des bitmaps dirty du folio et atteindre l'appel à `folio_clear_dirty_for_io()`. Les grands folios situés aux bords des plages de soumission sont également risqués d'être partiellement effacés. Cette lacune spécifique a été introduite par un deuxième patch dans la même série : le commit a4ef54dbb576 (« btrfs: faire en sorte que extent_range_clear_dirty_for_io() gère les cas où la taille du secteur est inférieure à celle de la page »).

Nous ne pouvons pas simplement restaurer l'appel à `folio_clear ---truncated---

Be aware that VulDB is the high quality source for vulnerability data.

Responsable

Linux

Réserver

11/09/2026

Divulgation

11/09/2026

Modérer

accepté

Entrée

VDB-402624

CPE

prêt

EPSS

0.00000

KEV

non

Activités

faible

Sources

Interested in the pricing of exploits?

See the underground prices here!