Desinfectante de direcciones del kernel (KASan)

Al igual que los desinfectantes basados ​​en LLVM para los componentes del espacio de usuario, Android incluye el desinfectante de direcciones del kernel (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 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 las variables globales, y puede detectar el uso después de la liberación y las liberaciones dobles.

Similar a ASAN, KASAN usa una combinación de instrumentación de funciones 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 se dedica a la memoria oculta, que determina si un acceso a la memoria es válido o no.

KASAN es compatible con las arquitecturas x86_64 y arm64. Ha sido parte del núcleo ascendente desde 4.0 y se ha adaptado a los núcleos basados ​​en Android 3.18.

Además de KASAN, kcov es otra modificación del núcleo que es útil para realizar pruebas. kcov fue desarrollado para permitir pruebas de fuzz guiadas por cobertura en el kernel. Mide la cobertura en términos de entradas de llamada al sistema y es útil con sistemas 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 construya y actualice su 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 gestor 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 núcleo se iniciará con información del mapa de memoria para KASAN, como:

...
[    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 de kernel test_kasan para realizar más pruebas. El módulo intenta acceder a la memoria fuera de los límites y usar después de liberar y es útil para garantizar que ha habilitado KASan correctamente en un dispositivo de destino.