CVE: CVE-2026-98070
Продукт: Linux Kernel
Дата публикации: 25.09.2026
Критичность: HIGH
CVSS: 8.1 (3.1)
EPSS: нет данных; процентиль нет данных
CISA KEV: нет подтверждения в каталоге CISA KEV
Краткое описание
В Linux kernel исправлена гонка в модуле net/rds при обработке reset callbacks для TCP. Старый код ждал освобождения флага RDS_IN_XMIT, но на слаботранзакционных архитектурах это не исключало повторный захват флага отправителем и параллельное переписывание состояния cp_xmit_* вместе с заменой сокета.
Нарушается взаимное исключение между путями отправки и сброса. Это приводит к повреждению данных ядра, потере целостности соединения и возможному отказу работы RDS-сервисов.
Основные характеристики
Риск связан с гонкой в ядре Linux при обработке TCP-соединений RDS. Один поток может одновременно менять состояние передачи и заменять сокет, что нарушает инварианты модуля net/rds.
- Тип ошибки: race condition / store-buffering в слаботранзакционной архитектуре
- CVSS 3.1:
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H, оценка 8.1, severity HIGH
- Условие атаки: удалённый доступ к RDS-сервису или возможность инициировать reset TCP-соединения в уязвимой системе
- Факт эксплуатации: не подтверждён в предоставленных источниках
- EPSS: нет данных; процентиль не указан
Какие продукты и версии затронуты
Затронут Linux kernel с модулем net/rds, где используется функция rds_tcp_reset_callbacks(). Пакет доказательств не содержит точного списка версий ядра и дистрибутивов.
- Компонент:
net/rds/tcp.cв ядре Linux
- Функция:
rds_tcp_reset_callbacks()
- Связанные функции:
rds_send_xmit(),rds_send_path_reset(),rds_conn_shutdown(),tcp_sendmsg()
- Версии: не раскрыты в предоставленных источниках
- Дистрибутивы: не раскрыты в предоставленных источниках
Причина уязвимости
Старый код вызывал wait_event(), ожидая, что флаг RDS_IN_XMIT будет снят. Это только читало состояние флага и не блокировало повторный захват другим потоком.
После возврата из wait_event() функция rds_send_xmit() могла снова установить RDS_IN_XMIT. Между путями reset и send возникла store-buffering гонка: resetter записывал state и читал bit, sender записывал bit и читал state. На слаботранзакционных архитектурах оба потока могли не увидеть запись друг друга.
В результате rds_send_path_reset() переписывала cp_xmit_* одновременно с работой отправки. Это нарушало условие, которое комментарий над rds_send_path_reset() требует соблюдать: вызов должен быть защищён от параллельного изменения состояния передачи.
Дополнительно старый код кэшировал t_sock до ожидания. Если teardown в rds_conn_shutdown() освобождал сокет и очищал t_sock, застаревший указатель мог остаться в памяти reset-потока. После пробуждения accept path мог получить невалидный или уже освобождённый указатель.
Отдельная ветка !osock вызывала rds_send_path_reset() без какой-либо сериализации. Теперь она выполняется под RDS_IN_XMIT, как и основной путь.
Как работает атака
Атака использует гонку между двумя путями: reset TCP-соединения в RDS и отправка данных по этому соединению.
Первый поток вызывает rds_tcp_reset_callbacks(). Он устанавливает состояние пути в RDS_CONN_RESETTING, чтобы остановить новых отправителей. Затем он ждёт освобождения RDS_IN_XMIT.
Второй поток находится внутри tcp_sendmsg() или вызывающей функции и может войти в rds_send_xmit(). После того как wait_event() вернул управление reset-потоку, второй поток может снова захватить RDS_IN_XMIT.
Из-за слабой порядковости записей процессоры могут не показать друг другу обновления state и bit. Reset-поток видит флаг очищенным, но на самом деле sender уже владеет им. Sender видит старое состояние, но resetter уже начал менять cp_xmit_*.
Оба потока начинают одновременно работать с одним и тем же состоянием передачи. rds_send_path_reset() перезаписывает cp_xmit_*, а rds_send_xmit() использует эти поля для отправки. Это приводит к повреждению структуры соединения, потере пакетов, некорректным переходам состояния RDS_CONN_RESETTING / RDS_CONN_UP и возможному падению ядра или отказу сервиса.
Отдельный сценарий связан со старым указателем t_sock. Если teardown освободил сокет до пробуждения reset-потока, указатель может быть невалидным. Использование такого указателя нарушает память и может вызвать crash или повреждение данных.
Условия успешной эксплуатации
Для успешной эксплуатации нужны следующие условия.
- Система использует Linux kernel с уязвимым модулем net/rds
- Включён подсистема RDS или сервис, использующий RDS TCP
- Есть возможность инициировать reset TCP-соединения в RDS: например, обрыв соединения, duelling SYN, повторный connect/accept или принудительный shutdown
- Архитектура поддерживает слабую порядковость записей или гонка может воспроизводиться на других архитектурах при определённых условиях переключения потоков
- Уязвимая версия ядра не обновлена до исправленной ветки stable
Возможный сценарий атаки
Сценарий начинается с RDS-соединения между двумя узлами. На одном из узлов происходит reset TCP-соединения, например из-за duelling SYN или ошибки соединения.
Reset-поток вызывает rds_tcp_reset_callbacks(). Он переводит путь в состояние RDS_CONN_RESETTING и ждёт освобождения RDS_IN_XMIT. В это время другой поток пытается отправить данные по тому же соединению через tcp_sendmsg().
После возврата из ожидания reset-поток начинает менять cp_xmit_* и заменять сокет. Если sender успел снова захватить RDS_IN_XMIT, оба потока работают одновременно. Переписывание состояния передачи происходит без взаимного исключения.
Результатом может стать повреждение структуры rds_conn_path или cp_transport_data. Соединение может перейти в некорректное состояние, пакеты могут потеряться, а сервис RDS может перестать отвечать. При использовании stale t_sock возможна работа с освобождённым указателем сокета.
После обновления ядра до стабильной ветки с исправлением reset-поток захватывает RDS_IN_XMIT через test_and_set_bit_lock(), удерживает флаг на протяжении замены сокета и вызова rds_send_path_reset(), затем освобождает его и будит ожидающие потоки. Это исключает параллельное выполнение.
Ссылки на исправления:
- net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks()
- net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks()
- net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks()
- net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks()
Есть ли публичный эксплойт
В предоставленных источниках нет информации о публичном эксплойте, PoC или подтверждённой эксплуатации CVE-2026-98070.
Исправление опубликовано в stable tree Linux kernel. Это означает, что техническое описание уязвимости и патч доступны в ядре. Но факт того, что кто-то использует эту гонку для компрометации систем, не подтверждён.
Отсутствие публичного эксплойта не означает, что эксплуатация невозможна. Условие AC:H указывает на сложность автоматизации: нужно попасть в узкое окно гонки между reset и send потоками, а также иметь доступ к RDS-сервису или возможность инициировать reset соединений.
Для оценки риска достаточно проверить версию ядра и наличие модуля net/rds. Если сервис использует RDS TCP, обновление до исправленной stable-ветки является приоритетным.
Признаки эксплуатации
Специфичных IOC для CVE-2026-98070 в предоставленных источниках нет.
Можно использовать только общие точки контроля, которые не являются уникальными признаками этой уязвимости.
- Рост числа RDS reset callbacks или ошибок TCP в ядре
- Внезапное увеличение количества обрывов соединений RDS
- Падения ядра или kernel panic с участием net/rds, tcp, socket или memory corruption
- Аномальные задержки в RDS-сервисах после массовых reconnect/accept операций
- Появление некорректных состояний RDS_CONN_RESETTING / RDS_CONN_UP в логировании ядра
- Рост числа ошибок cancel_delayed_work_sync или lock_sock в trace
Эти признаки неспецифичны и могут появляться при других сбоях сети, нагрузки или конфигурации.
Как обнаружить атаку
Для обнаружения атаки или последствий уязвимости можно использовать мониторинг ядра и сетевого состояния.
- Проверить версию ядра с командами
uname -r,uname -aиcat /proc/version
- Проверить, загружен ли модуль net/rds:
lsmod | grep rdsилиmodinfo rdsесли доступен
- Смотреть kernel log на ошибки RDS, TCP reset, socket lock, memory corruption
- Использовать ftrace или bpftrace для отслеживания вызовов rds_tcp_reset_callbacks(), rds_send_xmit(), tcp_sendmsg()
- Мониторить количество соединений RDS и частоту reset/duelling SYN
- Проверять журналы приложений, использующих RDS, на повторные обрывы и reconnect
Конкретных сигнатур для этой CVE нет. Детекция опирается на аномалии поведения RDS TCP и ошибки ядра.
Полезные команды:
Bash:
uname -r
uname -a
cat /proc/version
lsmod | grep rds
dmesg | grep -iE 'rds|tcp reset|socket lock|panic'
journalctl -k | grep -iE 'rds|tcp reset|socket lock|panic'
Как проверить свою версию
Проверить версию ядра можно стандартными командами.
uname -r— краткая версия ядра
uname -a— полная информация о ядре и архитектуре
cat /proc/version— версия ядра из runtime
Если используется дистрибутив, дополнительно проверять пакет kernel через пакетный менеджер:
Bash:
dpkg -l | grep linux-image # Debian/Ubuntu
rpm -qa | grep kernel # RHEL/CentOS/Fedora
apt-cache policy linux-image # Debian/Ubuntu
yum list installed kernel # RHEL/CentOS/Fedora
Точный список исправленных версий не раскрыт в предоставленных источниках. Для подтверждения исправления нужно сверить версию ядра с stable-веткой, куда был внесён патч.
Ссылки на патчи:
- commit 02c5f9dc2efd823e061954d564ce00bacd1bebeb
- commit 062d9e008c67289e8e1b221ecdd8f9d60566d012
- commit 8e4c3b7844c906c7097b4cfedd9dd1f48c9a6a92
- commit d625112564c3e980e02504270222b49b82690cee
Исправление
Основное исправление — обновление Linux kernel до стабильной ветки, содержащей патч net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks().
- Обновить ядро через пакетный менеджер дистрибутива
- Проверить наличие модуля net/rds после обновления
- Перезагрузить систему или перезапустить сервисы, использующие RDS TCP
- Если обновление невозможно немедленно, ограничить доступ к RDS-сервисам и снизить частоту reset соединений
Патч меняет логику rds_tcp_reset_callbacks():
- Вместо простого ожидания освобождения RDS_IN_XMIT используется test_and_set_bit_lock()
- Флаг удерживается на протяжении замены сокета и вызова rds_send_path_reset()
- После завершения флаг освобождается через clear_bit_unlock()
- Ожидающие потоки будятся через wake_up_all()
Это гарантирует, что reset-поток исключает sender от параллельного изменения состояния передачи.
Ссылки на исправления:
- commit 02c5f9dc2efd823e061954d564ce00bacd1bebeb
- commit 062d9e008c67289e8e1b221ecdd8f9d60566d012
- commit 8e4c3b7844c906c7097b4cfedd9dd1f48c9a6a92
- commit d625112564c3e980e02504270222b49b82690cee
Временные меры защиты
Пока обновление ядра не выполнено, можно снизить вероятность попадания в окно гонки.
- Ограничить количество одновременных RDS TCP соединений
- Уменьшить частоту reconnect и reset операций
- Отключить или изолировать сервисы, использующие RDS, если они не критичны
- Настроить мониторинг kernel log для быстрого обнаружения аномалий
- Проверить, что модуль net/rds загружен только на системах, где он действительно нужен
Эти меры не устраняют уязвимость. Они лишь снижают вероятность одновременного выполнения reset и send потоков.
Если сервис RDS работает в production, приоритет — обновление ядра. Если это невозможно, ограничить доступ к RDS-интерфейсам и снизить нагрузку на TCP-reset пути.
Как проверить устранение уязвимости
После обновления нужно подтвердить, что патч применён.
- Проверить версию ядра:
uname -r
- Сверить версию с stable-веткой, содержащей commit 02c5f9dc2efd823e061954d564ce00bacd1bebeb или его backport
- Проверить наличие функции test_and_set_bit_lock() в rds_tcp_reset_callbacks():
grep -n 'test_and_set_bit_lock' /lib/modules/$(uname -r)/kernel/net/rds/tcp.oесли доступен исходный код или бинарник
- Проверить, что модуль net/rds загружен:
lsmod | grep rds
- Провести функциональную проверку RDS TCP после обновления
- Смотреть kernel log на отсутствие новых ошибок reset и socket lock
Команды:
Bash:
uname -r
grep -n 'test_and_set_bit_lock' /lib/modules/$(uname -r)/kernel/net/rds/tcp.o 2>/dev/null || echo "binary not available"
lsmod | grep rds
dmesg | grep -iE 'rds|tcp reset|socket lock'
Если патч не найден в ядре, нужно обновить дистрибуивный пакет kernel или применить backport от вендора.
Вывод
CVE-2026-98070 — это race condition в Linux kernel внутри модуля net/rds. Уязвимость возникает из-за того, что старый код только ждал освобождения RDS_IN_XMIT, но не блокировал повторный захват другим потоком. На слаботранзакционных архитектурах это приводит к параллельному изменению состояния передачи и замене сокета.
Исправление уже опубликовано в stable tree Linux kernel. Оно заменяет wait_event() на test_and_set_bit_lock(), удерживает флаг RDS_IN_XMIT на протяжении критической секции и освобождает его с wake-up.
Для систем с RDS TCP это обновление нельзя откладывать: гонка может повредить состояние соединения, привести к потере данных или отказу ядра. Если точные версии дистрибутивов не раскрыты, нужно проверить версию ядра и наличие патча через stable-ветку.
Официальные источники
- NVD — CVE-2026-98070
- net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks() - kernel/git/stable/linux.git - Linux kernel stable tree
- net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks() - kernel/git/stable/linux.git - Linux kernel stable tree
- net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks() - kernel/git/stable/linux.git - Linux kernel stable tree
- net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks() - kernel/git/stable/linux.git - Linux kernel stable tree
- CVEs — The Linux Kernel documentation
История обновлений статьи
- 29.09.2026 — Опубликована первая версия материала.
