flawopen.com/Teardowns/cve-2025-39682-linux-ktls-zero-length-record-mishandling
Linux CVE-2025-39682: обработка пустой TLS-записи в kTLS
TLS-запись не-DATA нулевой длины в очереди приёма kTLS Linux могла обходить проверку типа на вызов recvmsg. Исправление проверяет тип обработанной записи, даже если не скопировано ни одного байта. В оценке CVSS Linux указаны возможная утечка данных из кучи ядра в пользовательское пространство, повреждение памяти и удалённые сбои ядра; это оценённые последствия, а не утверждение, что каждое затронутое устройство испытает все эффекты.
Вектор CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HПредставьте почтовую сортировку, где в каждую ячейку разрешено класть письма только одной категории. У пустого конверта тоже есть категория, но старая сортировка выбирала смену ячейки по числу писем. При нуле писем она игнорировала категорию и смешивала следующий тип. Исправление ядра проверяет сам маркер категории, даже если в конверте нет данных.
Ключевые понятия и термины
kTLS- TLS в ядре: Linux может обрабатывать TLS-записи в ядре для подключённого TCP-сокета.
recvmsg()- Системный вызов приёма сокета, используемый приложением и путём приёма kTLS.
Тип содержимого TLS- Поле, классифицирующее запись как данные приложения или управляющую запись.
rx_list- Очередь ожидающих записей приёма, обрабатываемых последующими вызовами recvmsg.
CWE-754- Недостаточная проверка необычных или исключительных условий. NVD указывает
CWE-754со ссылкой на CISA-ADP; в самой записи CVE Linux CWE не назначен.
Связи со стандартами
- Ссылка CWE для слабого места, описанного в этом руководстве: CWE-754
- CISA KEV — добавлено 2026-09-18 — CVE-2025-39682
Анализ первопричины
Приём Linux kTLS должен возвращать за один вызов recvmsg() либо непрерывные записи DATA, либо одну запись не-DATA. Если process_rx_list() обрабатывал начальную запись не-DATA нулевой длины, он мог установить тип TLS и вернуть err == 0. tls_sw_recvmsg() присваивал ноль переменной copied и использовал (copied && control != TLS_RECORD_TYPE_DATA) в условии остановки. Поскольку copied равнялся нулю, уже обработанный тип игнорировался и обработка продолжалась для следующих данных. Исправление upstream проверяет control напрямую: если тип задан и это не DATA, обработка прекращается; ноль остаётся маркером «тип ещё не сообщён». Уязвимость относится к системам, где включён и используется приём TLS ядром Linux (kTLS); это не ошибка всех пользовательских TLS-библиотек. Опубликованный Linux вектор CVSS 3.1 — 9,8 Critical (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H). Оценивайте риск с учётом реального использования kTLS и версии ядра поставщика.
Пошаговый сценарий атаки
kTLS получает записи
Приложение использует TCP-сокет с включённым приёмом TLS в ядре.
Обрабатывается пустая ожидающая запись не-DATA
Случай возникает, если первая запись из rx_list не содержит полезных данных. Обработка может сообщить тип и вернуть ноль скопированных байтов.
Старое условие зависит от числа скопированных байтов
При copied == 0 старое условие не проверяет, что обработанная запись была не-DATA.
Цикл пересекает границу типов
Следующие данные могут обрабатываться в том же вызове recvmsg, нарушая правило одного типа. В оценке CVSS Linux указаны возможная утечка данных из кучи ядра в пользовательское пространство, повреждение памяти и удалённые сбои ядра; это оценённые последствия, а не утверждение, что каждое затронутое устройство испытает все эффекты.
Исправление проверяет семантический маркер
Новая проверка останавливается, если control содержит заданный тип не-DATA, независимо от числа байтов.
Исходный код: Уязвимый vs Защищённый вариант
Фрагмент net/tls/tls_sw.c, не полная функция. Исправление upstream использует для условия остановки маркер сообщённого типа, а не количество скопированных байтов. control == 0 означает, что тип не сообщался; заданный тип не-DATA останавливает этот вызов recvmsg. Это точное логическое изменение upstream-патча.
Фрагмент исходного кода: Исходный код: net/tls/tls_sw.c
copied = err;
if (len <= copied ||
(copied && control != TLS_RECORD_TYPE_DATA) || rx_more)
goto end;
copied = err;
if (len <= copied || rx_more ||
(control && control != TLS_RECORD_TYPE_DATA))
goto end;
Чек-лист по защите системы для инженеров
- ✓Определите нагрузки, использующие приём Linux kTLS; обычный пользовательский TLS не означает автоматическую уязвимость.
- ✓Установите пакет ядра поставщика с исправлением и сверьте точную сборку с бюллетенем.
- ✓Соблюдайте инвариант: один вызов recvmsg обрабатывает непрерывные записи DATA или одну не-DATA, не переходя между типами.
- ✓Запускайте или сохраняйте upstream-тест kTLS для записей нулевой длины; downstream-реализации пути приёма также должны проверять, что пустая запись не-DATA не приводит к обработке следующей записи в том же вызове.
- ✓Разделяйте состояния «тип не обнаружен» и «скопировано ноль байтов»; проверяйте семантический маркер
control. - ✓При задержке обновления выполните рекомендацию поставщика по kTLS и проверьте влияние на необходимые нагрузки.