Limpiador de direcciones de kernel

Al igual que los desinfectantes basados en LLVM para componentes del espacio del usuario, Android incluye con Kernel Address Sanitizer (KASan). KASan es una combinación de kernel y las modificaciones en el tiempo de compilación que dan como resultado un sistema instrumentado y simplificar el descubrimiento de errores y el análisis de la causa raíz.

KASan puede detectar muchos tipos de infracciones de memoria en el kernel. También puede detectar lecturas y escrituras fuera de límite en variables de pila, montón y globales, y puede detectar usos después de liberación y doble liberación.

Similar a ASan, KASan usa una combinación de instrumentación de funciones de memoria en el tiempo de compilación y la memoria paralela para realizar un seguimiento de los accesos a la memoria durante el tiempo de ejecución. En KASan, una octava del espacio de memoria del kernel está dedicada a la memoria shadow, 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 kernel upstream desde la versión 4.0 y se adaptó a la versión basada en Android 3.18 kernels.

Además de KASan, kcov es otra modificación del kernel que sirve para y pruebas. kcov se desarrolló para permitir pruebas de fuzz guiadas por cobertura en el kernel. Mide la cobertura en términos de entradas de llamadas del sistema y es útil con fuzzing, como syzkaller.

Implementación

Para compilar un kernel con KASan y kcov habilitados, agrega las siguientes marcas de compilación a la configuración de compilación de tu kernel:

CONFIG_KASAN
CONFIG_KASAN_INLINE
CONFIG_TEST_KASAN
CONFIG_KCOV
CONFIG_SLUB
CONFIG_SLUB_DEBUG
CONFIG_CC_OPTIMIZE_FOR_SIZE

Además, quita lo siguiente:

CONFIG_SLUB_DEBUG_ON
CONFIG_SLUB_DEBUG_PANIC_ON
CONFIG_KASAN_OUTLINE
CONFIG_KERNEL_LZ4

Luego, compila y escribe tu kernel en la memoria flash como de costumbre. El kernel KASan es considerablemente más grande que el original. Si es necesario, modifica los parámetros de inicio y del bootloader para tener esto en cuenta.

Después de escribir el kernel en la memoria flash, revisa los registros de inicio del kernel para ver si KASan está habilitado. y en ejecución. El kernel comenzará con información de mapas de memoria para KASan, 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 tu kernel, puedes cargar el bloque test_kasan módulo de kernel para realizar más pruebas. El módulo intenta usar memoria fuera de los límites accesos y uso después de la liberación, y es útil para garantizar que habilitaste KASan correctamente en un dispositivo de destino.