flawopen.com/Teardowns/cve-2024-26585-linux-tls-tx-work-close-race
CVE-2024-26585: Linux TLS 종료 경쟁
Linux kTLS에서 TX 작업을 큐에 넣기 전에 sendmsg/recvmsg가 깨어날 수 있었습니다. 수정은 작업을 먼저 예약합니다.
작업자가 마지막 일을 공유 대기열에 넣기 전에 동료에게 “끝났다”고 알리는 상황을 생각해 보세요. 그사이 동료가 가게를 닫고 기존 작업을 취소할 수 있고, 작업자는 너무 늦게 새 작업을 추가합니다. 커널 수정은 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. TLS 전송 시작
프로세스가 kTLS 전송 경로를 사용하며 레코드 암호화가 비동기로 완료될 수 있습니다.
2. callback이 순서를 확인
tls_encrypt_done()은 완료된 레코드가 ctx->tx_list의 맨 앞인지 확인합니다.
3. 깨우기와 종료가 경쟁
패치 전에는 callback이 complete()로 스레드를 깨운 뒤 TX 작업을 큐에 넣을 수 있었고, 그사이에 스레드가 socket을 닫을 수 있었습니다.
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);
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓
CVE-2024-26585backport가 포함된 지원 배포판 커널로 업데이트하세요. 안정 브랜치에는 수정이 backport될 수 있으므로 공급업체 공지를 확인하세요. - ✓깨어난 스레드가 공유 객체를 닫을 수 있다면 비동기 callback에서 완료 신호보다 후속 작업을 먼저 큐에 넣으세요.
- ✓종료 시 callback 작업을 동기화해 취소하거나 비우고, 취소 지점 이후 callback이 새 작업을 넣지 못하게 하세요.
- ✓비동기 TLS 완료와 socket 종료를 경쟁시키고 작업 예약 순서를 확인하는 통제된 동시성 회귀 테스트를 추가하세요.
- ✓
MSG_ZEROCOPY나 하드웨어 암호화를 이 CVE의 전제 조건으로 간주하지 마세요. upstream 설명은 비동기 암호화 완료와 TX 작업 예약을 다룹니다.