FlawOpen

flawopen.com/Teardowns/cve-2024-26585-linux-tls-tx-work-close-race

● CVE-2024-26585 · CVSS 4.7 · 보통
보안 연구 · FlawOpen

CVE-2024-26585: Linux TLS 종료 경쟁

Linux kTLS에서 TX 작업을 큐에 넣기 전에 sendmsg/recvmsg가 깨어날 수 있었습니다. 수정은 작업을 먼저 예약합니다.

💡 알기 쉬운 설명 (ELI5)

작업자가 마지막 일을 공유 대기열에 넣기 전에 동료에게 “끝났다”고 알리는 상황을 생각해 보세요. 그사이 동료가 가게를 닫고 기존 작업을 취소할 수 있고, 작업자는 너무 늦게 새 작업을 추가합니다. 커널 수정은 TLS 전송 작업을 완료 신호보다 먼저 대기열에 넣습니다.

핵심 개념 및 용어

kTLS
Linux 커널 네트워크 경로에서 TLS 레코드를 처리하는 커널 TLS 기능입니다.
비동기 암호화 완료
비동기 TLS 암호화 작업이 끝난 뒤 실행되는 callback입니다.
`complete()`
작업 완료를 기다리는 스레드를 깨우는 Linux completion primitive입니다.
지연 TX 작업
암호화 후 TLS 레코드 전송을 이어 가도록 큐에 등록되는 커널 작업입니다.

프레임워크 매핑

  • 이 가이드에서 설명하는 약점의 CWE 참조: CWE-362

근본 원인 분석 (Root Cause)

net/tls/tls_sw.c의 tls_encrypt_done()은 첫 번째 레코드의 지연 TX 작업을 예약하기 전에 대기 중인 sendmsg()/recvmsg() 스레드에 complete()를 호출할 수 있었습니다. 깨어난 스레드가 반환해 socket을 닫는 동안 callback이 아직 작업을 큐에 넣으려 할 수 있어, socket 종료와 TX 작업 예약이 경쟁합니다. upstream commit e01e3934a1b2는 순서를 바꿉니다. 레코드가 ctx->tx_list의 맨 앞이면 complete() 전에 ctx->tx_work를 예약합니다. CVE 공지는 경쟁 조건을 설명하며, 인용 출처는 기존의 MSG_ZEROCOPY, 해제된 네트워크 페이지, 메모리 덮어쓰기, refcount_inc_not_zero() 수정 주장을 뒷받침하지 않습니다.

단계별 공격 실행 흐름

단계 1

1. TLS 전송 시작

프로세스가 kTLS 전송 경로를 사용하며 레코드 암호화가 비동기로 완료될 수 있습니다.

단계 2

2. callback이 순서를 확인

tls_encrypt_done()은 완료된 레코드가 ctx->tx_list의 맨 앞인지 확인합니다.

단계 3

3. 깨우기와 종료가 경쟁

패치 전에는 callback이 complete()로 스레드를 깨운 뒤 TX 작업을 큐에 넣을 수 있었고, 그사이에 스레드가 socket을 닫을 수 있었습니다.

단계 4

4. 패치가 전달 순서를 고정

지연 TX 작업을 먼저 큐에 넣고 완료를 알리므로 스레드가 작업 예약보다 먼저 진행하지 않습니다.

소스 코드 비교: 취약한 구현 vs 보안 패치

취약한 구현
// e01e3934a1b2 이전 net/tls/tls_sw.c의 관련 순서
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);
보안 강화 패치
// e01e3934a1b2 이후 net/tls/tls_sw.c의 관련 순서
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);

엔지니어링 및 시스템 보안 강화 체크리스트

출처