כלי לחיטוי של HWAddress

‫Android NDK תומך ב-HWAddress Sanitizer, שנקרא גם HWASan, החל מ-NDK r21 ומ-Android 10 (רמת API‏ 29). ‫HWASan זמין רק במכשירי Arm‏ 64 ביט.

‫HWASan הוא כלי לזיהוי שגיאות זיכרון שדומה ל-ASan. בהשוואה ל-ASan הקלאסי, ל-HWASan יש:

  • תקורה דומה של CPU ‏ (~2x)
  • תקורה דומה של גודל הקוד (40-50%)
  • תקורה קטנה בהרבה של זיכרון RAM ‏ (10% עד 35%)

‫HWASan מזהה את אותה קבוצת באגים כמו ASan:

  • גלישה או חריגה ממאגרים (buffer) בזיכרון המחסנית (stack) ובזיכרון הערימה (heap)
  • שימוש בערימה אחרי שחרור
  • שימוש במערך מחוץ להיקף
  • חינם או חופשי

בנוסף, HWASan מזהה גם:

  • שימוש במקבץ לאחר החזרה

אפליקציה לדוגמה

אפליקציה לדוגמה מראה איך להגדיר וריאנט build ל-hwasan.

פיתוח פתרונות

כדי ליצור את הקוד המקורי (JNI) של האפליקציה באמצעות HWAddress Sanitizer, מבצעים את הפעולות הבאות:

ndk-build

בקובץ Application.mk:

APP_STL := c++_shared # Or system, or none, but not c++_static.
APP_CFLAGS := -fsanitize=hwaddress -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=hwaddress

CMake (Gradle Groovy)‎

בקובץ build.gradle של המודול:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL, but not c++_static.
                arguments "-DANDROID_STL=c++_shared"
            }
        }
    }
}

לכל יעד בקובץ CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

ב-NDK 27 ומעלה, אפשר גם להשתמש באפשרויות הבאות ב-build.gradle ולא צריך לשנות את CMakeLists.txt:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                arguments "-DANDROID_SANITIZE=hwaddress"
            }
        }
    }
}

האפשרות הזו לא תפעל כשמשתמשים ב-ANDROID_USE_LEGACY_TOOLCHAIN_FILE=false.

‫CMake (Gradle Kotlin)

בקובץ build.gradle של המודול:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL, but not c++_static.
                arguments += "-DANDROID_STL=c++_shared"
            }
        }
    }
}

לכל יעד בקובץ CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

ב-NDK 27 ומעלה, אפשר גם להשתמש באפשרויות הבאות ב-build.gradle ולא צריך לשנות את CMakeLists.txt:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                arguments += "-DANDROID_SANITIZE=hwaddress"
            }
        }
    }
}

האפשרות הזו לא תפעל כשמשתמשים ב-ANDROID_USE_LEGACY_TOOLCHAIN_FILE=false.

‫Android מגרסה 14 ואילך: מוסיפים את wrap.sh

אם אתם מריצים Android מגרסה 14 ואילך, אתם יכולים להשתמש בסקריפט wrap.sh כדי להריץ את האפליקציה שניתן לבצע ניפוי באגים בכל מכשיר עם Android. אם בחרתם לפעול לפי השלבים שמפורטים בהוראות ההגדרה, אתם יכולים לדלג על השלב הזה.

פועלים לפי ההוראות לאריזת סקריפט wrap.sh כדי להוסיף את סקריפט wrap.sh הבא ל-arm64-v8a.

#!/system/bin/sh
LD_HWASAN=1 exec "$@"

ריצה

אם אתם מריצים גרסת Android ישנה יותר מ-14, או שלא הוספתם סקריפט wrap.sh, עליכם לפעול לפי הוראות ההגדרה לפני הפעלת האפליקציה.

מפעילים את האפליקציה כרגיל. כשמתגלה שגיאת זיכרון, האפליקציה קורסת עם SIGABRT ומדפיסה הודעה מפורטת ב-logcat. עותק של ההודעה נמצא בקובץ בתיקייה /data/tombstones והוא נראה כך:

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

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

מידע נוסף על הודעות השגיאה של HWASan מופיע במאמר הסבר על דוחות HWASan.

יצירת קובצי הפעלה משורת הפקודה

אתם יכולים ליצור ולהפעיל קובצי הפעלה שמוגדרים עם HWASan ב-Android 14 ובגרסאות חדשות יותר. אתם יכולים להשתמש באותה הגדרה שמתוארת במאמר בנושא בנייה עבור ndk-build או CMake לקובצי ההפעלה שלכם. דוחפים את קובצי ההפעלה למכשיר עם Android 14 או גרסה חדשה יותר ומפעילים אותם כרגיל באמצעות המעטפת.

אם אתם משתמשים ב-libc++, חשוב לוודא שאתם משתמשים ב-STL המשותף, להעביר אותו למכשיר ולהגדיר את LD_LIBRARY_PATH לספרייה שמכילה אותו כשמריצים את הקובץ הבינארי.

אם אתם לא משתמשים ב-Gradle, תוכלו לעיין במסמכי התיעוד של NDK כדי ללמוד איך לבצע build משורת הפקודה באמצעות CMake ו-ndk-build.

‫Android מגרסה 13 ואילך: הגדרה

אם במכשיר שלכם מותקנת Android מגרסה 14 ואילך, אתם יכולים לדלג על השלב הזה ולפעול לפי ההוראות לשימוש ב-wrap.sh בקטע Build. אפשר גם לפעול לפי ההוראות שבקטע הזה ולדלג על ההוראות לשימוש ב-wrap.sh.

לפני Android 14, כדי להפעיל אפליקציות של HWASan צריך ליצור גרסת build של Android עם HWASan. אפשר לצרוב קובצי אימג' של HWASan שנבנו מראש במכשירי Pixel נתמכים. הגרסאות זמינות בכתובת ci.android.com. שם אפשר ללחוץ על הריבוע של הגרסה המדויקת שרוצים לקבל קישור Flash Build. כדי לעשות את זה, צריך לדעת את שם הקוד של הטלפון.

צריבת ROM של גרסת build במכשיר

יכול להיות שיהיה קל יותר להיכנס ישירות לכתובת flash.android.com כי שם תהליך ההפעלה מתחיל בזיהוי המכשיר ומציג רק את הגרסאות שאפשר להשתמש בהן. בתמונות הבאות מוצג תהליך ההגדרה בכלי הזה.

מפעילים את מצב הפיתוח במכשיר ומחברים אותו למחשב באמצעות כבל USB. לוחצים על הוספת מכשיר חדש, בוחרים את המכשיר בתיבת הדו-שיח ולוחצים על חיבור.

זיהוי מכשיר לצריבת ROM‏ (flash) בוחרים את המכשיר שאליו רוצים להתחבר.

אחרי שהמכשיר מחובר, לוחצים עליו כדי להגדיר את הגרסה. בתיבה Select a build ID (בחירת מזהה build), בוחרים את הענף aosp-master-with-phones-throttled כדי שהמערכת תבחר באופן אוטומטי את התמונה הנכונה למכשיר שמחובר.

בחירת המכשיר לצריבה מאשרים את אפשרויות ההפעלה של הפלאש ומפעילים את הפלאש במכשיר

לוחצים על התקנה כדי לצרוב את המכשיר.

במסמכים בנושא Android Flash Tool יש פרטים נוספים על ההגדרה הנדרשת. אפשרות אחרת היא לעיין בתיעוד של AOSP לקבלת הוראות ליצירת תמונת HWASan ממקור.