Desinfectante de dirección del núcleo (KASan)

De manera similar a los desinfectantes basados ​​​​en LLVM para componentes del espacio de usuario, Android incluye Kernel Address Sanitizer (KASAN). KASAN es una combinación de modificaciones del kernel y del tiempo de compilación que dan como resultado un sistema instrumentado que permite un descubrimiento de errores y un análisis de la causa raíz más simples.

KASAN puede detectar muchos tipos de violaciones de memoria en el kernel. También puede detectar lecturas y escrituras fuera de límites en la pila, el montón y variables globales, y puede detectar uso después de la liberación y doble liberación.

Al igual que ASAN, KASAN utiliza una combinación de instrumentación de función de memoria en tiempo de compilación y memoria oculta para rastrear los accesos a la memoria en tiempo de ejecución. En KASAN, una octava parte del espacio de la memoria del kernel está dedicada a la memoria oculta, que determina si un acceso a la memoria es válido o no.

KASAN es compatible con arquitecturas x86_64 y arm64. Ha sido parte del kernel ascendente desde 4.0 y ha sido compatible con kernels basados ​​en Android 3.18.

Además de KASAN, kcov es otra modificación del kernel que resulta útil para realizar pruebas. kcov fue desarrollado para permitir pruebas fuzz guiadas por cobertura en el kernel. Mide la cobertura en términos de entradas de llamadas al sistema y es útil con sistemas de fuzzing, como syzkaller .

Implementación

Para compilar un kernel con KASAN y kcov habilitados, agregue los siguientes indicadores de compilación a la configuración de compilación de su kernel:

CONFIG_KASAN
CONFIG_KASAN_INLINE
CONFIG_TEST_KASAN
CONFIG_KCOV
CONFIG_SLUB
CONFIG_SLUB_DEBUG
CONFIG_CC_OPTIMIZE_FOR_SIZE

Y eliminando lo siguiente:

CONFIG_SLUB_DEBUG_ON
CONFIG_SLUB_DEBUG_PANIC_ON
CONFIG_KASAN_OUTLINE
CONFIG_KERNEL_LZ4

Luego compila y actualiza tu kernel como de costumbre. El núcleo KASAN es considerablemente más grande que el original. Si es necesario, modifique los parámetros de arranque y la configuración del cargador de arranque para tener esto en cuenta.

Después de actualizar el kernel, verifique los registros de arranque del kernel para ver si KASAN está habilitado y ejecutándose. El kernel se iniciará con información del mapa de memoria para KASAN, como por ejemplo:

...
[    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)
...

Y así es como se verá un error:

[   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 ==================================================================

Además, si los módulos están habilitados en su kernel, puede cargar el módulo del kernel test_kasan para realizar más pruebas. El módulo intenta accesos a la memoria fuera de los límites y uso después de la liberación y es útil para garantizar que haya habilitado KASan correctamente en un dispositivo de destino.