Kernel Address Sanitizer

בדומה למכשירי ה-sanitizer שמבוססים על LLVM לרכיבים במרחב המשתמש, Android כולל את Kernel Address Sanitizer‏ (KASan). KASan הוא שילוב של שינויים בליבה ובזמן הידור, שמובילים ליצירת מערכת עם כלי מדידה שמאפשרת לזהות באגים ולנתח את שורש הבעיה בצורה פשוטה יותר.

KASan יכול לזהות סוגים רבים של הפרות זיכרון בליבה. הוא יכול גם לזהות קריאות וכתוביות מחוץ למגבלות ב-stack, ב-heap ובמשתנים גלובליים, וגם לזהות שימוש לאחר שחרור (use-after-free) ושחרורים כפולים.

בדומה ל-ASAN, ‏KASan משתמש בשילוב של מכשירי מדידה של פונקציות זיכרון בזמן הידור וזיכרון צל כדי לעקוב אחרי הגישה לזיכרון בזמן הריצה. ב-KASan, שמונה חלקים ממרחב הזיכרון של הליבה מוקדשים לזיכרון צל, שמאפשר לקבוע אם גישה לזיכרון תקינה או לא.

יש תמיכה ב-KASan בארכיטקטורות x86_64 ו-arm64. הוא היה חלק מהליבה של Android מגרסה 4.0, והוא הועבר לגרסאות קודמות של ליבות מבוססי Android 3.18.

בנוסף ל-KASan, kcov הוא שינוי נוסף בליבה ששימושי לבדיקה. kcov פותח כדי לאפשר בדיקת fuzz מבוססת-כיסוי בליבה. הוא מודד את הכיסוי במונחים של קלט של syscall, והוא שימושי במערכות fuzzing, כמו syzkaller.

הטמעה

כדי לקמפל ליבה עם KASan ו-kcov מופעלים, מוסיפים את דגלי ה-build הבאים לתצורת ה-build של הליבה:

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

לאחר מכן, מפתחים את הליבה ומעבירים אותה (flash) כרגיל. הליבה של 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 בצורה נכונה במכשיר היעד.