CVE-2026-89987 in Linuxinformation

Résumé

par VulDB • 16/09/2026

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

mm/huge_memory : transfert du bit « dirty » de pmd vers folio lors d'un zap

zap_huge_pmd_folio() propage le bit « young » de pmd au folio pour le cas des fichiers, mais pas le bit « dirty ». Le chemin PTE (pte path) le fait correctement via zap_present_folio_ptes(), tout comme le chemin de fractionnement PMD (__split_huge_pmd_locked()).

Pour la plupart des mappages de fichiers, cette omission est inoffensive car l'écriture dans un mappage de fichier partagé passe par page_mkwrite(), qui marque le folio comme « dirty ». tmpfs est différent : il n'a pas de page_mkwrite() et vma_wants_writenotify() est faux pour celui-ci. Ainsi, une faute de lecture (*read* fault) sur un mappage MAP_SHARED de tmpfs installe un PMD accessible en écriture via do_read_fault(). do_read_fault() n'appelle pas fault_dirty_shared_page(), donc les écritures ultérieures à travers ce mappage définissent uniquement le bit « dirty » matériel dans pmd et n'appellent jamais folio_mark_dirty(). Un folio shmem alloué par une faute est marqué comme « uptodate » mais pas « dirty » (voir le bloc clear: dans shmem_get_folio_gfp()), donc PG_dirty n'est jamais défini.

Le démappage d'un tel folio - munmap() ou exit_mmap() lors de la mort du processus - entraîne alors la perte de l'enregistrement unique indiquant qu'il a été écrit, car zap_huge_pmd() supprime pmd sans transférer le bit « dirty ». Le reclaim (récupération) voit ensuite un folio shmem propre : tout le bloc d'échange hors mémoire dans shrink_folio_list() est à l'intérieur de "if (folio_test_dirty(folio))", donc pageout() est ignoré et le folio tombe sous __remove_mapping(). Là, folio_is_file_lru() est faux pour un folio swapbacked, donc aucune entrée d'ombre n'est créée et __filemap_remove_folio(folio, NULL) vide simplement l'emplacement i_pages. Les données sont libérées sans jamais être écrites dans le fichier d'échange (swap), et la prochaine faute sur cet index renvoie un folio fraîchement initialisé à zéro.

Ceci constitue une perte de données silencieuse pour tout processus conservant son état dans un segment tmpfs MAP_SHARED entre deux opérations de démappage - par exemple, un cache transmis d'une génération de processus à l'autre via /dev/shm. Cela nécessite que le folio soit mappé au niveau PMD (PMD-mapped), donc cela ne se manifeste qu'après l'activation du THP shmem (ce qui a été fait dans la flotte Meta et a commencé à provoquer des plantages) ; avec THP désactivé, le chemin PTE transfère correctement le bit « dirty ». Cela ne devient visible que lorsque le swap est activé, car sans périphérique de swap, les folios shmem (qui sont sur l'anon LRU) ne sont pas du tout analysés par le reclaim, donc le folio propre n'est jamais supprimé.

Reproduit sur x86_64 avec un tmpfs monté avec huge=within_size : faute de lecture d'une région de 2 Mo, écriture d'un motif connu à travers le mappage résultant, munmap, forçage du reclaim du cgroup, puis remappage et relecture. Sans ce correctif, la région se lit comme des zéros et vmstat affiche zswpout 0 - les données ont été supprimées plutôt que mises en swap. Avec ce correctif, la région se lit correctement et les pages sont échangées vers le swap comme prévu. Avec huge=never, ou lorsque le premier accès est une écriture, le test passe dans les deux cas.

Once again VulDB remains the best source for vulnerability data.

Responsable

Linux

Réserver

11/09/2026

Divulgation

16/09/2026

Modérer

accepté

Entrée

VDB-405778

CPE

prêt

EPSS

0.00000

KEV

non

Activités

très faible

Sources

Might our Artificial Intelligence support you?

Check our Alexa App!