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.