במאמר הסבר על דוחות HWASan מוסבר איך לקרוס קבצים של HWASan.
AddressSanitizer (HWASan) עם תמיכה בחומרה הוא כלי לזיהוי שגיאות בזיכרון, בדומה ל-AddressSanitizer. HWASan משתמש בהרבה פחות זיכרון RAM בהשוואה ל-ASan, ולכן הוא מתאים לניקוי של המערכת כולה. HWASan זמין רק ב-Android מגרסה 10 ואילך, ורק בחומרה של AArch64.
הכלי HWASan שימושי בעיקר לקוד C/C++, אבל הוא יכול לעזור גם בניפוי באגים בקוד Java שגורם לקריסות ב-C/C++ שמשמש להטמעה של ממשקי Java. הוא שימושי כי הוא מאתר שגיאות בזיכרון כשהן מתרחשות, ומפנה אתכם ישירות לקוד שאחראי לשגיאה.
בהשוואה ל-ASan הקלאסי, ל-HWASan יש:
- תקורה דומה של CPU (~2x)
- תקורה דומה של גודל הקוד (40-50%)
- תקורה נמוכה בהרבה של RAM (10% עד 35%)
HWASan מזהה את אותה קבוצת באגים כמו ASan:
- גלישה או חוסר גלישה של מאגרים בערימה ובמחסנית
- שימוש בערימה אחרי שחרור
- שימוש ב-Stack מחוץ להיקף
- Double free/wild free
בנוסף, HWASan מזהה שימוש במחסנית אחרי החזרה.
HWASan (זהה ל-ASan) תואם ל-UBSan, ואפשר להפעיל את שניהם ביעד בו-זמנית.
פרטי ההטמעה והמגבלות
HWASan מבוסס על הגישה של תיוג זיכרון, שבה ערך תג אקראי קטן משויך גם למצביעים וגם לטווחים של כתובות זיכרון. כדי שגישה לזיכרון תהיה תקפה, התגים של המצביע והזיכרון צריכים להיות זהים. HWASan מסתמך על התכונה top byte ignore (TBI) של ARMv8, שנקראת גם virtual address tagging, כדי לאחסן את תג המצביע בביטים הגבוהים ביותר של הכתובת.
מידע נוסף על העיצוב של HWASan זמין באתר התיעוד של Clang.
ב-HWASan אין אזורים אדומים בגודל מוגבל כמו ב-ASan, שנועדו לזיהוי של הצפות, או הסגר בקיבולת מוגבלת כמו ב-ASan, שנועד לזיהוי של שימוש אחרי שחרור. לכן, HWASan יכול לזהות באג לא משנה כמה גדול הגלישה או כמה זמן עבר מאז שהזיכרון בוטל. זה נותן ל-HWASan יתרון גדול על פני ASan.
עם זאת, ל-HWASan יש מספר מוגבל של ערכי תגים אפשריים (256), מה שאומר שיש הסתברות של 0.4% לפספס באג כלשהו במהלך הרצה אחת של התוכנית.
דרישות
גרסאות עדכניות (4.14 ואילך) של הליבה הנפוצה של Android תומכות ב-HWASan מחוץ לקופסה. לסניפים ספציפיים של Android 10 אין תמיכה ב-HWASan.
התמיכה ב-HWASan במרחב המשתמש זמינה החל מ-Android 11.
אם אתם עובדים עם ליבה אחרת, כדי להשתמש ב-HWASan צריך שהליבה של Linux תקבל מצביעים מתויגים בארגומנטים של קריאות מערכת. התמיכה הזו הוטמעה בערכות התיקונים הבאות של upstream:
- arm64 tagged address ABI
- arm64: untag user pointers passed to the kernel
- mm: Avoid creating virtual address aliases in brk()/mmap()/mremap()
- arm64: אימות כתובות מתויגות ב-access_ok() שנקרא משרשורים של ליבת המערכת
אם אתם משתמשים בשרשרת כלים מותאמת אישית, ודאו שהיא כוללת את כל מה שנדרש עד ל-commit של LLVM c336557f.
שימוש ב-HWASan
כדי ליצור את כל הפלטפורמה באמצעות HWASan, משתמשים בפקודות הבאות:
lunch aosp_walleye-userdebug # (or any other product)export SANITIZE_TARGET=hwaddressm -j
כדי להקל על התהליך, אפשר להוסיף את ההגדרה SANITIZE_TARGET להגדרת מוצר, בדומה ל-aosp_coral_hwasan.
למשתמשים שמכירים את AddressSanitizer, הרבה מהמורכבות של הבנייה נעלמת:
- אין צורך להריץ את הפקודה make פעמיים.
- גרסאות build מצטברות פועלות באופן אוטומטי.
- אין צורך להפעיל פלאש בנתוני המשתמש.
גם חלק מההגבלות של AddressSanitizer כבר לא קיימות:
- יש תמיכה בקבצים הפעלה סטטיים.
- אפשר לדלג על ניקוי של כל יעד מלבד libc. בניגוד ל-ASan, אין דרישה שאם ספרייה עוברת סניטציה, גם כל קובץ הפעלה שמקשר אליה יעבור סניטציה.
אפשר לעבור בין HWASan לבין תמונות רגילות באותו מספר Build (או במספר Build גבוה יותר) באופן חופשי. אין צורך למחוק את המכשיר.
כדי לדלג על ניקוי של מודול, משתמשים ב-LOCAL_NOSANITIZE := hwaddress (Android.mk) או ב-sanitize: { hwaddress: false } (Android.bp).
ניקוי של יעדים בודדים
אפשר להפעיל את HWASan לכל יעד בנפרד בגרסה רגילה (לא מחוטאת), כל עוד גם libc.so מחוטא. מוסיפים את hwaddress: true לבלוק sanitize ב-"libc_defaults"
ב-bionic/libc/Android.bp. אחר כך חוזרים על הפעולה ביעד שעליו אתם עובדים.
הערה: ניקוי של libc מאפשר תיוג של הקצאות זיכרון בערימה בכל המערכת, וגם בדיקה של התגים לפעולות זיכרון בתוך libc.so. יכול להיות שהכלי יזהה באגים גם בקבצים בינאריים שלא הופעל בהם HWASan, אם הגישה הבעייתית לזיכרון היא ב-libc.so (לדוגמה, pthread_mutex_unlock() ב-delete()ed mutex).
אין צורך לשנות קובצי build אם הפלטפורמה כולה בנויה באמצעות HWASan.
מעקבי ערימה משופרים
HWASan משתמש בכלי מהיר לביטול ההרשמה שמבוסס על מצביע מסגרת כדי לתעד את מעקב המחסנית לכל אירוע של הקצאת זיכרון וביטול הקצאת זיכרון בתוכנית. ב-Android, מצביעים על מסגרות מופעלים בקוד AArch64 כברירת מחדל, ולכן זה עובד מצוין בפועל. אם אתם צריכים לבטל את הפעולה באמצעות קוד מנוהל, צריך להגדיר את HWASAN_OPTIONS=fast_unwind_on_malloc=0 בסביבת התהליך. הערה: מעקב אחר גישה שגויה לזיכרון
משתמש ב-unwinder 'איטי' כברירת מחדל. ההגדרה הזו משפיעה רק על
מעקב אחר הקצאה וביטול הקצאה. האפשרות הזו יכולה להיות מאוד
אינטנסיבית מבחינת השימוש במעבד, בהתאם לעומס.
סימבוליזציה
מידע נוסף זמין במאמר בנושא הסמלים בקטע 'הסבר על דוחות HWASan'.
HWASan באפליקציות
בדומה ל-AddressSanitizer, HWASan לא יכול לראות את קוד Java, אבל הוא יכול לזהות באגים בספריות JNI. עד Android 14, הפעלת אפליקציות של HWASan במכשיר שאינו HWASan לא נתמכה.
במכשיר עם HWASan, אפשר לבדוק אפליקציות באמצעות HWASan על ידי בניית הקוד שלהן עם SANITIZE_TARGET:=hwaddress ב-Make או עם -fsanitize=hwaddress בדגלי קומפיילר.
במכשיר שאין בו HWASan (עם Android מגרסה 14 ואילך), צריך להוסיף הגדרה לקובץ wrap.sh
LD_HWASAN=1.
פרטים נוספים מופיעים במסמכי התיעוד למפתחים.