Google is committed to advancing racial equity for Black communities. See how.
Эта страница переведена с помощью Cloud Translation API.
Switch to English

AddressSanitizer

AddressSanitizer (ASan) - это быстрый инструмент на основе компилятора для обнаружения ошибок памяти в машинном коде.

ASan обнаруживает:

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

ASan работает как на 32-битной, так и на 64-битной ARM, а также на x86 и x86-64. Накладные расходы ЦП ASan составляют примерно 2x, накладные расходы на размер кода составляют от 50% до 2x и большие накладные расходы памяти (в зависимости от ваших шаблонов распределения, но порядка 2x).

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

HWASan имеет аналогичные накладные расходы на ЦП и размер кода, но гораздо меньшие накладные расходы на ОЗУ (15%). HWASan недетерминирован. Существует только 256 возможных значений тегов, поэтому вероятность пропуска какой-либо ошибки составляет 0,4%. HWASan не имеет красных зон ограниченного размера ASan для обнаружения переполнения и карантина с ограниченной емкостью для обнаружения использования после освобождения, поэтому для HWASan не имеет значения, насколько велик переполнение или как давно была освобождена память. Это делает HWASan лучше, чем ASan. Вы можете узнать больше о дизайне HWASan или об использовании HWASan на Android .

ASan обнаруживает переполнение стека / глобального переполнения в дополнение к переполнению кучи и работает быстро с минимальными затратами памяти.

В этом документе описывается, как собирать и запускать части / все Android с помощью ASan. Если вы создаете приложение SDK / NDK с помощью ASan, см. Вместо этого раздел Address Sanitizer .

Очистка отдельных исполняемых файлов с помощью 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 из источников в 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 во всех приложениях на устройстве одновременно, что является большой нагрузкой, но устройство с 2 ГБ ОЗУ должно справиться с этим.

Добавьте LOCAL_SANITIZE:=address в app_process сборки app_process в frameworks/base/cmds/app_process . app_process__asan обращайте внимания на цель 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 и перезагрузка.

Использование свойства wrap

Подход, описанный в предыдущем разделе, помещает ASan в каждое приложение в системе (фактически, в каждый потомок процесса Zygote). С ASan можно запускать только одно (или несколько) приложений, жертвуя накладными расходами памяти на более медленный запуск приложения.

Это можно сделать, запустив приложение с wrap. свойство. В следующем примере приложение Gmail запускается под ASan:

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

В этом контексте asanwrapper перезаписывает /system/bin/app_process в /system/bin/asan/app_process , который построен с помощью ASan. Он также добавляет /system/lib/asan в начало пути поиска динамической библиотеки. Таким образом, библиотеки с ASan из /system/lib/asan предпочтительнее обычных библиотек в /system/lib при работе с asanwrapper .

Если ошибка обнаружена, приложение вылетает, и отчет печатается в журнале.

SANITIZE_TARGET

Android 7.0 и выше включает поддержку создания всей платформы Android с ASan сразу. (Если вы создаете выпуск выше Android 9, HWASan - лучший выбор.)

Выполните следующие команды в том же дереве сборки.

make -j42
SANITIZE_TARGET=address make -j42

В этом режиме userdata.img содержит дополнительные библиотеки и также должен быть прошит на устройство. Используйте следующую командную строку:

fastboot flash userdata && fastboot flashall

Это создает два набора разделяемых библиотек: обычные в /system/lib (первый вызов make) и с инструментами ASan в /data/asan/lib (второй вызов make). Исполняемые файлы из второй сборки перезаписывают исполняемые файлы из первой сборки. Исполняемые файлы, оснащенные ASan, получают другой путь поиска библиотек, который включает /data/asan/lib перед /system/lib счет использования /system/bin/linker_asan в PT_INTERP .

Система сборки очищает каталоги промежуточных объектов при изменении значения $SANITIZE_TARGET . Это вызывает перестройку всех целей с сохранением установленных двоичных файлов в /system/lib .

Некоторые цели не могут быть построены с помощью ASan:

  • Статически связанные исполняемые файлы
  • LOCAL_CLANG:=false цели
  • LOCAL_SANITIZE:=false не ASan'd для SANITIZE_TARGET SANITIZE_TARGET=address

Подобные исполняемые файлы пропускаются в сборке SANITIZE_TARGET , а версия из первого вызова make остается в /system/bin .

Подобные библиотеки создаются без ASan. Они могут содержать некоторый код ASan из статических библиотек, от которых они зависят.

Сопутствующая документация