Kernel AddressSanitizer

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

‫KASan יכול לזהות סוגים רבים של הפרות זיכרון בליבת המערכת. הוא יכול גם לזהות קריאות וכתיבות מחוץ לגבולות במשתנים של מחסנית, ערימה ומשתנים גלובליים, ויכול לזהות שימוש אחרי שחרור ופעולות שחרור כפולות.

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

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

בנוסף ל-KASan, ‏ kcov הוא שינוי נוסף בקרנל שימושי לבדיקות. הוא פותח כדי לאפשר בדיקות 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

לאחר מכן, בונים את הליבה ומעדכנים אותה כרגיל. ליבת 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 מודול הקרנל לבדיקה נוספת. המודול מנסה לגשת לזיכרון מחוץ לגבולות (out-of-bounds) ולבצע פעולות של שימוש אחרי שחרור (use-after-free), והוא שימושי כדי לוודא שהפעלתם את KASan בצורה נכונה במכשיר היעד.