مطهّر العنوان

AddressSanitizer (ASan) هي أداة سريعة تستند إلى التجميع لاكتشاف أخطاء الذاكرة في التعليمات البرمجية الأصلية.

يكتشف ASan ما يلي:

  • تجاوز/تدفق المخزن المؤقت للتكديس وأجزاء من الذاكرة
  • استخدام لقطات لأجزاء من الذاكرة بعد الفترة المجانية
  • استخدام التكديس خارج النطاق
  • موقف سيارات مزدوج/بدون تكلفة

يعمل ASan على كل من معالجات ARM بالإصدار 32 بت و64 بت، بالإضافة إلى معالجات x86 وx86-64. أعباء وحدة المعالجة المركزية في ASan أكبر بمرتين تقريبًا، ويتراوح حجم الرمز البرمجي بين 50% و2x، فضلاً عن حجم كبير من الذاكرة التي تحملها (يعتمد على أنماط التخصيص، ولكن بترتيب 2x).

Android 10 والفرع الرئيسي لنظام AOSP على AArch64 دعامة addressSanitizer (HWASan) المدعوم بالأجهزة، أداة مماثلة ذات أعباء أقل لذاكرة الوصول العشوائي نطاق من الأخطاء المكتشفة. رصدت HWASan استخدام التكديس بعد الإرجاع، بالإضافة إلى الأخطاء التي اكتشفها ASan.

لدى HWASan أعباء إضافية على وحدة المعالجة المركزية (CPU) وحجم الرموز، لكن حجم ذاكرة الوصول العشوائي أقل بكثير (%15). لغة HWASan غير حتمية. هناك فقط 256 قيمة علامة محتملة، لذا توجد قيمة ثابتة تبلغ 0.4% واحتمال فقدان أي خطأ. لا تحتوي HWASan على مناطق حمراء محدودة الحجم من ASan الكشف عن حالات تجاوز السعة ووحدة العزل ذات السعة المحدودة لاكتشاف حالات "الاستخدام بعد النقل"، لذلك لا يهم بالنسبة إلى HWASan حجم الفائض أو كم من الوقت مضى على تم تخصيصه. وهذا يجعل HWASan أفضل من ASan. يمكنك قراءة المزيد عن تصميم HWASan أو عن استخدام HWASan على Android

اكتشاف ASan لتجاوزات التكديس/تجاوزات عامة بالإضافة إلى تجاوزات لأجزاء من الذاكرة، وهي سريعة مع الحد الأدنى من أعباء الذاكرة.

يوضّح هذا المستند كيفية تصميم أجزاء من Android أو كل أجهزة Android وتشغيلها باستخدام ASan. في حال إنشاء تطبيق SDK/NDK باستخدام ASan، يُرجى الاطّلاع على معقّم العنوان بدلاً من ذلك.

تنظيف الملفات التنفيذية الفردية باستخدام ASan

إضافة LOCAL_SANITIZE:=address أو sanitize: { address: true } إلى قاعدة الإصدار للملف التنفيذي. ويمكنك البحث في التعليمات البرمجية عن أمثلة حالية أو البحث عن معطقمات التنظيف الأخرى المتاحة.

عند اكتشاف خطأ، يطبع ASan تقريرًا مطوَّلاً إلى المعيار إلى logcat ثم تعطل العملية.

تنظيف المكتبات المشتركة باستخدام ASan

نظرًا للطريقة التي تعمل بها 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 أداة إلغاء سريعة مستندة إلى مؤشر الإطار لتسجيل تكديس لكل حدث تخصيص للذاكرة وترتيب في البرنامج. معظم الأقسام في نظام Android بدون مؤشرات عرض الإطارات. نتيجة لذلك، غالبًا ما إطار أو إطارين ذي معنى. لحل هذه المشكلة، يمكنك إما إعادة إنشاء المكتبة باستخدام 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. المكتبات. ولتنفيذ ذلك، تحتاجون إلى إنشاء ملف قابل للتنفيذ باستخدام ASan، والذي هذا الطلب هو /system/bin/app_process(32|64). هذا النمط لتمكين ASan في جميع التطبيقات على الجهاز في نفس الوقت، وهو ولكن من المفترض أن يتمكن الجهاز المزوّد بذاكرة وصول عشوائي (RAM) بسعة 2 غيغابايت من معالجة هذا الإجراء.

إضافة "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، وتشغيل فلاش Fastboot، وإعادة التشغيل.

استخدام خاصية الالتفاف

النهج الموجود في القسم السابق يضع ASan في كل في النظام (في الواقع، في كل عنصر تابع لـ Zygote العملية). من الممكن تشغيل تطبيق واحد (أو أكثر) باستخدام ميزة ASan، تداول بعض أعباء الذاكرة لبدء تشغيل التطبيق بشكل أبطأ.

ويمكن إجراء ذلك من خلال بدء تطبيقك باستخدام السمة wrap.. يُشغِّل المثال التالي تطبيق Gmail ضمن ASan:

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

في هذا السياق، تتم إعادة كتابة /system/bin/app_process من قِبل "asanwrapper". إلى /system/bin/asan/app_process، التي تم إنشاؤها باستخدام ASan. يضيف أيضًا /system/lib/asan في بداية مسار بحث المكتبة الديناميكي. بهذه الطريقة تعزف موسيقى ASan من المكتبات من /system/lib/asan هي المفضّلة للمكتبات العادية. في /system/lib عند التشغيل مع asanwrapper.

في حال العثور على خطأ، يتعطّل التطبيق وتتم طباعة التقرير السجل.

SANITIZE_TARGET

يشمل الإصدار 7.0 من Android والإصدارات الأحدث دعمًا لإنشاء نظام Android الأساسي بأكمله باستخدام ASan مرة واحدة. (إذا كنت بصدد إنشاء إصدار أحدث من Android 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.

يخترق نظام التصميم أدلة الكائنات الوسيطة عندما تم تغيير قيمة $SANITIZE_TARGET. يؤدي هذا إلى إعادة إنشاء كل المستهدفة مع الاحتفاظ بالثنائيات المثبَّتة ضمن /system/lib.

لا يمكن إنشاء بعض الاستهدافات باستخدام ASan:

  • الملفات التنفيذية المرتبطة بشكل ثابت
  • هدفان (LOCAL_CLANG:=false)
  • لم يتم إنشاء LOCAL_SANITIZE:=false باستخدام ASan لـ SANITIZE_TARGET=address

يتم تخطي الملفات التنفيذية مثل هذه في إصدار SANITIZE_TARGET، من أول استدعاء (إجراء) متبقٍّ في /system/bin.

تم بناء مثل هذه المكتبات بدون ASan. يمكن أن تحتوي على بعض ASan من المكتبات الثابتة التي تعتمد عليها.

المستندات الداعمة