CVE-2026-98980 in Linux情報

要約

〜によって VulDB • 2026年10月23日

Linuxカーネルにおいて、以下の脆弱性が修正されました:

namei: refwalk中にオーバーマウントされたエントリを公開しない

rcuwalkでは、dentryが受け入れられる前に検証が行われます。step_into()はd_seqを再チェックし、__follow_mount_rcu()はmount_lockを再チェックします。その間にアンリンク(削除)されると、ルックアップは再試行され、結果を見逃すことになります。

refwalkはこの処理を行いません。lookup_fast()はハッシュ化されたdentryへの参照を取得し、単純にそれを受け入れます。したがって、参照が取得された後に発生するunlink操作は、refwalkからは検知されません。これは通常のファイルでは問題ありません。アンリンクされる前にファイルをオープンしたとしても、何の問題もありません。

しかし、マウントポイント、特にロックされたマウントポイントの場合、それは非常に深刻な問題です。unlink操作によりすべてのマウントがデタッチされ、その後名前が削除されます。まだマウントを横断していないrefwalkは、基盤となるエントリを単純に公開してしまいます。これは非常に狭いウィンドウですが、以下のような条件で発生し得ます:

カバードされたファイルの読み取り(60秒間、3人のウォーカー、約15,000回のunlink) ウィドニングなし 27回 そのステップ + 200 us 3741回

より信頼性の高い再現コードについては添付パッチを参照してください。

したがって、step_into()の後にエントリをチェックする必要があります。unlink(), rmdir(), rename()は、マウントをデタッチしdentryを削除する前に、dont_mount()フラグでdentryにマークを付けます。

つまり、DCACHE_CANT_MOUNTでマークされ、かつそのマウントが参照される時点でハッシュから外されているdentryは、refwalk中にアンリンクされた名前です。DCACHE_CANT_MOUNTは、マウントのルックアップ後に読み取られ、detach_mounts()によってデタッチされる前に設定されます。マウントを見逃したrefwalkは、DCACHE_CANT_MOUNTを検出します。

単純なd_unlinked()チェックでは不十分です。rename操作はdentryをハッシュチェーンから外しますが、___d_drop()はd_hash.pprevを設定したままにしておきます。したがって、__d_drop()とdentry上でのrenameのみがこれをアンハッシュ化します。IS_ROOTフラップを変更する唯一の移動は、切断されたエイリアスをスパイスインすることです。これにはDCACHE_CANT_MOUNTフラグは設定されていません。

このチェックをstep_into_slowpath()に追加します。「..」およびLOOKUP_DOWNでは、 legitimately(正当な理由で)アンハッシュ化されたディレクトリに着地する可能性があります。マウントを横断したrefwalkの場合、path.mntはnd->path.mntとは異なります。ファイルシステムが独自にドロップしたdentry(d_invalidate(), d_drop()によるもの)にはフラグが設定されておらず、以前と同様に扱われます。

// SPDX-License-Identifier: GPL-2.0 /* * unlink_covered: マウントポイントであるファイルを、そのマウントのデタッチされたコピーに対してアンリンクし、 * そのコピーを通じてファイルを開くウォーカーに対するテストを行います。 * * Aはtmpfsで、ファイルf1(内容:SECRET_F)とプレーンなファイルMARK_Aを含みます。A'はopen_tree(OPEN_TREE_CLONE)によるAのコピーで、MARK_AがA'/f1にバインドされており、ツリーfdを閉じた後にそのルートに対するO_PATH fdによって保持されます。ウォーカーはそのfdを通じてf1を開きますが、ドライバーはA/f1(そこに何もマウントされていない)のアンリンクを行います。ウォーカーはMARK_Aを読み取るか、ENOENTエラーを受け取ります。SECRET_Fの読み取りはヒットとなります:名前はマウントが消えた後に見つかったからです。ロックレスなウォークにはopenat2(RESOLVE_CACHED)が使用されます。 * * 使用方法: 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; /* A'のルート、存在しない場合は-1 */ static atomic_long n_unlink, n_walk, n_mark, n_enoent, n_othe ---truncated---

If you want to get best quality of vulnerability data, you may have to visit VulDB.

責任者

Linux

予約する

2026年09月25日

モデレーション

承諾済み

エントリ

VDB-425767

EPSS

0.00000

アクティビティ

低い

ソース

Want to know what is going to be exploited?

We predict KEV entries!