정수 오버플로 제거

의도하지 않은 정수 오버플로는 메모리 액세스 또는 메모리 할당과 관련된 변수에서 메모리 손상 또는 정보 공개 취약성 문제를 일으킬 수 있습니다. 이 문제를 해결하기 위해 Clang의 UndefinedBehaviorSanitizer(UBSan) 부호 있는 정수 및 부호 없는 정수 오버플로 새니타이저를 추가해 Android 7.0에서 미디어 프레임워크를 강화했습니다. Android 9에서는 더 많은 구성요소를 포함하도록 UBSan을 확장하고 UBSan에 대한 빌드 시스템 지원을 개선했습니다.

오버플로가 발생한 경우 프로세스를 안전하게 취소하기 위해 오버플로가 발생할 수 있는 산술 연산/명령에 대한 검사를 추가하도록 설계되었습니다. 이러한 새니타이저는 메모리 손상 및 정보 공개 취약점의 전체 클래스를 완화할 수 있는데, 이러한 취약점의 근본 원인은 원래 Stagefright 취약점과 같은 정수 오버플로입니다.

예시 및 소스

정수 오버플로 제거(IntSan)는 컴파일러에서 제공하며 연산 오버플로를 감지하기 위해 컴파일하는 동안 바이너리에 계측을 추가합니다. 또한 플랫폼 전체의 다양한 구성요소에서 기본적으로 사용 설정되어 있습니다(예: /platform/external/libnl/Android.bp).

구현

IntSan은 UBSan의 부호 있는 정수 및 부호 없는 정수 오버플로 새니타이저를 사용합니다. 이 완화는 모듈별 수준에서 사용 설정됩니다. Android의 중요한 구성요소를 안전하게 유지하는 데 도움이 되므로 사용 중지하면 안 됩니다.

추가 구성요소에 대해 정수 오버플로 제거를 사용 설정하는 것이 좋습니다. 이상적인 방식은 권한 있는 네이티브 코드나 신뢰하지 않는 사용자 입력을 파싱하는 네이티브 코드입니다. 새니타이저와 관련된 사소한 성능 오버헤드가 있는데, 코드의 사용량과 산술 연산의 배포에 따라 달라집니다. 약간의 오버헤드 비율을 예상하고 성능이 문제가 되는지 테스트합니다.

Makefile에서 IntSan 지원

Makefile에서 IntSan을 사용하려면 다음을 추가합니다.

LOCAL_SANITIZE := integer_overflow
# Optional features
LOCAL_SANITIZE_DIAG := integer_overflow
LOCAL_SANITIZE_BLACKLIST := modulename_blacklist.txt
  • LOCAL_SANITIZE는 쉼표로 구분된 새니타이저 목록을 가져옵니다. 개별의 부호 있는 정수 및 부호 없는 정수 오버플로 새니타이저에 대해 기본 블랙리스트를 사용하여 미리 패키징된 옵션 집합이 되는 integer_overflow를 사용합니다.
  • LOCAL_SANITIZE_DIAG는 새니타이저에 진단 모드를 켭니다. 진단 모드는 오버플로에 대해 취소되지 않으며 완화의 보안 이점을 완전히 무효화하므로 테스트 중에만 사용합니다. 자세한 내용은 문제 해결을 참조하세요.
  • LOCAL_SANITIZE_BLACKLIST를 사용하면 블랙리스트 파일을 지정하여 함수와 소스 파일이 제거되지 않도록 방지할 수 있습니다. 자세한 내용은 문제 해결을 참조하세요.

더 세부적으로 제어하려면 다음 플래그 중 하나 또는 둘 다를 사용하여 새니타이저를 개별적으로 사용 설정합니다.

LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow
LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow

청사진 파일에서 IntSan 지원

청사진 파일(예: /platform/external/libnl/Android.bp)에서 정수 오버플로 제거를 사용 설정하려면 다음을 추가합니다.

   sanitize: {
      integer_overflow: true,
      diag: {
          integer_overflow: true,
      },
      blacklist: "modulename_blacklist.txt",
   },

Makefile과 마찬가지로 integer_overflow 속성은 개별의 부호 있는 정수 및 부호 없는 정수 오버플로 새니타이저에 대해 기본 블랙리스트를 사용해 미리 패키징된 옵션 집합입니다.

속성의 diag 집합은 새니타이저에 진단 모드를 사용 설정합니다. 테스트 중에만 진단 모드를 사용합니다. 진단 모드는 오버플로에 대해 취소되지 않으며, 사용자 빌드에서 완화의 보안 이점을 완전히 무효화합니다. 자세한 내용은 문제 해결을 참조하세요.

blacklist 속성은 개발자가 함수 및 소스 파일이 제거되지 않게 방지하도록 허용하는 블랙리스트 파일의 사양을 허용합니다. 자세한 내용은 문제 해결을 참조하세요.

새니타이저를 개별적으로 사용 설정하려면 다음을 사용합니다.

   sanitize: {
      misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
      diag: {
          misc_undefined: ["signed-integer-overflow",
                           "unsigned-integer-overflow",],
      },
      blacklist: "modulename_blacklist.txt",
   },

문제 해결

새 구성요소에서 정수 오버플로 제거를 사용 설정하거나 정수 오버플로 제거가 있는 플랫폼 라이브러리를 사용하는 경우, 취소를 일으키는 무해한 정수 오버플로와 관련된 몇 가지 문제가 발생할 수 있습니다. 무해한 오버플로가 드러날 수 있도록 제거가 사용 설정된 상태에서 구성요소를 테스트해야 합니다.

사용자 빌드에서 제거로 인해 발생한 취소를 찾으려면 UBSan에서 감지한 오버플로를 나타내는 다음과 같은 취소 메시지를 사용해 SIGABRT 충돌을 검색합니다.

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/surfaceflinger <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'ubsan: sub-overflow'

스택 트레이스에는 취소를 일으킨 함수가 포함되어야 하지만 인라인 함수에서 발생하는 오버플로는 스택 트레이스에서 명확하게 표시되지 않을 수 있습니다.

근본 원인을 더 쉽게 확인하려면 라이브러리에서 진단을 사용 설정하여 취소를 트리거하고 오류를 재현해 봅니다. 진단을 사용 설정하면 프로세스가 중단되지 않고 대신 계속 실행됩니다. 취소하지 않으면 각 버그를 수정한 후 다시 컴파일할 필요 없이 특정 실행 경로에서 무해한 오버플로의 수를 최대화하는데 도움이 됩니다. 진단은 취소를 일으킨 행 번호와 소스 파일이 포함된 다음과 같은 오류 메시지를 생성합니다.

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

문제가 있는 산술 연산이 발견되면 오버플로가 무해하고 의도된 것인지 확인합니다(예: 보안에 영향을 미치지 않음). 새니타이저 취소는 다음과 같이 처리할 수 있습니다.

  • 코드를 리팩터링하여 오버플로 방지()
  • Clang의 __builtin_*_overflow 함수를 통해 명시적으로 오버플로()
  • no_sanitize 속성을 지정하여 함수에서 제거 사용 중지()
  • 블랙리스트 파일을 통해 함수 또는 소스 파일의 제거 사용 중지()

가능한 한 가장 세분화된 솔루션을 사용해야 합니다. 예를 들어 다수의 산술 연산과 오버플로 연산 하나가 있는 큰 함수에는 차단된 전체 함수가 아니라 리팩터링된 단일 연산이 있어야 합니다.

무해한 오버플로가 발생할 수 있는 일반적인 패턴은 다음과 같습니다.

  • 부호 있는 형식으로 변환되기 전에 부호 없는 오버플로가 발생하는 암시적 변환()
  • 삭제 시 루프 색인을 줄이는 연결된 목록 삭제()
  • 실제 최댓값을 지정하는 대신 부호 없는 유형을 -1로 할당()
  • 조건에서 부호 없는 정수를 줄이는 루프(, )

개발자는 제거를 사용 중지하기 전에 새니타이저가 의도하지 않은 부작용이나 보안에 미치는 영향 없이 실제로 무해한 오버플로를 감지하는지 확인하는 것이 좋습니다.

IntSan 사용 중지

블랙리스트 또는 함수 속성을 사용해 IntSan을 사용 중지할 수 있습니다. 코드 리팩터링이 적절하지 않거나 성능 오버헤드가 문제가 되는 경우에만 드물게 사용 중지합니다.

함수 속성블랙리스트 파일 형식으로 IntSan을 사용 중지하는 방법에 대한 자세한 내용은 Clang 업스트림 문서를 참조하세요. 다른 새니타이저에 영향을 미치지 않으려면 섹션 이름을 사용해 타겟 새니타이저를 지정하여 특정 새니타이저로 블랙리스트의 범위를 지정해야 합니다.

유효성 검사

현재 정수 오버플로 제거에 대한 CTS 테스트는 없습니다. 대신 IntSan 사용 설정 여부와 상관없이 CTS 테스트가 통과되도록 하여 IntSan이 기기에 영향을 미치지 않는지 확인하세요.