Kernel Address Sanitizer(KASan)

LLVM 기반의 사용자 공간 구성요소 새니타이저와 마찬가지로 Android에는 Kernel Address Sanitizer(KASAN)가 포함되어 있습니다. KASAN은 커널 및 컴파일 시간 수정 기능을 결합하여 버그 탐색 및 근본 원인 분석을 단순화하는 계측 시스템을 제공합니다.

KASAN은 커널에서 여러 유형의 메모리 위반을 감지할 수 있습니다. 또한 스택, 힙 및 전역 변수에서의 범위를 벗어난 읽기 및 쓰기와 use-after-free 및 double free를 감지할 수 있습니다.

ASAN과 마찬가지로 KASAN은 런타임 시 메모리 액세스를 추적하기 위해 컴파일 시점의 메모리 함수 계측과 섀도 메모리의 조합을 사용합니다. KASAN에서 커널 메모리 공간의 8분의 1은 메모리 액세스가 유효한지 아닌지를 결정하는 섀도 메모리 전용입니다.

KASAN은 x86_64 및 arm64 아키텍처에서 지원됩니다. 4.0부터 업스트림 커널의 일부였으며 Android 3.18 기반 커널로 백포트되었습니다.

KASAN 외에도 kcov는 테스트에 유용한 또 다른 커널 수정 기능입니다. kcov는 커널에서 커버리지 기반 퍼징 테스트를 지원하기 위해 개발되었습니다. 이는 syscall 입력 값으로 커버리지를 측정하며 syzkaller와 같은 퍼징 시스템에서 유용합니다.

구현

KASAN 및 kcov가 사용 설정된 커널을 컴파일하려면 커널 빌드 구성에 다음 빌드 플래그를 추가합니다.

CONFIG_KASAN
CONFIG_KASAN_INLINE
CONFIG_TEST_KASAN
CONFIG_KCOV
CONFIG_SLUB
CONFIG_SLUB_DEBUG
CONFIG_CC_OPTIMIZE_FOR_SIZE

그리고 다음을 삭제합니다.

CONFIG_SLUB_DEBUG_ON
CONFIG_SLUB_DEBUG_PANIC_ON
CONFIG_KASAN_OUTLINE
CONFIG_KERNEL_LZ4

그런 다음 평소와 같이 커널을 빌드하고 플래시합니다. KASAN 커널은 원래 커널보다 훨씬 큽니다. 필요한 경우 부트 매개변수와 부트로더 설정을 수정합니다.

커널을 플래시한 후 KASAN이 사용 설정되어 실행 중인지 커널 부트 로그를 확인합니다. 커널은 다음과 같이 KASAN의 메모리 맵 정보로 시작합니다.

...
[    0.000000] c0      0 Virtual kernel memory layout:
[    0.000000] c0      0     kasan   : 0xffffff8000000000 - 0xffffff9000000000   (    64 GB)
[    0.000000] c0      0     vmalloc : 0xffffff9000010000 - 0xffffffbdbfff0000   (   182 GB)
[    0.000000] c0      0     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000] c0      0               0xffffffbdc0000000 - 0xffffffbdc3f95400   (    63 MB actual)
[    0.000000] c0      0     PCI I/O : 0xffffffbffa000000 - 0xffffffbffb000000   (    16 MB)
[    0.000000] c0      0     fixed   : 0xffffffbffbdfd000 - 0xffffffbffbdff000   (     8 KB)
[    0.000000] c0      0     modules : 0xffffffbffc000000 - 0xffffffc000000000   (    64 MB)
[    0.000000] c0      0     memory  : 0xffffffc000000000 - 0xffffffc0fe550000   (  4069 MB)
[    0.000000] c0      0       .init : 0xffffffc001d33000 - 0xffffffc001dce000   (   620 KB)
[    0.000000] c0      0       .text : 0xffffffc000080000 - 0xffffffc001d32284   ( 29385 KB)
...

그리고 버그가 다음과 같이 표시됩니다.

[   18.539668] c3      1 ==================================================================
[   18.547662] c3      1 BUG: KASAN: null-ptr-deref on address 0000000000000008
[   18.554689] c3      1 Read of size 8 by task swapper/0/1
[   18.559988] c3      1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: G        W      3.18.24-xxx #1
[   18.569275] c3      1 Hardware name: Android Device
[   18.577433] c3      1 Call trace:
[   18.580739] c3      1 [<ffffffc00008b32c>] dump_backtrace+0x0/0x2c4
[   18.586985] c3      1 [<ffffffc00008b600>] show_stack+0x10/0x1c
[   18.592889] c3      1 [<ffffffc001481194>] dump_stack+0x74/0xc8
[   18.598792] c3      1 [<ffffffc000202ee0>] kasan_report+0x11c/0x4d0
[   18.605038] c3      1 [<ffffffc00020286c>] __asan_load8+0x20/0x80
[   18.611115] c3      1 [<ffffffc000bdefe8>] android_verity_ctr+0x8cc/0x1024
[   18.617976] c3      1 [<ffffffc000bcaa2c>] dm_table_add_target+0x3dc/0x50c
[   18.624832] c3      1 [<ffffffc001bdbe60>] dm_run_setup+0x50c/0x678
[   18.631082] c3      1 [<ffffffc001bda8c0>] prepare_namespace+0x44/0x1ac
[   18.637676] c3      1 [<ffffffc001bda170>] kernel_init_freeable+0x328/0x364
[   18.644625] c3      1 [<ffffffc001478e20>] kernel_init+0x10/0xd8
[   18.650613] c3      1 ==================================================================

또한 커널에서 모듈을 사용 설정하는 경우 test_kasan 커널 모듈을 로드하여 추가로 테스트할 수 있습니다. 모듈은 범위를 벗어난 메모리 액세스 및 use-after-free를 시도하며, 대상 기기에서 KASan을 올바르게 사용 설정하는 데 유용합니다.