Sanitizer آدرس هسته

مشابه پاک‌کننده‌های مبتنی بر LLVM برای اجزای فضای کاربری، اندروید شامل Kernel AddressSanitizer (KASan) است. KASan ترکیبی از اصلاحات زمان کامپایل و هسته است که منجر به یک سیستم ابزار دقیق می‌شود که امکان کشف ساده‌تر اشکالات و تجزیه و تحلیل ریشه‌ای علت را فراهم می‌کند.

KASan می‌تواند انواع مختلفی از نقض‌های حافظه را در هسته تشخیص دهد. همچنین می‌تواند خواندن‌ها و نوشتن‌های خارج از محدوده روی متغیرهای پشته، هیپ و سراسری را تشخیص دهد و همچنین می‌تواند use-after-free و double frees را تشخیص دهد.

مشابه ASan، KASan از ترکیبی از ابزار دقیق تابع حافظه در زمان کامپایل و حافظه سایه برای ردیابی دسترسی‌های حافظه در زمان اجرا استفاده می‌کند. در KASan، یک هشتم فضای حافظه هسته به حافظه سایه اختصاص داده شده است که تعیین می‌کند آیا دسترسی به حافظه معتبر است یا خیر.

KASan روی معماری‌های x86_64 و arm64 پشتیبانی می‌شود. از نسخه ۴.۰ بخشی از هسته بالادستی بوده و به هسته‌های مبتنی بر اندروید ۳.۱۸ نیز بک‌پورت شده است.

علاوه بر KASan، kcov یکی دیگر از اصلاحات هسته است که برای آزمایش مفید است. kcov برای امکان آزمایش فازی هدایت‌شده توسط پوشش در هسته توسعه داده شد. این ابزار پوشش را بر اساس ورودی‌های syscall اندازه‌گیری می‌کند و برای سیستم‌های فازی مانند syzkaller مفید است.

پیاده‌سازی

برای کامپایل یک هسته با KASan و kcov فعال، پرچم‌های ساخت زیر را به پیکربندی ساخت هسته خود اضافه کنید:

CONFIG_KASAN
CONFIG_KASAN_INLINE
CONFIG_TEST_KASAN
CONFIG_KCOV
CONFIG_SLUB
CONFIG_SLUB_DEBUG
CONFIG_CC_OPTIMIZE_FOR_SIZE

و حذف موارد زیر:

CONFIG_SLUB_DEBUG_ON
CONFIG_SLUB_DEBUG_PANIC_ON
CONFIG_KASAN_OUTLINE
CONFIG_KERNEL_LZ4

سپس طبق معمول کرنل خود را بسازید و فلش کنید. کرنل KASan به طور قابل توجهی بزرگتر از نسخه اصلی است. در صورت نیاز، پارامترهای بوت و تنظیمات بوت لودر را تغییر دهید تا این موضوع در نظر گرفته شود.

پس از فلش کردن کرنل، لاگ‌های بوت کرنل را بررسی کنید تا ببینید آیا KASan فعال و در حال اجرا است یا خیر. کرنل با اطلاعات نگاشت حافظه برای KASan راه‌اندازی می‌شود، مانند:

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

و این شکلی است که یک باگ به نظر می‌رسد:

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

علاوه بر این، اگر ماژول‌ها در هسته شما فعال باشند، می‌توانید ماژول هسته test_kasan را برای آزمایش بیشتر بارگذاری کنید. این ماژول دسترسی‌های حافظه خارج از محدوده و استفاده پس از آزادسازی را امتحان می‌کند و برای اطمینان از فعال بودن صحیح KASan در دستگاه هدف مفید است.