CVE-2026-98981
>_ Opis
Tłumaczenie automatyczne – może zawierać nieścisłości.
W jądrze Linuksa usunięto następującą lukę:
namespace: odblokuj dentry przed odłączeniem od niego wierzchowców
unlink(), rmdir() i rename() usuwają wpis z systemu plików,
wywołaj detach_mounts() na wpisie z zablokowanym i-węzłem, a następnie wywołaj
d_delete() po odblokowaniu i-węzła.
Rzecz w tym, że pomiędzy detach_mounts() i d_delete() dentry jest
nadal zaszyfrowany i pozytywny. Ale po odłączeniu() nic nie obejmuje
już dentysta. Wyszukiwanie, które znajdzie ten dentry w puszce dcache
odkryj to, co skrywały wierzchowce.
Stanowi to problem podczas odłączania plików lub katalogów, które są
punkty montowania w innych przestrzeniach nazw montowania. Każdy, kto miał podstawy
objęty wpis może ścigać się z wywołaniem detach_mount() do momentu uruchomienia d_delete().
Okno wyścigu nie jest wcale takie małe. Obejmuje namespace_unlock()
z pełnym okresem karencji synchronizacji_rcu_expedited() i
inode_unlock() wpisu.
W moich eksperymentach trzech piechurów, którzy próbowali czytać na wierzchołku
plik w 11938 z 16140 odłączeń, które usunęły jego punkt montowania z pliku
powiąż montowanie systemu plików w ciągu minuty.
Ciekawostka, d_invalidate() ma ten sam problem z porządkowaniem, ale go rozumie
prawda. Najpierw usuwa zęby, a następnie odłącza mocowania.
Zróbmy to samo w __detach_mounts():
- Wyszukiwanie, które nie znalazło jeszcze dentry, pomija ją w dcache i
czeka na blokadę katalogu, którą osoba wywołująca przechowuje do momentu pojawienia się nazwy
zniknął na dobre.
- Wyszukiwanie bez blokady, które znalazło, już nie przeszło kontroli mount_lock
podczas gdy dentry nadal liczy się jako punkt montowania i sprawdzenie d_seq raz
tak się nie dzieje i próbuje ponownie.
To naprawia ścieżkę bez blokady. Musimy jeszcze ustalić liczbę referencji
wyszukaj w kolejnej łatce.
Więc d_drop() dentysta. Zęby pozostają pozytywne i trzymają się, lecz nie jest to możliwe
już nie znaleziono. Następnie kontynuuj odłączanie i rozłączanie.
Producent:
Odczyty zliczano za pomocą poniższego programu, trzech spacerowiczów przez 60 s
na maszynie wirtualnej z 4 procesorami. Okno wyścigu jest rozciągnięte przez łatkę debugującą
wklejony tutaj. fs.detach_race_walk_us śpi w funkcji lookup_fast().
znalazł ząb wierzchowca i zanim jego wierzchowce zostały przekroczone.
fs.detach_race_unlink_us śpi w vfs_unlink() pomiędzy detach_mounts()
i d_delete().
// Identyfikator licencji SPDX: GPL-2.0
/*
* unlink_covered: odłącz plik będący punktem montowania w odłączonej kopii
* jego wierzchowiec, względem wyszukiwań, które otwierają go przez tę kopię.
*
* A to tmpfs z plikiem f1 (zawartość SECRET_F) i zwykłym plikiem
* MARK_A. A' jest kopią open_tree(OPEN_TREE_CLONE) A z powiązaniem MARK_A
* na A'/f1, utrzymywany przez O_PATH fd w jego korzeniu, gdy drzewo fd jest
* zamknięte. Walkery otwierają f1 przez ten fd, podczas gdy kierowca odłącza A/f1,
* gdzie nic nie jest na nim zamontowane. Pieszo może przeczytać MARK_A lub otrzymać ENOENT.
* Czytanie SECRET_F jest strzałem w dziesiątkę: nazwa została znaleziona po odkryciu wierzchowca
* zniknęło. Spacery bez zamków używają openat2 (RESOLVE_CACHED).
*
* użycie: unlink_covered [-t sekund] [-w spacerowiczów]
*/
#ifndef _GNU_SOURCE
#zdefiniuj _GNU_SOURCE
#endif
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <linux/openat2.h>
#ifndef __NR_open_tree
#zdefiniuj __NR_open_tree 428
#endif
#ifndef __NR_move_mount
#zdefiniuj __NR_move_mount 429
#endif
#ifndef __NR_openat2
#zdefiniuj __NR_openat2 437
#endif
#ifndef OPEN_TREE_CLONE
#zdefiniuj OPEN_TREE_CLONE 1
#endif
#ifndef OPEN_TREE_CLOEXEC
#zdefiniuj OPEN_TREE_CLOEXEC O_CLOEXEC
#endif
#ifndef MOVE_MOUNT_F_EMPTY_PATH
#zdefiniuj MOVE_MOUNT_F_EMPTY_PATH 0x00000004
#endif
#zdefiniuj PRACĘ „/tmp/uc”
#define ADIR PRACA „/A”
statyczny int czas trwania = 60, nwalkers = 3;
statyczny atomic_int stop, write_waiting;
statyczny pthread_rwlock_t cur_lock = PTHREAD_RWLOCK_INITIALIZER;
statyczny int cur_fd = -1; /* pierwiastek A', -1 wh
---obcięty---
>_ Referencje
- https://git.kernel.org/stable/c/528b383dc35d1e5caf64ddf5d35f983ae543b0d0
- https://git.kernel.org/stable/c/8300de4aa5d09061bfcf2af5b52c0cdba3873185
- https://git.kernel.org/stable/c/8d71bfc9b3fc15d7103e82ea9dc5057541866e46
- https://git.kernel.org/stable/c/d29cd99db3db74cf3447be74d25740981789d461
- https://git.kernel.org/stable/c/db90eecbde319527aa9480c039d32a0f5fe80574
Dane podatności pochodzą z oficjalnych źródeł (CVE® List / NVD). Opisy po polsku są tłumaczone automatycznie i mogą zawierać nieścisłości – na stronie rekordu można wyświetlić wersję angielską.
This product uses the NVD API but is not endorsed or certified by the NVD.
Copyright © 1999–2026, The MITRE Corporation. CVE is a registered trademark and the CVE logo is a registered trademark of The MITRE Corporation.
CVE Usage: MITRE hereby grants you a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Common Vulnerabilities and Exposures (CVE®). Any copy you make for such purposes is authorized provided that you reproduce MITRE's copyright designation and this license in any such copy. ALL DOCUMENTS AND THE INFORMATION CONTAINED THEREIN PROVIDED BY MITRE ARE PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
NVD Terms of Use / CVE® Terms of Use / nvd.nist.gov / cve.org