כלי לחיטוי כתובות ליבה

בדומה לחומרי חיטוי מבוססי LLVM לרכיבי מרחב משתמשים, Android כולל מכשיר לחיטוי כתובות הליבה (KASan). KASan הוא שילוב של ליבה להדר תהליך פשוט יותר לזיהוי באגים וניתוח של שורש הבעיות.

KASan יכול לזהות סוגים רבים של הפרות זיכרון בליבה (kernel). אפשר גם אנחנו מזהים קריאה וכתיבה מחוץ לתחום (in-of-bound) על סמך משתנים גלובליים, ערימה (heap) ומשתנים גלובליים. יכול לזהות שימוש אחרי שימוש ושחרור כפול.

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

KASan נתמך בארכיטקטורות x86_64 ו-arm64. הוא היה חלק ליבה (kernel) של upstream החל מ-4.0, והועברה לאחור ל-Android 3.18 של הליבה.

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

הטמעה

כדי להדר ליבה (kernel) שמופעלת ב-KASan וב-kcov, מוסיפים את דגלי ה-build הבאים לתצורת ה-kernel של ה-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 כוללת באופן משמעותי גדול יותר מהמקור. במקרה הצורך, משנים את הפרמטרים של ההפעלה צריך להביא את זה בחשבון בהגדרות של תוכנת האתחול.

אחרי הבהוב של הליבה, בודקים את יומני אתחול הליבה (kernel) כדי לראות אם 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 ==================================================================

בנוסף, אם מודולים מופעלים בליבה (kernel), אפשר לטעון את test_kasan. של מודול הליבה לבדיקות נוספות. המודול מנסה להשתמש בזיכרון מחוץ לתחום ניגש ל-KASan ונכנס לשימוש לאחר מכן, והוא שימושי כדי לוודא שהפעלתם את KASan בצורה נכונה במכשיר יעד.