Аппаратно поддерживаемый AddressSanitizer (HWASan) — это инструмент обнаружения ошибок памяти, аналогичный AddressSanitizer . HWASan использует гораздо меньше оперативной памяти по сравнению с ASan, что делает его пригодным для очистки всей системы. HWASan доступен только на Android 10 и выше и только на оборудовании AArch64.
Хотя HWASan в первую очередь полезен для кода C/C++, он также может помочь в отладке кода Java, вызывающего сбои в C/C++, используемом для реализации интерфейсов Java. Это полезно, потому что он перехватывает ошибки памяти, когда они происходят, указывая вам непосредственно на ответственный код.
Вы можете прошить готовые образы HWASan на поддерживаемые устройства Pixel с сайта ci.android.com ( подробные инструкции по установке ).
По сравнению с классическим ASan, HWAsan имеет:
- Аналогичные накладные расходы ЦП (~ 2x)
- Накладные расходы аналогичного размера кода (40–50%)
- Гораздо меньшие накладные расходы на оперативную память (10–35%)
HWASan обнаруживает тот же набор ошибок, что и ASan:
- Переполнение/опустошение буфера стека и кучи
- Использование кучи после бесплатного
- Использование стека вне области действия
- Двойной бесплатный/дикий бесплатный
Кроме того, HWASan обнаруживает использование стека после возврата.
Детали реализации и ограничения
HWASan основан на подходе тегирования памяти , где небольшое случайное значение тега связано как с указателями, так и с диапазонами адресов памяти. Чтобы доступ к памяти был действительным, указатель и теги памяти должны совпадать. HWASan использует функцию игнорирования верхнего байта (TBI) ARMv8, также называемую тегированием виртуального адреса , для сохранения тега указателя в старших битах адреса.
Вы можете узнать больше о дизайне HWASan на сайте документации Clang.
По замыслу HWASan не имеет красных зон ограниченного размера ASan для обнаружения переполнения или карантина ASan с ограниченной емкостью для обнаружения использования после бесплатного использования. По этой причине HWASan может обнаружить ошибку независимо от того, насколько велико переполнение или как давно память была освобождена. Это дает HWASan большое преимущество перед ASan.
Однако у HWASan есть ограниченное количество возможных значений тегов (256), а это означает, что существует 0,4% вероятность пропустить какую-либо ошибку во время одного выполнения программы.
Требования
HWASan требует, чтобы ядро Linux принимало помеченные указатели в аргументах системного вызова. Поддержка этого была реализована в следующих наборах исправлений основной ветки разработки:
- arm64 тегированный адрес ABI
- arm64: удалить пользовательские указатели, переданные ядру
- mm: избегайте создания псевдонимов виртуальных адресов в brk()/mmap()/mremap().
- arm64: Проверять помеченные адреса в access_ok(), вызываемом из потоков ядра.
Эти исправления доступны в качестве резервных копий в общем ядре Android в ветках android-4.14 и выше, но не в ветках, специфичных для Android 10, таких как android-4.14-q .
Поддержка пользовательского пространства для HWAsan доступна, начиная с Android 11 .
Если вы создаете с помощью специальной цепочки инструментов, убедитесь, что она включает в себя все, вплоть до коммита LLVM c336557f .
Использование HWAСан
Используйте следующие команды для создания всей платформы с помощью HWASan:
lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j
Для удобства вы можете добавить параметр SANITIZE_TARGET в определение продукта, аналогичный aosp_coral_hwasan .
В отличие от ASan, с HWAsan нет необходимости создавать дважды. Инкрементные сборки просто работают, нет специальных инструкций по перепрошивке или требований к очистке, поддерживаются статические исполняемые файлы, и можно пропустить очистку любой библиотеки, кроме libc
. Также не требуется, чтобы в случае очистки библиотеки любой исполняемый файл, который ссылается на нее, также должен быть очищен.
Чтобы пропустить очистку модуля, используйте LOCAL_NOSANITIZE := hwaddress
или sanitize: { hwaddress: false }
.
Отдельные модули могут быть санированы с помощью HWASan, с оговоркой, что libc
также является санитизированным с помощью HWASan. Это можно сделать, добавив sanitize: { hwaddress: true }
в соответствующее определение модуля Android.bp
. Вся платформа Android построена с помощью HWASan при использовании сборки с _hwasan
_hwasan (включая libc
), поэтому ручная очистка libc
не требуется для сборок HWASan.
Улучшенная трассировка стека
HWASan использует быструю размотку на основе указателя кадра для записи трассировки стека для каждого события выделения и освобождения памяти в программе. Android по умолчанию включает указатели кадров в коде AArch64, так что на практике это прекрасно работает. Если вам нужно раскрутить управляемый код, установите HWASAN_OPTIONS=fast_unwind_on_malloc=0
в среде процесса. Обратите внимание, что в трассировках стека при неправильном доступе к памяти по умолчанию используется «медленная» размотка; этот параметр влияет только на трассировки распределения и освобождения. Этот параметр может сильно нагружать ЦП, в зависимости от нагрузки.
Символизация
См. Символы в документации ASan .
HWASan в приложениях
Подобно AddressSanitizer, HWASan не может заглянуть в код Java, но может обнаружить ошибки в библиотеках JNI. В отличие от ASan, запуск приложений HWASan на устройстве, отличном от HWASan, не поддерживается.
На устройстве HWASan приложения можно проверить с помощью HWASan, создав их код с SANITIZE_TARGET:=hwaddress
в Make или -fsanitize=hwaddress
во флагах компилятора. Дополнительные сведения см. в документации разработчика приложений .