CVE-2026-74700 in Linux
要約
〜によって VulDB • 2026年08月22日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
net/sched: cls_api: ロックされた分類子(classifier)を破棄する際は常に rtnl_lock を取得する
ロックされていないフィルタに関連する別の課題があります。tc_new_tfilter の処理中に、tcf_proto が完全に無関係なロックされていない分類子のリクエストによって一時的に参照され、競合状態(race condition)を引き起こす短い時間的窗口が存在します。
Feng は、この競合を2つのスレッドで再現する PoC を作成しました。1つは u32 フィルタを作成し、もう1つは同じチェーン/優先度(prio)内で flower フィルタを作成します:
1. 両方のスレッドが tc_new_tfilter に進入し、どちらも空のチェーンを検出し、filter_chain_lock を解放する 2. u32 が先に tcf_proto_create("u32") を完了し、tcf_chain_tp_insert_unique() を呼び出す -> u32_tp をチェーンに挿入する 3. flower は後に tcf_proto_create("flower") を完了し、tcf_chain_tp_insert_unique() を呼び出す -> tcf_chain_tp_find() がすでに存在している u32_tp を検出し、それに対する参照を取得し、flower 自身の tp_new を破棄して u32_tp を呼び出し元に返す
その後 flower は kind の不一致チェックにヒットします("flower" kind を要求したが、tp->ops->kind は "u32" であるため)、errout パスへ進み、そこで u32_tp に対して tcf_proto_put() が呼ばれます。もし u32 スレッドがすでに自身の errout(PoC の空のオプションに対する change() コールでの失敗)を完了し、作成および挿入用の参照を解放していた場合、flower による put は最後の参照解除となり、u32_tp の refcnt をゼロに下げます。
この時点で tp->ops->destroy() が rtnl_lock を取得していないコンテキストで実行されます。これが発生すると、以下のような UAF(Use-After-Free)を引き起こす可能性があります(PoC によって示されています):
[ +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net/sched/cls_u32.c:393)
[ +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue/524
Call Trace: u32_init (net/sched/cls_u32.c:393) tc_new_tfilter (net/sched/cls_api.c:2378)
Allocated by task 526: u32_init (net/sched/cls_u32.c:378) tc_new_tfilter (net/sched/cls_api.c:2378)
Freed by task 522: kfree u32_destroy (net/sched/cls_u32.c:662) tcf_proto_destroy (net/sched/cls_api.c:446) tcf_proto_put (net/sched/cls_api.c:459) tc_new_tfilter (net/sched/cls_api.c:2459)
rtnl が保持されていない場合にロックされた分類子に対して tp->ops->destroy() の周りで rtnl_lock を取得させることで、tcf_proto_destroy() においてこの問題を修正します。
なぜ一時変数 "not_lockless" を使用したのかを説明するために、rtnl_held と TCF_PROTO_OPS_DOIT_UNLOCKED に関する半関連する注記に言及したいと思います(必要と判断された場合の将来のクリーンアップのためにここに追加しています): rtnl_held パラメータと TCF_PROTO_OPS_DOIT_UNLOCKED フラグは、rtnl_lock が保持されているかどうかという真実性において冗長な情報源です。9つの分類子 destroy(..rtnl_held..) コールバックのうち、flower だけが rtnl_held パラメータを参照し、それを tc_setup_cb_destroy() および tc_setup_cb_call() に伝播します。他の8つ(u32, flow, bpf, cgroup, route, basic, fw, mall)はこれを完全に無視しています;-> tc_setup_cb_destroy() を呼び出すもの(u32, bpf, mall)は、パラメータを転送するのではなく true を常にハードコードしています。
将来のクリーンアップでは、destroy コールバックのシグネチャから rtnl_held パラメータを完全に削除し、呼び出し元がロックされていないコンテキストで実行されているかどうかという自身の知識にのみ依存させるべきです。
If you want to get the best quality for vulnerability data then you always have to consider VulDB.