- GCC 14의
-fanalyzer는 C 코드의 여러 실행 경로를 상징 실행으로 따라가며, 런타임 전에 잡기 어려운 결함을 컴파일 시점에 찾는 데 초점을 둠 - 이번 개선은 무한 루프 감지, 버퍼 오버플로 시각화, C 문자열 추적, 오염 분석 기본 활성화로 나뉘며 진단 결과를 더 이해하기 쉽게 만드는 데 집중됨
-Wanalyzer-out-of-bounds는 단순 경고를 넘어 텍스트 다이어그램으로 버퍼와 쓰기 위치의 관계를 보여주고, UTF-8 문자열에서 어느 문자 중간에 넘치는지도 표시함- 새
null_terminated_string_arg(PARAM_IDX)속성은 널 종료 문자열을 기대하는 API 조건을 분석기와 코드 독자에게 알려, 널 종료되지 않은 버퍼 전달 경로를 더 잘 드러냄 - 오염 분석은
-fanalyzer선택 시 기본으로 켜지며, 공격자 제어 값이 상한 검사 없이 크기·인덱스·오프셋 등에 쓰이는 흐름을 더 쉽게 확인할 수 있음
-fanalyzer가 다루는 문제 범위
-fanalyzer는 GCC의 정적 분석 패스로, C 소스 코드의 여러 실행 경로를 상징 실행해 컴파일 시점에 결함을 찾으려 함- GCC 14의 개선 사항은 2024년 4월 공식 릴리스를 앞두고 정리됐으며, 글 작성 시점에는 GCC 14.1 릴리스가 2024년 4월 중 기대되는 상태였음
- GCC 14.0 프리릴리스는 Fedora 40 Beta에서 이미 사용 중임
- 예제들은 Compiler Explorer에서 새 컴파일러 옵션과 함께 시험해볼 수 있음
단순 무한 루프 감지
- GCC 14에는 새 경고
-Wanalyzer-infinite-loop가 추가됨 - 예제 코드는 중첩
for문에서 두 번째 루프 조건은j < n인데 증감식은i++로 남아 있는 형태임- 첫 번째
for문을 복사한 뒤 증감식의i를j로 바꾸지 않은 실수에 해당함 - 분석기는 이 경로에서
j < n의 true 분기를 계속 따라가며 루프 반복을 경고함
- 첫 번째
- 현재 진단 출력은 이벤트 번호
(1)부터(5)까지 순서대로 읽어야 흐름을 이해하기 쉬움 - GCC 15에서는 제어 흐름 경로를 강조하는 ASCII 아트 같은 방식으로 가독성을 높이는 방안이 희망 사항으로 남아 있음
- 해당 코드는 Compiler Explorer 예제에서 실행해볼 수 있음
버퍼 오버플로를 텍스트로 시각화
- GCC 13에서 분석기는
-Wanalyzer-out-of-bounds를 통해 경계 검사를 지원하기 시작함 - GCC 14에서는 예측된 버퍼 오버플로의 공간 관계를 텍스트 기반 다이어그램으로 출력할 수 있음
char buf[10]에strcpy(buf, "hello")를 수행한 뒤strcat(buf, " world!")를 호출하는 예제에서 스택 기반 버퍼 오버플로가 감지됨- 기존 메시지는
buf용량이 10바이트이고 byte 10부터 byte 12까지 범위를 벗어난 쓰기가 발생한다고 표시함 - GCC 14의 다이어그램은
strcpy가 채운 목적지 버퍼와strcat시작점이 되는 기존 종료NUL바이트를 함께 보여줌
- 기존 메시지는
- 비ASCII 문자열 예제에서도 UTF-8 표현을 따라가며 오버플로 위치를 표시함
char buf[11]에"サツキ"를 복사한 뒤"メイ"를 이어붙이는 코드가 예시로 사용됨- 다이어그램은 오버플로가
メ문자, 즉 U+30E1의 중간에서 발생함을 보여줌
- 관련 코드는 ASCII 문자열 예제와 비ASCII 문자열 예제에서 확인할 수 있음
C 문자열 연산 추적 강화
- GCC 14 분석기는 C 문자열 연산 추적을 개선해, 널 종료 바이트를 찾으며 버퍼를 스캔하는 API를 시뮬레이션함
- 포인터가 널 종료되지 않은 버퍼를 가리키는데 해당 API에 전달되는 경로가 있으면 경고함
- 새 함수 속성
null_terminated_string_arg(PARAM_IDX)는 특정 매개변수가 널 종료 문자열이어야 한다는 조건을 분석기와 코드 독자에게 알려줌 - 예제에서는
example_fn(const char *p)에null_terminated_string_arg(1)과nonnull속성이 붙어 있음char str[3] = "abc";는 널 종료 바이트를 담을 공간이 없음example_fn(str)호출 시 분석기는str끝 이후 1바이트를 읽는 스택 기반 버퍼 과다 읽기를 경고함- 진단에는
example_fn의 1번 인자가 널 종료 문자열 포인터여야 한다는 note도 함께 출력됨
- 이 예제는 Compiler Explorer에서 실행해볼 수 있음
오염 분석 기본 활성화
- 분석기의 오염 분석은 공격자 제어 입력, 정제 지점, 정제 없이 사용되는 지점을 추적함
- 이전 GCC 릴리스에서는 버그와 많은 오탐 때문에 기본 활성화되지 않았고 별도 명령행 인자 뒤에 숨겨져 있었음
- GCC 14에서는 여러 버그 수정 이후
-fanalyzer를 선택하면 오염 분석이 기본으로 켜짐 - 이 변경으로 다음 6개 오염 기반 경고도 함께 활성화됨
CVE-2011-2210로 본 커널 분석 사례
- Linux 커널의 CVE-2011-2210 발췌 예제가 오염 분석 사례로 사용됨
__SYSCALL_DEFINEx매크로에__attribute__((tainted_args))를 추가해osf_getsysinfo인자가 신뢰 경계를 넘어온 값이며 오염된 값으로 취급되어야 함을 분석기에 알림- GCC 14 분석기는
copy_to_user(buffer, hwrpb, nbytes)에서 공격자 제어 값nbytes를 상한 검사 없이 크기로 사용한다고 경고함- 진단은
nbytes가if (nbytes < sizeof(*hwrpb))에서 하한 검사만 받았음을 표시함 copy_to_user의 세 번째 매개변수는access(write_only, 1, 3)속성으로 크기 매개변수임을 나타냄
- 진단은
- 문제는 정제 조건이
if (nbytes < sizeof(*hwrpb))로 작성된 점임- 의도된 조건은
if (nbytes > sizeof(*hwrpb))형태였음 - 조건을 수정한 버전에서는 분석기가 경고하지 않음
- 의도된 조건은
- 커널에서 분석기를 실행해 취약점을 찾고 분석기 오탐을 수정하는 작업은 계속 진행 중임