Kernel Address Sanitizer

Comme les outils de nettoyage basés sur LLVM pour les composants de l'espace utilisateur, Android inclut Kernel Address Sanitizer (KASan). KASan est une combinaison de modifications du noyau et du temps de compilation qui aboutit à un système instrumenté qui permet de détecter plus facilement les bugs et d'analyser les causes sous-jacentes.

KASan peut détecter de nombreux types d'infractions de mémoire dans le noyau. Il peut également détecter les lectures et écritures hors limites sur la pile, la mémoire tampon et les variables globales, et peut détecter les utilisations après libération et les doubles libérations.

Comme ASan, KASan utilise une combinaison d'instrumentation de fonction mémoire au moment de la compilation et de mémoire fantôme pour suivre les accès à la mémoire au moment de l'exécution. Dans KASan, un huitième de l'espace mémoire du noyau est dédié à la mémoire fantôme, qui détermine si un accès à la mémoire est valide ou non.

KASan est compatible avec les architectures x86_64 et arm64. Il fait partie du kernel en amont depuis la version 4.0 et a été rétroporté vers les kernels basés sur Android 3.18.

En plus de KASan, kcov est une autre modification du kernel utile pour les tests. kcov a été développé pour permettre les tests fuzz guidés par la couverture dans le kernel. Il mesure la couverture en termes d'entrées de syscall et est utile avec les systèmes de fuzzing, tels que syzkaller.

Implémentation

Pour compiler un noyau avec KASan et kcov activés, ajoutez les options de compilation suivantes à votre configuration de compilation du noyau:

CONFIG_KASAN
CONFIG_KASAN_INLINE
CONFIG_TEST_KASAN
CONFIG_KCOV
CONFIG_SLUB
CONFIG_SLUB_DEBUG
CONFIG_CC_OPTIMIZE_FOR_SIZE

et en supprimant les éléments suivants:

CONFIG_SLUB_DEBUG_ON
CONFIG_SLUB_DEBUG_PANIC_ON
CONFIG_KASAN_OUTLINE
CONFIG_KERNEL_LZ4

Compilez et flashez ensuite votre kernel comme d'habitude. Le noyau KASan est considérablement plus volumineux que l'original. Si nécessaire, modifiez les paramètres de démarrage et du bootloader pour tenir compte de cela.

Après avoir flashé le kernel, vérifiez les journaux de démarrage du kernel pour voir si KASan est activé et en cours d'exécution. Le noyau démarre avec des informations de mappage de mémoire pour KASan, par exemple:

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

Voici à quoi ressemble un bug:

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

De plus, si des modules sont activés dans votre noyau, vous pouvez charger le module de noyau test_kasan pour effectuer d'autres tests. Le module tente des accès de mémoire hors limites et des utilisations après libération. Il est utile pour vous assurer que vous avez correctement activé KASan sur un appareil cible.