flawopen.com/Teardowns/cve-2025-39682-linux-ktls-zero-length-record-mishandling
Linux CVE-2025-39682: kTLS 제로 길이 레코드 처리 결함
Linux kTLS 수신 대기열의 길이 0인 non-DATA TLS 레코드가 recvmsg별 레코드 유형 검사를 우회할 수 있었다. 수정은 복사된 바이트가 0이어도 처리된 레코드 유형을 확인한다. Linux CVSS 평가에는 커널 힙 정보의 사용자 공간 노출, 메모리 손상, 원격 커널 충돌 가능성이 기재되어 있다. 이는 평가된 영향이며 모든 취약 시스템에서 각각 발생한다는 뜻은 아니다.
CVSS 벡터
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H각 칸에는 한 종류의 편지만 넣을 수 있는 우편 분류대를 떠올려 보자. 빈 봉투에도 종류가 있지만, 이전 분류기는 편지 개수를 세어 칸을 바꿀지 결정했다. 편지가 0개면 봉투의 종류를 무시하고 다음 유형까지 같은 칸에 섞었다. 커널 수정은 봉투에 데이터가 없어도 종류 표식을 확인한다.
핵심 개념 및 용어
kTLS- 커널 TLS: Linux가 연결된 TCP 소켓의 TLS 레코드를 커널에서 처리할 수 있다.
recvmsg()- 애플리케이션과 kTLS 수신 경로가 사용하는 소켓 수신 시스템 호출.
TLS content type- 애플리케이션 데이터나 제어 레코드 등 레코드 유형을 분류하는 필드.
rx_list- 후속 recvmsg 호출에서 처리되는 대기 중 수신 레코드 큐.
CWE-754- 비정상 또는 예외 조건에 대한 부적절한 검사. NVD는 CWE-754를 CISA-ADP 출처로 표시하며 Linux CVE 레코드 자체는 CWE를 지정하지 않는다.
프레임워크 매핑
- 이 가이드에서 설명하는 약점의 CWE 참조: CWE-754
- CISA KEV — 추가일 2026-09-18 — CVE-2025-39682
근본 원인 분석 (Root Cause)
Linux kTLS 수신 처리는 한 번의 recvmsg() 호출에서 연속된 DATA 레코드 또는 단 하나의 non-DATA 레코드만 반환해야 한다. process_rx_list()가 처음에 길이 0인 non-DATA 레코드를 처리하면 TLS 유형을 설정하면서 err == 0을 반환할 수 있었다. tls_sw_recvmsg()는 이 0을 copied에 저장하고 중지 조건의 일부로 (copied && control != TLS_RECORD_TYPE_DATA)를 사용했다. copied가 0이므로 이미 처리된 레코드 유형 검사가 생략되고 다음 데이터 처리가 계속됐다. upstream 수정은 control을 직접 확인한다. 유형이 보고되었고 DATA가 아니면 중지하며, 0은 “아직 유형이 보고되지 않음”을 뜻한다. Linux 커널 TLS 수신 경로(kTLS)가 활성화되어 사용되는 경우에만 해당하며 모든 userspace 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가 레코드를 받는다
애플리케이션은 커널 TLS 수신이 활성화된 TCP 소켓을 사용한다.
대기열의 길이 0 non-DATA 레코드가 처리된다
rx_list 첫 레코드에 payload가 없을 때 발생한다. 처리는 유형을 보고하면서 복사 바이트 수 0을 반환할 수 있다.
이전 조건은 복사 바이트 수에 의존했다
copied가 0이면 처리된 유형이 non-DATA인지 확인하지 않았다.
수신 루프가 유형 경계를 넘는다
다음 데이터가 같은 recvmsg 호출에서 처리되어 단일 유형 규칙을 위반할 수 있다. Linux CVSS 평가에는 커널 힙 정보의 사용자 공간 노출, 메모리 손상, 원격 커널 충돌 가능성이 기재되어 있다. 이는 평가된 영향이며 모든 취약 시스템에서 각각 발생한다는 뜻은 아니다.
수정은 의미 표식을 검사한다
새 조건은 복사 바이트 수와 관계없이 control이 설정된 non-DATA 유형을 나타내면 중지한다.
소스 코드 비교: 취약한 구현 vs 보안 패치
net/tls/tls_sw.c의 일부 코드이며 전체 함수는 아니다. upstream 수정은 복사한 바이트 수 대신 보고된 콘텐츠 유형 표식을 중지 조건에서 확인한다. control == 0은 유형이 보고되지 않았다는 뜻이며, 설정된 non-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 수신을 활성화한 워크로드를 조사한다. 일반 userspace TLS가 자동으로 영향받는 것은 아니다.
- ✓수정이 포함된 공급업체 커널 패키지로 업데이트하고 보안 공지에서 정확한 빌드를 확인한다.
- ✓recvmsg 한 번은 연속 DATA 레코드 또는 단일 non-DATA 레코드만 처리하며 유형 경계를 넘지 않는다는 불변 조건을 유지한다.
- ✓업스트림 kTLS 길이 0 레코드 회귀 테스트를 실행하거나 유지하고, 다운스트림 수신 경로 구현에서도 빈 non-DATA 레코드가 같은 호출에서 다음 레코드까지 소비하지 않는지 검증한다.
- ✓“유형이 보고되지 않음”과 “복사된 바이트 0”을 구분하고
control같은 의미 상태를 검사한다. - ✓패치가 지연되면 kTLS 관련 공급업체 완화 조치를 따르고 필요한 워크로드 영향을 확인한다.