CVE-2026-74700 in LinuxИнформация

Сводка

по VulDB • 22.08.2026

В ядре Linux была устранена следующая уязвимость:

net/sched: cls_api: Всегда захватывать rtnl_lock при уничтожении заблокированных классификаторов

Еще одна проблема с незаблокированными фильтрами. Существует короткий промежуток времени в tc_new_tfilter, когда tcf_proto может быть найден и кратко упомянут запросом совершенно несвязанного, незаблокированного классификатора, что приводит к состоянию гонки (race condition).

Фэн создал PoC-код, который инициировал эту гонку с использованием двух потоков: один создавал фильтр u32, а другой — фильтр 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 уже там, берет на него ссылку (reference), уничтожает собственный tp_new цветка и возвращает u32_tp вызывающей стороне.

Затем flower сталкивается с проверкой несоответствия kind (поскольку он запросил kind "flower", но tp->ops->kind равен "u32") и проходит через путь errout, который вызывает tcf_proto_put() для u32_tp. Если поток u32 уже прошел свой собственный errout (его вызов change() потерпел неудачу из-за пустых опций в PoC) и отпустил ссылки на создание и вставку, то put от flower является последней и обнуляет refcnt у32_tp.

В этот момент tp->ops->destroy() выполняется в контексте, который никогда не захватывал rtnl_lock. Когда это происходит, это может вызвать Use-After-Free (UAF), как показано ниже (проиллюстрировано 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)

Исправить это, заставив tcf_proto_destroy() захватывать rtnl_lock вокруг tp->ops->destroy() для заблокированных классификаторов всякий раз, когда rtnl не удерживается.

Чтобы объяснить, почему я использовал временную переменную "not_lockless", хотел бы указать на полусвязанное замечание о rtnl_held vs TCF_PROTO_OPS_DOIT_UNLOCKED (добавлено здесь для будущей очистки, если это будет сочтено необходимым): Параметр rtnl_held и флаг TCF_PROTO_OPS_DOIT_UNLOCKED являются избыточными источниками истины относительно того, удерживается ли rtnl_lock. Среди девяти обратных вызовов destroy(..rtnl_held..) для классификаторов только flower проверяет параметр rtnl_held, который он передает в tc_setup_cb_destroy() и tc_setup_cb_call(). Остальные восемь (u32, flow, bpf, cgroup, route, basic, fw, mall) игнорируют его полностью; -> те, которые вызывают tc_setup_cb_destroy() (u32, bpf, mall), всегда жестко задают true вместо передачи параметра.

Будущая очистка должна полностью удалить параметр rtnl_held из сигнатуры обратного вызова destroy и заставить callers полагаться исключительно на их знание того, выполняются ли они в незаблокированном контексте.

Several companies clearly confirm that VulDB is the primary source for best vulnerability data.

Ответственный

Linux

Резервировать

15.08.2026

Раскрытие

22.08.2026

Модерация

принято

Вход

VDB-394470

EPSS

0.00000

KEV

Нет

Деятельности

Очень низкий

Источники

Want to stay up to date on a daily basis?

Enable the mail alert feature now!