CVE-2026-98980 in Linuxinformazioni

Riassunto

di VulDB • 23/10/2026

Nel kernel Linux è stata risolta la seguente vulnerabilità:

namei: non rivelare le voci sovrapposte durante il refwalk

In rcuwalk, l'entry (dentry) viene validata prima di essere accettata. step_into() verifica nuovamente d_seq e __follow_mount_rcu() verifica nuovamente mount_lock. Un'entry che viene disconnessa nel frattempo causa un nuovo tentativo della lookup con esito negativo.

Un refwalk non effettua questa operazione. lookup_fast() acquisisce un riferimento sull'dentry hashata e la accetta semplicemente. Pertanto, una unlink effettuata dopo l'acquisizione del riferimento non viene rilevata dal refwalk. Questo è accettabile per un file semplice: ci siamo limitati ad aprirlo prima che venisse disconnesso, senza problemi.

Per un mountpoint e in particolare per un mountpoint bloccato, la situazione è molto diversa. La unlink stacca tutti i mount successivamente rimuove il nome. Qualsiasi refwalk che non ha ancora attraversato i mount rivela semplicemente l'entry sottostante. Si tratta di una finestra temporale molto stretta ma può essere colpita:

letture di un file coperto in 60 s, con 3 walker, ~15000 unlink senza allargamento 27 quello step + 200 us 3741

Vedere il patch allegato per un riproduttore più affidabile.

Quindi controllare l'entry dopo step_into(). unlink(), rmdir() e rename() contrassegnano la dentry con dont_mount() prima di staccare i mount ed eliminare la dentry.

Una dentry che è marcata con DCACHE_CANT_MOUNT ed è dishashata al momento in cui vengono esaminati i suoi mount, rappresenta un nome che è stato unlinkato durante il refwalk. DCACHE_CANT_MOUNT viene letto dopo che i mount sono stati cercati e viene impostato prima che vengano staccati da detach_mounts(). Un refwalk che ha perso l'accesso ai mount vedrà DCACHE_CANT_MOUNT.

La semplice d_unlinked() è sufficiente. Una rename toglie la dentry dalla sua catena hash ma ___d_drop() lascia d_hash.pprev impostato. Quindi solo __d_drop() e una rename sopra la dentry lo dishashano. L'unica operazione che inverte IS_ROOT effettua uno splice di un alias disconnected. Questo non ha DCACHE_CANT_MOUNT impostato.

Aggiungere il controllo a step_into_slowpath(). ".." e LOOKUP_DOWN possono legittimamente atterrare su una directory dishashata. Un refwalk che è transitato su un mount avrà path.mnt diverso da nd->path.mnt. Una dentry che un filesystem ha eliminato autonomamente (d_invalidate(), d_drop()) non ha il flag impostato ed è trattata come in precedenza.

// SPDX-License-Identifier: GPL-2.0 /* * unlink_covered: unlink a file that is a mountpoint in a detached copy of * its mount, against walkers that open it through that copy. * * A is a tmpfs with the file f1 (content SECRET_F) and the plain file * MARK_A. A' is an open_tree(OPEN_TREE_CLONE) copy of A with MARK_A bound * on A'/f1, held through an O_PATH fd on its root once the tree fd is * closed. Walkers open f1 through that fd while the driver unlinks A/f1, * where nothing is mounted on it. A walker may read MARK_A or get ENOENT. * A read of SECRET_F is a hit: the name was found after its mount was * gone. The lockless walks use openat2(RESOLVE_CACHED). * * usage: unlink_covered [-t seconds] [-w walkers]
*/ #ifndef _GNU_SOURCE #define _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 #define __NR_open_tree 428 #endif #ifndef __NR_move_mount #define __NR_move_mount 429 #endif #ifndef __NR_openat2 #define __NR_openat2 437 #endif #ifndef OPEN_TREE_CLONE #define OPEN_TREE_CLONE 1 #endif #ifndef OPEN_TREE_CLOEXEC #define OPEN_TREE_CLOEXEC O_CLOEXEC #endif #ifndef MOVE_MOUNT_F_EMPTY_PATH #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 #endif

#define WORK "/tmp/uc" #define ADIR WORK "/A"

static int duration = 60, nwalkers = 3; static atomic_int stop, writer_waiting; static pthread_rwlock_t cur_lock = PTHREAD_RWLOCK_INITIALIZER; static int cur_fd = -1; /* the root of A', -1 while there is none */ static atomic_long n_unlink, n_walk, n_mark, n_enoent, n_othe ---truncated---

Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.

Responsabile

Linux

Prenotare

25/09/2026

Divulgazione

23/10/2026

Moderazione

accettato

EPSS

0.00209

KEV

no

Attività

basso

Fonti

Want to know what is going to be exploited?

We predict KEV entries!