במאמר הסבר על דוחות HWASan מוסבר איך לקרוא קריסות של HWASan.
AddressSanitizer (HWASan) הוא כלי לזיהוי שגיאות בזיכרון, בדומה ל-AddressSanitizer. ב-HWASan נעשה שימוש בפחות זיכרון RAM בהשוואה ל-ASAN, ולכן הוא מתאים לניקוי של כל המערכת. התכונה HWASan זמינה רק ב-Android מגרסה 10 ואילך, ורק בחומרה מסוג AArch64.
הכלי שימושי בעיקר לקוד C/C++, אבל הוא יכול גם לעזור בניפוי באגים בקוד Java שגורם לקריסות ב-C/C++ שמשמש להטמעת ממשקי Java. האפשרות הזו מועילה כי היא מזהה שגיאות זיכרון כשמתרחשות, ומפנה אתכם ישירות לקוד האחראי.
ניתן ליצור Flash תמונות HWASan מוכנות מראש למכשירי Pixel נתמכים מהכתובת ci.android.com (הוראות הגדרה מפורטות).
בהשוואה ל-ASan הקלאסי, ל-HWASan יש:
- תקורה דומה של המעבד (CPU) (כ-2x)
- יתרת קוד דומה (40-50%)
- תקורה קטנה בהרבה של RAM (10%-35%)
HWASan מזהה את אותה קבוצת באגים כמו ASan:
- זליגה/חוסר מקום במאגרים של סטאק ושל אשכול
- שימוש בערימה (heap) אחרי 'free'
- שימוש ב-Stack מחוץ להיקף
- חופש כפול/חינמי
בנוסף, HWASan מזהה שימוש ב-stack אחרי החזרה.
HWASan (כמו ASan) תואם ל-UBSan, ניתן להפעיל את שניהם ביעד מסוים בו-זמנית.
פרטים על ההטמעה ומגבלות
HWASan מבוסס על הגישה של תיוג זיכרון, שבה ערך תג אקראי קטן משויך גם למצביעים וגם לטווח של כתובות זיכרון. כדי שגישה לזיכרון תהיה חוקית, צריך שיהיו התאמה בין התגים של הסמן לבין תגי הזיכרון. HWASan מסתמך על התעלמות מבייט עליון של תכונת ARMv8 (TBI), שנקרא גם תיוג כתובת וירטואלית, כדי לאחסן את תג המצביע בביטים הגבוהים ביותר של הכתובת.
תוכלו לקרוא מידע נוסף על העיצוב של HWASan באתר התיעוד של Clang.
במכונה HWASan אין אזורי אדום בגודל מוגבל של ASan עבור זיהוי חריגות או הסגר בעל קיבולת מוגבלת של ASan לזיהוי שימוש לאחר תשלום בחינם. לכן, HWASan יכול לזהות באג לא משנה כמה גדולה החריגה או כמה זמן חלף מאז שהזיכרון הוקצה מחדש. ל-HWASan יש יתרון גדול על פני ASan.
עם זאת, ל-HWASan יש מספר מוגבל של ערכי תגים אפשריים (256), כלומר יש 0.4% סיכוי לפספס באג במהלך הפעלה אחת של התוכנית.
הדרישות
הגרסאות האחרונות (4.14 ואילך) של ליבת Android הנפוצה תומכות ב-HWASan מראש. להסתעפויות הספציפיות של Android 10 אין תמיכה ב-HWASan.
התמיכה במרחב המשתמש ב-HWASan זמינה החל מ-Android 11.
אם אתם עובדים עם ליבה (kernel) אחרת, HWASan דורש שהליבה של Linux תקבל את המצביעים המתויגים בארגומנטים של שיחות מערכת. התמיכה בכך הופעלה בחבילות התיקונים הבאות ב-upstream:
- arm64 tagged address ABI
- arm64: ביטול תיוג של מצביעי משתמש שמועברים לליבה
- mm: נמנעים מיצירה של כתובות וירטואליות חלופיות ב-brk()/mmap()/mremap()
- arm64: אימות כתובות מתויגות ב-access_ok() שנקראות משרשורי ליבה
אם אתם מבצעים פיתוח באמצעות ערכת כלים מותאמת אישית, חשוב לוודא שהיא כוללת את כל השינויים עד ל-commit של LLVM c336557f.
שימוש ב-HWASan
כדי ליצור את כל הפלטפורמה באמצעות HWASan, משתמשים בפקודות הבאות:
lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j
מטעמי נוחות, אפשר להוסיף את ההגדרה SANITIZE_TARGET להגדרת מוצר, בדומה ל-aosp_coral_hwasan.
משתמשים שמכירים את AddressSanitizer לא צריכים להתמודד עם הרבה מהמורכבות של ה-build:
- אין צורך להריץ פעמיים.
- פיתוחים מצטברים עובדים באופן עצמאי.
- אין צורך להריץ את נתוני המשתמש ב-Flash.
חלק מההגבלות של AddressSanitizer נעלמו גם הן:
- יש תמיכה בקובצי הפעלה סטטיים.
- מותר לוותר על חיטוי עבור כל יעד מלבד libc. בשונה מ-ASan, אין דרישה שאם ספרייה עוברת חיטוי, היא חייבת להיות גם בקובץ הפעלה שמקשר אליה.
אפשר לעבור בקלות בין קובצי אימג' של HWASan לבין קובצי אימג' רגילים עם אותו מספר build (או מספר build גבוה יותר). אין צורך למחוק את המכשיר.
כדי לדלג על החיטוי במודול, משתמשים
ב-LOCAL_NOSANITIZE := hwaddress
(Android.mk) או ב-sanitize: { hwaddress: false }
(Android.bp).
טיהור יעדים ספציפיים
אפשר להפעיל HWASan לכל יעד בגרסת build רגילה (לא נקייה), כל עוד libc.so
גם עובר ניקיון. מוסיפים את hwaddress: true
לבלוק הטיהור ב-"libc_defaults"
ב-bionic/libc/Android.bp. לאחר מכן, מבצעים את אותה פעולה ביעד שבו אתם עובדים.
חשוב לשים לב שחיטוי libc מאפשר תיוג של הקצאות זיכרון של הזיכרון בכל המערכת, וכן את הבדיקה של התגים לפעולות זיכרון בתוך libc.so
. הדבר עלול לקלוט באגים גם בקבצים בינאריים שבהם לא הופעל HWASan אם הגישה הגרועה לזיכרון היא ב-libc.so
(לדוגמה, pthread_mutex_unlock()
ב-mutex עם delete()
).
אם הפלטפורמה כולה נוצרה באמצעות HWASan, אין צורך לשנות קובצי build.
Flashstation
למטרות פיתוח, אפשר להשתמש ב-Flashstation כדי להריץ אימג' של AOSP עם תמיכה ב-HWAsan במכשיר Pixel עם מרכז האתחול (bootloader) פתוח. בוחרים את היעד _hwasan, למשל aosp_flame_hwasan-userdebug. למידע נוסף, תוכלו לעיין במסמכי התיעוד של NDK בנושא HWASan למפתחי אפליקציות.
מעקבי ערימה משופרים
HWASan משתמש בתוכנת Unwinder מהירה שמבוססת על פריים כדי לתעד דוח קריסות
לכל אירוע של הקצאת זיכרון והקצאת זיכרון בתוכנית. 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 ואילך), צריך להוסיף את ההגדרה LD_HWASAN=1
לקובץ wrap.sh.
פרטים נוספים זמינים במסמכי התיעוד למפתחי אפליקציות.