Понимание отчетов HWAsan

Когда инструмент HWASan обнаруживает ошибку памяти, процесс завершается с помощью abort() , и отчет выводится в stderr и logcat. Как и все сбои в нативных приложениях Android, ошибки HWASan находятся в каталоге /data/tombstones .

Пример отчета

В отличие от обычных сбоев, вызванных нативными процессами, HWASan содержит дополнительную информацию в поле сообщения Abort, расположенном в верхней части сообщения об ошибке. Вот пример сбоя, связанного с кучей данных. Информацию об ошибках, связанных со стеком, см. в примечании к разделам, посвященным конкретным проблемам со стеком.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
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.

Ошибка доступа

Содержит информацию о некорректных обращениях к памяти, в том числе:

  • Тип доступа ( READ или WRITE )
  • Размер доступа (количество байтов, к которым была предпринята попытка доступа)
  • номер потока доступа
  • Указатели и метки памяти (для расширенной отладки)

Трассировка стека доступа

Трассировка стека некорректного доступа к памяти. См. раздел «Символизация» для создания символических данных.

Причина

Возможная причина проблем с доступом. Если есть несколько вариантов, они перечислены в порядке убывания вероятности. Предшествует подробной информации о потенциальной причине. 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 (Other Deployment Disclosure ).
<address> is located N bytes inside of M-byte region [<start>, <end>)
freed by thread T0 here:
Не могу указать адрес Либо происходит свободное освобождение памяти (освобождение памяти, которая ранее не была выделена), либо двойное освобождение памяти после того, как выделенная память была вытеснена из буфера свободного пространства HWASan.
0x... — это теневая память HWAsan. Произошла несанкционированная освобождение памяти, поскольку приложение пыталось освободить память, находящуюся внутри HWASan.

трассировка стека освобождения памяти

Трассировка стека, показывающая место освобождения памяти. Присутствует только при ошибках, связанных с использованием памяти после освобождения (use-after-free) или недопустимой свободным памятью (valid-free). См. раздел «Символизация» для символизации.

трассировка стека выделения

Трассировка стека, показывающая, где была выделена память. См. раздел «Символизация» для символизации.

Расширенная отладочная информация

В отчете 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 байт ad тегов слева, которые соответствуют тегу указателя.

Если размер выделенной памяти не кратен 16, оставшаяся часть размера сохраняется в качестве тега памяти , а сам тег хранится как короткий гранулярный тег . В предыдущем примере, сразу после выделенной жирным шрифтом области памяти с тегом ad , мы имеем выделение памяти размером 5 × 16 + 4 = 84 байта с тегом 5c .

Метка нулевой памяти (например, tags: ad/ 00 (ptr/mem) ) указывает на ошибку использования стека после возврата из функции.

Дамп регистра

Дамп регистров в отчетах HWASan соответствует инструкции, выполнившей недопустимый доступ к памяти. За этим дампом следует еще один дамп регистров из обычного обработчика сигналов Android. Второй дамп следует игнорировать , поскольку он был получен при вызове функции abort() в HWASan и не имеет отношения к ошибке.

Символизация

Для получения имен функций и номеров строк в трассировках стека (а также имен переменных для ошибок, связанных с использованием после завершения работы программы) необходим этап символизации в автономном режиме.

Первоначальная настройка: установите llvm-symbolizer.

Для символизации в вашей системе должен быть установлен и доступен из $PATH llvm-symbolizer . В Debian его можно установить с помощью sudo apt install llvm .

Получить файлы символов

Для символизации нам необходимы необработанные бинарные файлы, содержащие символы. Их расположение зависит от типа сборки:

  • Для локальной сборки файлы символов находятся в папке out/target/product/<product>/symbols/ .
  • Для сборок AOSP (например, прошитых с помощью Android Flash Tool ) сборка выполняется в среде 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 не преобразует их в понятный человеку контент в отчете об ошибке и требует дополнительного этапа символизации .

нарушения ODR

Некоторые ошибки, связанные с использованием памяти после освобождения (use-after-free), о которых сообщает HWASan, могут указывать на нарушение правила одного определения (One Definition Rule, ODR). Нарушение ODR происходит, когда одна и та же переменная определяется несколько раз в одной и той же программе. Это также означает, что переменная уничтожается несколько раз, что может привести к ошибке use-after-free.

После символизации нарушения 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. Сообщите об ошибке и, если возможно, предоставьте инструкции по воспроизведению проблемы.