فهم تقارير HWASan

عندما تكتشف أداة HWASan وجود خطأ في الذاكرة، يتم إنهاء العملية باستخدام abort()، ويتم طباعة تقرير إلى stderr وlogcat. مثل جميع الأعطال الأصلية على Android، يمكن العثور على أخطاء HWASan ضمن /data/tombstones .

بالمقارنة مع الأعطال الأصلية المعتادة، يحمل HWASan معلومات إضافية في حقل "رسالة الإلغاء" بالقرب من الجزء العلوي من شاهد القبر. راجع نموذجًا للعطل المستند إلى الكومة أدناه (بالنسبة لأخطاء المكدس، راجع الملاحظة أدناه للتعرف على الأقسام الخاصة بالمكدس).

تقرير المثال

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys'
Revision: 'DVT1.0'
ABI: 'arm64'
Timestamp: 2019-04-24 01:13:22+0000
pid: 11154, tid: 11154, name: sensors@1.0-ser  >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<<
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: '

[...]

[0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5








[ … regular crash dump follows …]

وهذا مشابه جدًا لتقرير AddressSanitizer . وخلافًا لتلك الأخطاء، فإن جميع أخطاء HWASan تقريبًا هي "عدم تطابق العلامات"، أي الوصول إلى الذاكرة حيث لا تتطابق علامة المؤشر مع علامة الذاكرة المقابلة. هذا يمكن أن يكون واحدا من

  • الوصول خارج الحدود على المكدس أو الكومة
  • استخدم بعد الحرة على الكومة
  • استخدم بعد العودة على المكدس

الأقسام

فيما يلي شرح لكل قسم من أقسام تقرير HWASan:

خطأ في الوصول

يحتوي على معلومات حول الوصول السيئ للذاكرة، بما في ذلك:

  • نوع الوصول ("قراءة" مقابل "كتابة")
  • حجم الوصول (عدد البايتات التي تمت محاولة الوصول إليها)
  • رقم الموضوع للوصول
  • علامات المؤشر والذاكرة (للتصحيح المتقدم)

الوصول إلى تتبع المكدس

تتبع المكدس للوصول إلى الذاكرة السيئة. راجع قسم الترميز للترميز.

سبب

السبب المحتمل للوصول السيئ. إذا كان هناك عدة مرشحين، يتم إدراجهم بترتيب تنازلي. تسبق المعلومات التفصيلية حول السبب المحتمل. يمكن لـ HWASan تشخيص الأسباب التالية:

  • الاستخدام بعد الحرة
  • عدم تطابق علامة المكدس: يمكن أن يكون هذا مكدسًا للاستخدام بعد الإرجاع/الاستخدام بعد النطاق، أو خارج الحدود
  • تجاوز سعة المخزن المؤقت للكومة
  • الفائض العالمي

معلومات الذاكرة

يصف ما تعرفه HWASan عن الذاكرة التي يتم الوصول إليها، وقد يختلف بناءً على نوع الخطأ.

نوع الخطأ سبب شكل التقرير
عدم تطابق العلامة الاستخدام بعد الحرة
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
تجاوز سعة المخزن المؤقت للكومة لاحظ أن هذا يمكن أن يكون أيضًا تدفقًا سفليًا.
<address> is located N bytes to the right of M-byte region [<start>, <end>)
  allocated here:
عدم تطابق علامة المكدس لا تفرق تقارير المكدس بين أخطاء التجاوز/التجاوز وأخطاء الاستخدام بعد الإرجاع. بالإضافة إلى ذلك، للعثور على تخصيص المكدس الذي يمثل مصدر الخطأ، يلزم وجود خطوة ترميز دون اتصال. راجع قسم فهم تقارير المكدس أدناه.
خالية من صالحة الاستخدام بعد الحرة هذا خطأ مزدوج مجاني. إذا حدث هذا عند إيقاف تشغيل العملية، فقد يشير ذلك إلى انتهاك ODR .
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
لا يمكن وصف العنوان إما حرة جامحة (خالية من الذاكرة التي لم يتم تخصيصها من قبل)، أو حرة مزدوجة بعد إزالة الذاكرة المخصصة من المخزن المؤقت الحر لـ HWASan.
0x... هي ذاكرة الظل HWAsan. يعد هذا مجانيًا للغاية، حيث كان التطبيق يحاول تحرير الذاكرة الداخلية لـ HWASan.

تتبع المكدس إلغاء التخصيص

تتبع المكدس حيث تم إلغاء تخصيص الذاكرة. موجود فقط للأخطاء الخالية من الاستخدام أو الخالية من الصالحات. راجع قسم الترميز للترميز.

تتبع مكدس التخصيص

تتبع المكدس للمكان الذي تم تخصيص الذاكرة فيه. راجع قسم الترميز للترميز.

معلومات التصحيح المتقدمة

يتميز تقرير HWASan أيضًا ببعض معلومات تصحيح الأخطاء المتقدمة، بما في ذلك (بالترتيب):

  1. قائمة المواضيع في هذه العملية
  2. قائمة المواضيع في هذه العملية
  3. قيمة علامات الذاكرة القريبة من الذاكرة المعطوبة
  4. تفريغ السجلات عند نقطة الوصول إلى الذاكرة

تفريغ علامة الذاكرة

يمكن استخدام تفريغ ذاكرة العلامة للبحث عن عمليات تخصيص الذاكرة القريبة بنفس العلامة مثل علامة المؤشر. يمكن أن تشير هذه إلى وصول خارج الحدود مع إزاحة كبيرة. علامة واحدة تقابل 16 بايت من الذاكرة؛ علامة المؤشر هي أعلى 8 بتات من العنوان. يمكن أن يقدم تفريغ ذاكرة العلامة تلميحات، على سبيل المثال ما يلي هو تجاوز سعة المخزن المؤقت إلى اليمين:

tags: ad/5c (ptr/mem)
[...]
Memory tags around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: 0e  0e  0e  57  20  20  20  20  20  2e  5e  5e  5e  5e  5e  b5
=>0x006f33ae2000: f6  f6  f6  f6  f6  4c  ad  ad  ad  ad  ad  ad [5c] 5c  5c  5c
  0x006f33ae2010: 5c  04  2e  2e  2e  2e  2e  2f  66  66  66  66  66  80  6a  6a
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: ab  52  eb  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
=>0x006f33ae2000: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. [..] ..  ..  ..
  0x006f33ae2010: ..  5c  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
(لاحظ تشغيل 6 × 16 = 96 بايت من علامات "الإعلان" الموجودة على اليسار والتي تطابق علامة المؤشر).

إذا لم يكن حجم التخصيص من مضاعفات 16، فسيتم تخزين باقي الحجم كعلامة ذاكرة وسيتم تخزين العلامة كعلامة حبيبية قصيرة . في المثال أعلاه، بعد إعلان التخصيص الغامق مباشرةً، لدينا تخصيص 5 × 16 + 4 = 84 بايت للعلامة 5c.

تشير علامة الذاكرة الصفرية (مثل tags: ad/ 00 (ptr/mem) ) عادةً إلى وجود خطأ في استخدام المكدس بعد العودة.

تسجيل تفريغ

يتوافق تفريغ السجل في تقارير HWASan مع التعليمات الفعلية التي أدت إلى الوصول غير الصالح إلى الذاكرة. يتبعه تفريغ تسجيل آخر من معالج إشارة Android العادي - تجاهل الثاني ، يتم التقاطه عندما يستدعي HWASan abort() ولا علاقة له بالخطأ.

الترميز

للحصول على أسماء الوظائف وأرقام الأسطر في تتبعات المكدس (والحصول على أسماء متغيرة لأخطاء الاستخدام بعد النطاق)، يلزم وجود خطوة ترميز دون اتصال.

الإعداد لأول مرة: تثبيت llvm-symbolizer

للترمز، يجب أن يكون نظامك مثبتًا على llvm-symbolizer ويمكن الوصول إليه من $PATH. على دبيان، يمكنك تثبيته باستخدام sudo apt install llvm .

الحصول على ملفات الرمز

للترميز، نطلب ثنائيات غير معزولة تحتوي على رموز. يعتمد مكان العثور عليها على نوع البناء:

بالنسبة للإصدارات المحلية ، يمكن العثور على ملفات الرموز في out/target/product/<product>/symbols/ .

بالنسبة لإصدارات AOSP (على سبيل المثال، التي تومض من Flashstation )، يمكن العثور على الإصدارات على Android CI . في "Artifacts" الخاصة بالإنشاء، سيكون هناك ملف `${PRODUCT}-symbols-${BUILDID}.zip`.

بالنسبة للإصدارات الداخلية من مؤسستك، راجع وثائق مؤسستك للحصول على مساعدة في الحصول على ملفات الرموز.

يرمز

hwasan_symbolize –-symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash

فهم تقارير المكدس

بالنسبة للأخطاء التي تحدث مع متغيرات المكدس، سيحتوي تقرير HWASan على تفاصيل مثل هذه:

Cause: stack tag-mismatch
Address 0x007d4d251e80 is located in stack of thread T64
Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000)
Previously allocated frames:
  record_addr:0x7df7300c98 record:0x51ef007df3f70fb0  (/apex/com.android.art/lib64/libart.so+0x570fb0)
  record_addr:0x7df7300c90 record:0x5200007df3cdab74  (/apex/com.android.art/lib64/libart.so+0x2dab74)
  [...]
	

للسماح بفهم أخطاء المكدس، تقوم HWASan بتتبع إطارات المكدس التي حدثت في الماضي. حاليًا، لا تقوم HWASan بتحويل هذا إلى محتوى يمكن فهمه من قبل الإنسان في تقرير الأخطاء، وتتطلب خطوة ترميز إضافية.

انتهاكات تسوية المنازعات على الإنترنت

يمكن أن تشير بعض أخطاء الاستخدام بعد الاستخدام المجانية التي أبلغت عنها HWASan أيضًا إلى انتهاك قاعدة التعريف الواحدة (ODR). يحدث انتهاك ODR عندما يتم تعريف نفس المتغير عدة مرات في نفس البرنامج. وهذا يعني أيضًا أنه تم إتلاف المتغير عدة مرات، مما قد يؤدي إلى خطأ الاستخدام بعد التحرر.

بعد الترميز، تظهر انتهاكات ODR استخدامًا بعد الاستخدام مع __cxa_finalize ، على كل من مكدس الوصول غير الصالح ومكدس "تم التحرير هنا". يحتوي المكدس "المخصص مسبقًا هنا" على __dl__ZN6soinfo17call_constructorsEv ويجب أن يشير إلى الموقع في برنامجك الذي يحدد المتغير الأعلى في المكدس.

أحد أسباب انتهاك ODR هو استخدام المكتبات الثابتة. إذا كانت المكتبة الثابتة التي تحدد عمومية C++ مرتبطة بعدة مكتبات مشتركة أو ملفات تنفيذية، فقد ينتهي الأمر بوجود تعريفات متعددة لنفس الرمز في نفس مساحة العنوان، مما سيؤدي إلى حدوث خطأ ODR.

استكشاف الأخطاء وإصلاحها

"لا يمكن لـ HWAddressSanitizer وصف العنوان بمزيد من التفصيل."

في بعض الأحيان قد تنفد المساحة المتوفرة في HWAsan للحصول على معلومات حول عمليات تخصيص الذاكرة السابقة. في هذه الحالة، سيحتوي التقرير على تتبع مكدس واحد فقط للوصول الفوري إلى الذاكرة، متبوعًا بملاحظة:

  HWAddressSanitizer can not describe address in more detail.

في بعض الحالات، يمكن حل هذه المشكلة عن طريق إجراء الاختبار عدة مرات. هناك خيار آخر وهو زيادة حجم سجل HWASan. يمكن القيام بذلك عالميًا في build/soong/cc/sanitize.go (ابحث عن hwasanGlobalOptions )، أو في بيئة العملية الخاصة بك (جرب adb shell echo $HWASAN_OPTIONS لرؤية الإعدادات الحالية).

يمكن أن يحدث هذا أيضًا إذا لم يتم تعيين الذاكرة التي تم الوصول إليها، أو تخصيصها بواسطة مُخصص غير مدرك لـ HWASan. في هذه الحالة، ستكون علامة mem المدرجة في رأس العطل بشكل عام 00 . إذا كان لديك حق الوصول إلى شاهد القبر الكامل، فقد يكون من المفيد مراجعة تفريغ خرائط الذاكرة لمعرفة التعيين (إن وجد) الذي ينتمي إليه العنوان.

"خطأ متداخل في نفس الموضوع"

وهذا يعني أنه كان هناك خطأ أثناء إنشاء تقرير تعطل HWASan. يحدث هذا عادةً بسبب خطأ في وقت تشغيل HWASan، يرجى الإبلاغ عن خطأ وتقديم إرشادات حول كيفية إعادة إظهار المشكلة إن أمكن.