flawopen.com/Teardowns/cve-2024-26585-linux-tls-tx-work-close-race
CVE-2024-26585: гонка закрытия TLS в Linux
В kTLS Linux завершение могло разбудить sendmsg/recvmsg до постановки TX-задачи в очередь. Исправление сначала ставит задачу.
Работник говорит ожидающему коллеге «готово» до того, как добавит последнюю задачу в общую очередь. За это время коллега может закрыть мастерскую и отменить задачи; затем работник добавит задачу слишком поздно. Исправление ядра ставит передачу TLS в очередь до сигнала о завершении.
Ключевые понятия и термины
kTLS- TLS в ядре Linux, обрабатывающий TLS-записи в сетевом стеке ядра.
Асинхронное завершение криптооперации- Callback, запускаемый после окончания асинхронного шифрования TLS.
`complete()`- Примитив завершения Linux, который будит поток, ожидающий окончания операции.
Отложенная TX-задача- Задача ядра в очереди, продолжающая передачу записи TLS после шифрования.
Связи со стандартами
- Ссылка CWE для слабого места, описанного в этом руководстве: CWE-362
Анализ первопричины
В net/tls/tls_sw.c функция tls_encrypt_done() могла вызвать complete() для ожидающего потока sendmsg()/recvmsg() до планирования отложенной TX-задачи для первой записи. Разбуженный поток может вернуться и закрыть сокет, пока callback ещё собирается поставить задачу в очередь; возникает гонка между закрытием сокета и постановкой TX-задачи. Upstream-коммит e01e3934a1b2 меняет порядок: если запись находится в начале ctx->tx_list, он планирует ctx->tx_work до вызова complete(). В уведомлении CVE описана гонка; приведённые источники не подтверждают прежние утверждения о MSG_ZEROCOPY, освобождённых сетевых страницах, перезаписи памяти или исправлении через refcount_inc_not_zero().
Пошаговый сценарий атаки
1. Начинается передача TLS
Процесс использует путь передачи kTLS, где шифрование записей может завершаться асинхронно.
2. Callback проверяет порядок
tls_encrypt_done() проверяет, находится ли завершённая запись в начале ctx->tx_list.
3. Пробуждение конкурирует с закрытием
До патча callback мог разбудить поток через complete(), а TX-задачу поставить позже; между этими действиями поток мог закрыть сокет.
4. Патч упорядочивает передачу управления
Исправление сначала ставит отложенную TX-задачу в очередь, затем сигнализирует о завершении, не позволяя потоку продолжить раньше постановки.
Исходный код: Уязвимый vs Защищённый вариант
// Порядок операций в net/tls/tls_sw.c до e01e3934a1b2
bool ready = false;
if (rec == first_rec)
ready = true;
if (atomic_dec_and_test(&ctx->encrypt_pending))
complete(&ctx->async_wait.completion);
if (!ready)
return;
if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
schedule_delayed_work(&ctx->tx_work.work, 1);
// Порядок операций в net/tls/tls_sw.c после e01e3934a1b2
if (rec == first_rec) {
// Поставьте задачу передачи в очередь до пробуждения отправившего потока.
if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
schedule_delayed_work(&ctx->tx_work.work, 1);
}
if (atomic_dec_and_test(&ctx->encrypt_pending))
complete(&ctx->async_wait.completion);
Чек-лист по защите системы для инженеров
- ✓Установите поддерживаемое ядро дистрибутива с backport
CVE-2024-26585; проверьте бюллетень поставщика, так как стабильные ветки получают backport-исправления. - ✓В асинхронных callback ставьте последующую задачу в очередь до сигнала о завершении, если разбуженный поток может закрыть общий объект.
- ✓Синхронизируйте отмену или ожидание фоновых задач при закрытии, чтобы callback не мог добавить новую задачу после точки отмены.
- ✓Добавьте контролируемый тест гонки асинхронного завершения TLS с закрытием сокета и проверяйте порядок постановки задачи.
- ✓Не считайте
MSG_ZEROCOPYили аппаратное шифрование обязательными условиями: upstream-описание говорит об асинхронном завершении криптооперации и планировании TX-задачи.