Sqix

KASAN 본문

CS

KASAN

Sqix_ow 2021. 11. 18. 20:11

참고 : https://www.kernel.org/doc/html/latest/dev-tools/kasan.html


Kernal Address SANitizer의 약자로 동적 메모리 관련 버그(oob, uaf)를 찾기 위한 도구입니다.

총 3가지 모드가 있으며 다음과 같습니다.
- Generic KASAN
- Software Tag-Based KASAN
- Hardware Tag-Based KASAN

Generic KASAN

Software KASAN 모드는 Shadow Memory를 사용해서 각 메모리 바이트가 접근하기에 안전한지를 기록하고, 컴파일 시간 계측기를 사용해서 메모리에 접근하기 이전에 Shadow Memory를 검사합니다.


Generic Kasan은 커널의 메모리 중 1/8을 Shadow Memory에 할당하고, 크기와 주소에 대한 다이렉트 매핑을 사용하여 Shadow Memory에 메모리 주소를 변환하여 삽입합니다.


각 메모리 주소를 Shadow Address로 전환하는 코드는 다음과 같습니다.

static inline void *kasan_mem_to_shadow(const void *addr)
{
    return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT) + KASAN_SHADOW_OFFSET;
}

여기서 KASAN_SHADOW_SCHALE_SHIFT의 값은 3입니다.


컴파일 시간 계측기는 메모리 액세스 검사 삽입을 위해 사용됩니다. 컴파일러는 크기가 1, 2, 4, 8, 16바이트인 메모리 액세스 앞에 다음 함수 호출을 삽입합니다. 아래의 기능은 섀도우 메모리를 확인해 현재 메모리 액세스가 유효한 액세스인지를 체크합니다.

(__asan_load*(addr), __asan_store*(addr))


함수 호출 대신 인라인 계측을 진행할 경우 컴파일러는 직접 섀도우 메모리를 검사하기 위한 코드를 삽입합니다. 이 옵션은 커널을 상당히 많이 확대시키지만, 외부 호출에 의한 계측에 비해 약 1.1배에서 1.2배 가량의 성능 향상이 있습니다.


Generic KASAN은 검역을 통해 Free된 객체에 대한 재사용을 지연시키는 유일한 모드입니다.


Software tag-based KASAN


Sofware tag-based KASAN은 x86_64가 아닌 arm64 아키텍처에 구현된 KASAN으로 소프트웨어 메모리 태그 방식을 사용합니다. arm64 CPU 내의 TBI(Top-Byte-Ignore, 하드웨어가 메모리에 엑세스할 때 포인터의 최상위 바이트를 무시) 기능을 사용해 커널 포인터의 최상위 바이트에 포인터 태그를 저장합니다. 또한, 각 16바이트 셀과 연결된 메모리 태그를 저장하기 위해 섀도우 메모리를 활용합니다.


각각의 메모리를 할당할 때 Software tag-based KASAN은 랜덤 태그를 생성하고, 할당된 메모리와 반환된 포인터에 생성된 랜덤 태그를 추가합니다.


Software tag-based KASAN은 컴파일 시간 계측기를 활용해서 메모리 액세스를 하기 전 몇 가지 검사들을 진행합니다. 이 검사들은 메모리의 태그가 해당 메모리를 액세스하기 위해 사용된 포인터의 태그와 동일한지를 확인합니다. 만약 태그가 일치하지 않다면 버그 리포트를 출력합니다.


Hardware tag-based KASAN


Hardware tag-based KASAN은 현재 Arm64 아키텍처에서만 구현되어 있으며, Arm64 MTE를 기반으로 합니다. 동작 개념은 SW tag-based KASAN과 유사하지만, Shadow Memory와 컴파일러 대신 메모리 태깅을 위한 하드웨어를 사용한다는 점이 다릅니다.


각 메모리 태그를 할당하기 위해서 특수한 arm64 명령어들이 사용됩니다. 이 과정에서 포인터들에게도 동일한 태그가 할당됩니다. 모든 메모리 액세스에서, 하드웨어는 메모리와 그 메모리에 접근하기 위한 포인터의 태그가 일치한지를 검사합니다. 태그가 일치하지 않는 경우 에러 리포트가 발생합니다.


만약 하드웨어가 MTE를 지원하지 않는 경우(ARM v8.5 이전 빌드) Hardware tag-based KASAN을 사용할 수 없다고 합니다.


Kasan 사용


커널 설정에서 CONFIG_KASAN=y로 놓고, CONFIG_KASAN_GENERIC / CONFIG_KASAN_SW_TAGS / CONFIG_KASAN_HW_TAGS 중 하나의 옵션을 선택하면 됩니다.

Comments