AddressSanitizer

AddressSanitizer (ASan) הוא כלי מבוסס מהדר מהיר לאיתור באגי זיכרון בקוד מקורי.

אסאן מזהה:

  • הצפה וערימה של מאגר הצפה/תת זרימה
  • שימוש בערמה לאחר חינם
  • שימוש בערימה מחוץ להיקף
  • חינם כפול/חינם

ASan פועל הן על 32 סיביות והן על 64 סיביות ARM, בתוספת x86 ו- x86-64. תקורות המעבד של ASan הן בערך פי 2, תקורה בגודל קוד היא בין 50% ל -2, ותקרת זיכרון גדולה (תלוי בדפוסי ההקצאה שלך, אך בסדר גודל של 2x).

אנדרואיד 10 ואת הסניף מאסטר AOSP על תמיכה AArch64 בחומרה מואצת אסאן (HWASan) , כלי דומה עם תקורה RAM נמוך ומגוון גדול של באגים שהתגלו. HWASan מזהה שימוש במחסנית לאחר החזרה, בנוסף לבאגים שזוהו על ידי ASan.

ל- HWASan תקורה דומה של מעבד וגודל קוד, אך תקורה של זיכרון RAM קטן בהרבה (15%). HWASan היא לא קבועה. ישנם רק 256 ערכי תג אפשריים, כך שיש סיכוי של 0.4% להחמיץ כל באג. ל- HWASan אין אזורים אדומים בגודל מוגבל של ASan לאיתור הצפות והסגר בעל יכולת מוגבלת לאיתור שימוש אחרי חינם, כך שזה לא משנה ל- HWASan כמה גדול הצפה או כמה זמן הזיכרון הועבר. זה הופך את HWASan לטוב יותר מ- ASan. אתה יכול לקרוא עוד על העיצוב של HWASan או על שימוש HWASan על אנדרואיד .

ASan מזהה הצפות מחיצות/גלובליות בנוסף להצפות ערימות, והוא מהיר עם תקרת זיכרון מינימלית.

מסמך זה מתאר כיצד לבנות ולהפעיל חלקים/כל אנדרואיד עם ASan. אם אתה בונה SDK / אפליקציה NDK עם אסאן, לראות כתובת Sanitizer במקום.

חיטוי הפעלות בודדות עם ASan

להוסיף LOCAL_SANITIZE:=address או sanitize: { address: true } מן הכלל לבנות עבור הפעלה. תוכל לחפש בקוד דוגמאות קיימות או למצוא את חומרי החיטוי הזמינים האחרים.

כאשר באג מזוהה, אסאן מדפיס דוח מפורט הן לפלט הסטנדרטי וכדי logcat ואז מתרסק בתהליך.

חיטוי ספריות משותפות עם אסאן

בשל אופן הפעולה של ASan, ניתן להשתמש בספרייה שנבנתה עם ASan רק על ידי הפעלה שנבנית עם ASan.

כדי לחטא ספרייה משותפת המשמשת להרבה הפעלות, שלא כולן בנויות עם ASan, אתה צריך שני עותקים של הספרייה. הדרך המומלצת לעשות זאת היא להוסיף את הדברים הבאים כדי Android.mk עבור המודול מדובר:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

שמה זה בספרייה /system/lib/asan במקום /system/lib . לאחר מכן, הפעל את קובץ ההפעלה שלך באמצעות:

LD_LIBRARY_PATH=/system/lib/asan

הדמונים המערכת, הוסף את הקוד הבא במקטע של מתאים /init.rc או /init.$device$.rc .

setenv LD_LIBRARY_PATH /system/lib/asan

לוודא שתהליך משתמש ספריות מ /system/lib/asan כאשר ההווה על ידי קריאה /proc/$PID/maps . אם זה לא, ייתכן שתצטרך להשבית את SELinux:

adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID
# if it is a system service, or may be adb shell stop; adb shell start.

עקבות ערימה טובות יותר

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

LOCAL_CFLAGS:=-fno-omit-frame-pointer
LOCAL_ARM_MODE:=arm

או להגדיר ASAN_OPTIONS=fast_unwind_on_malloc=0 בסביבת התהליך. האחרון יכול להיות מאוד עתיר מעבד, תלוי בעומס.

סמל

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

  • ודא כי llvm-symbolizer בינארי הוא נוכח /system/bin . llvm-symbolizer בנוי ממקורות third_party/llvm/tools/llvm-symbolizer .
  • סנן את הדו"ח דרך external/compiler-rt/lib/asan/scripts/symbolize.py סקריפט.

הגישה השנייה יכולה לספק נתונים יותר (כלומר, file:line מקומות) בגלל הזמינות של ספריות סמלו במחשב המארח.

ASan באפליקציות

ASan לא יכול להיכנס לקוד Java, אך הוא יכול לזהות באגים בספריות JNI. בשביל זה, אתה צריך לבנות את ההפעלה עם אסאן, אשר במקרה זה הוא /system/bin/app_process( 32|64 ) . זה מאפשר ל- ASan בכל היישומים במכשיר בו זמנית, וזה עומס כבד, אבל מכשיר עם 2 GB זיכרון RAM אמור להיות מסוגל להתמודד עם זה.

להוסיף LOCAL_SANITIZE:=address אל app_process הכלל לבנות ב frameworks/base/cmds/app_process . התעלם app_process__asan היעד באותו קובץ לעת עתה (אם זה עדיין שם בזמן שאתה קורא את זה).

ערוך את service zygote הקטע המתאימה system/core/rootdir/init.zygote( 32|64 ).rc הקובץ להוסיף את השורות הבאות גוש קווי מסוכסך המכיל class main , גם מסוכסך ידי אותה כמות:

    setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    setenv ASAN_OPTIONS allow_user_segv_handler=true

בנה, סנכרן ADB, אתחול פלאש באתח מהיר והפעל מחדש.

שימוש בנכס העטיפה

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

ניתן לעשות זאת על ידי הפעלת האפליקציה עם wrap. תכונה. הדוגמה הבאה מריצה את אפליקציית Gmail תחת ASan:

adb root
adb shell setenforce 0  # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"

בהקשר זה, asanwrapper משכתב /system/bin/app_process כדי /system/bin/asan/app_process , אשר בנויה עם אסאן. זה גם מוסיף /system/lib/asan בתחילת נתיב חיפוש ספריה דינמית. בדרך זו תסאן מאובזרת ספריות מ /system/lib/asan עדיפות לספריות רגילות /system/lib כאשר רצו עם asanwrapper .

אם נמצא באג, האפליקציה קורסת והדוח מודפס ביומן.

SANITIZE_TARGET

אנדרואיד 7.0 ומעלה כולל תמיכה בבניית כל פלטפורמת האנדרואיד עם ASan בבת אחת. (אם אתה בונה גרסה גבוהה יותר מאנדרואיד 9, HWASan היא בחירה טובה יותר.)

הפעל את הפקודות הבאות באותו עץ בנייה.

make -j42
SANITIZE_TARGET=address make -j42

במצב זה, userdata.img מכיל ספריות מיותרות וצריך הבזיק למכשיר גם כן. השתמש בשורת הפקודה הבאה:

fastboot flash userdata && fastboot flashall

זה בונה שני סטים של ספריות משותפות: רגיל /system/lib (השבעה איפור הראשון), ואת אסאן המאובזרת ב /data/asan/lib (השבעה איפור השני). תוכנות הפעלה מהמבנה השני מחליפות את אלה מהבנייה הראשונה. רצה מאובזרת תסאן לקבל נתיב חיפוש ספרייה שונה שכולל /data/asan/lib לפני /system/lib באמצעות /system/bin/linker_asan ב PT_INTERP .

Clobbers מערכת לבנות ביניים ספריות אובייקט כאשר $SANITIZE_TARGET הערך השתנה. כוחות זה יש לבנות מחדש של כל מטרות תוך שמירה הבינאריים מותקן תחת /system/lib .

לא ניתן לבנות מטרות מסוימות עם ASan:

  • הפעלות מקושרות סטטית
  • LOCAL_CLANG:=false מטרות
  • LOCAL_SANITIZE:=false אינם ASan'd עבור SANITIZE_TARGET=address

הרצה כמו אלה דלגו על SANITIZE_TARGET לבנות, ואת הגרסה מן שבעה האיפור הראשונים נותרה /system/bin .

ספריות כאלה נבנות ללא ASan. הם יכולים להכיל קוד ASan מהספריות הסטטיות שבהן הם תלויים.

מסמכים תומכים