Аппаратный адрессанитайзер

Информацию о том, как читать сбои HWASan, см. в разделе «Понимание отчетов HWASan» !

Аппаратно-ассистируемый AddressSanitizer (HWASan) — это инструмент обнаружения ошибок памяти, похожий на AddressSanitizer . HWASan использует намного меньше оперативной памяти по сравнению с ASan, что делает его пригодным для очистки всей системы. HWASan доступен только на Android 10 и выше и только на оборудовании AArch64.

Хотя HWASan в первую очередь полезен для кода C/C++, он также может помочь отладить код Java, который вызывает сбои в C/C++, используемых для реализации интерфейсов Java. Он полезен, поскольку он отлавливает ошибки памяти, когда они происходят, указывая вам непосредственно на ответственный код.

По сравнению с классическим ASan, HWASan имеет:

  • Аналогичная загрузка ЦП (~2x)
  • Аналогичные накладные расходы по размеру кода (40–50%)
  • Значительно меньшие накладные расходы на ОЗУ (10% – 35%)

HWASan обнаруживает тот же набор ошибок, что и ASan:

  • Переполнение/незаполнение буфера стека и кучи
  • Использование кучи после освобождения
  • Использование стека вне области действия
  • Двойной бесплатный/дикий бесплатный

Кроме того, HWASan обнаруживает использование стека после возврата.

HWASan (то же, что и ASan) совместим с UBSan , оба могут быть включены на целевом устройстве одновременно.

Детали реализации и ограничения

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

Подробнее о разработке HWASan можно прочитать на сайте документации Clang.

По замыслу HWASan не имеет ограниченных по размеру красных зон ASan для обнаружения переполнений или ограниченного по емкости карантина ASan для обнаружения использования после освобождения. По этой причине HWASan может обнаружить ошибку независимо от того, насколько велико переполнение или как давно была освобождена память. Это дает HWASan большое преимущество перед ASan.

Однако HWASan имеет ограниченное количество возможных значений тегов (256), что означает, что вероятность пропуска любой ошибки во время одного выполнения программы составляет 0,4%.

Требования

Последние версии (4.14+) общего ядра Android поддерживают HWASan из коробки. Ветви, специфичные для Android 10, не поддерживают HWASan.

Поддержка пользовательского пространства для HWASan доступна начиная с Android 11 .

Если вы работаете с другим ядром, HWASan требует, чтобы ядро ​​Linux принимало помеченные указатели в аргументах системного вызова. Поддержка этого была реализована в следующих upstream patchsets:

Если вы создаете проект с помощью пользовательского набора инструментов, убедитесь, что он включает все до коммита LLVM c336557f .

Используйте HWASan

Для сборки всей платформы с помощью HWASan используйте следующие команды:

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

Для удобства вы можете добавить параметр SANITIZE_TARGET в определение продукта, аналогично aosp_coral_hwasan .

Для пользователей, знакомых с AddressSanitizer, значительная часть сложности сборки исчезла:

  • Нет необходимости запускать make дважды.
  • Инкрементные сборки работают сразу после установки.
  • Нет необходимости прошивать пользовательские данные.

Некоторые ограничения AddressSanitizer также сняты:

  • Поддерживаются статические исполняемые файлы.
  • Можно пропустить санацию любой цели, кроме libc. В отличие от ASan, нет требования, что если библиотека санирована, то и любой исполняемый файл, который ее связывает, тоже должен быть санирован.

Переключение между HWASan и обычными образами с тем же (или более высоким) номером сборки может быть выполнено свободно. Очистка устройства не требуется.

Чтобы пропустить очистку модуля, используйте LOCAL_NOSANITIZE := hwaddress (Android.mk) или sanitize: { hwaddress: false } (Android.bp).

Обеззараживать отдельные цели

HWASan можно включить для каждой цели в обычной (несанированной) сборке, если libc.so также санирован. Добавьте hwaddress: true в блок sanitize в "libc_defaults" в bionic/libc/Android.bp. Затем сделайте то же самое в цели, над которой вы работаете.

Обратите внимание, что очистка libc включает маркировку выделений памяти кучи по всей системе, а также проверку тегов для операций с памятью внутри libc.so . Это может обнаружить ошибки даже в двоичных файлах, для которых HWASan не был включен, если плохой доступ к памяти находится в libc.so (например, pthread_mutex_unlock() на мьютексе delete() ).

Если вся платформа собрана с использованием HWASan, изменять какие-либо файлы сборки не требуется.

Улучшенные трассировки стека

HWASan использует быстрый, основанный на указателях кадров раскручиватель для записи трассировки стека для каждого события выделения и освобождения памяти в программе. Android по умолчанию включает указатели кадров в коде AArch64, поэтому это отлично работает на практике. Если вам нужно раскручивать через управляемый код, установите HWASAN_OPTIONS=fast_unwind_on_malloc=0 в среде процесса. Обратите внимание, что трассировки стека плохого доступа к памяти используют «медленный» раскручиватель по умолчанию; эта настройка влияет только на трассировки выделения и освобождения. Эта опция может быть очень ресурсоемкой для ЦП, в зависимости от нагрузки.

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

См. Символизацию в разделе «Понимание отчетов HWASan».

HWASan в приложениях

Подобно AddressSanitizer, HWASan не может заглядывать в код Java, но может обнаруживать ошибки в библиотеках JNI. До Android 14 запуск приложений HWASan на устройстве, отличном от HWASan, не поддерживался.

На устройстве HWASan приложения можно проверить с помощью HWASan, построив их код с помощью SANITIZE_TARGET:=hwaddress в Make или -fsanitize=hwaddress в флагах компилятора. На устройстве, отличном от HWASan (под управлением Android 14 или более поздней версии), необходимо добавить файл wrap.sh с настройкой LD_HWASAN=1 . Подробнее см. в документации разработчика приложений .