UndefineBehaviorSanitizer (UBSan) выполняет инструментирование во время компиляции для проверки различных типов неопределенного поведения. Хотя UBSan способен обнаруживать множество неопределенных ошибок поведения , Android поддерживает:
- выравнивание
- логическое значение
- границы
- перечисление
- переполнение с плавающей запятой
- деление на ноль с плавающей запятой
- целое число, деление на ноль
- ненулевой атрибут
- нулевой
- возвращаться
- возвращает ненулевой атрибут
- сменная база
- показатель сдвига
- целочисленное переполнение со знаком
- недостижимый
- беззнаковое-целочисленное переполнение
- привязка к Вла
unsigned-integer-overflow, хотя технически и не является неопределенным поведением, включен в дезинфицирующее средство и используется во многих модулях Android, включая компоненты медиасервера, для устранения любых скрытых уязвимостей переполнения целых чисел.
Выполнение
В системе сборки Android вы можете включить UBSan глобально или локально. Чтобы включить UBSan глобально, установите SANITIZE_TARGET в Android.mk. Чтобы включить UBSan на уровне каждого модуля, установите LOCAL_SANITIZE и укажите неопределенное поведение, которое вы хотите искать в Android.mk. Например:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0 LOCAL_SRC_FILES:= sanitizer-status.c LOCAL_MODULE:= sanitizer-status LOCAL_SANITIZE := alignment bounds null unreachable integer LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer include $(BUILD_EXECUTABLE)
И эквивалентная конфигурация проекта (Android.bp):
cc_binary { cflags: [ "-std=c11", "-Wall", "-Werror", "-O0", ], srcs: ["sanitizer-status.c"], name: "sanitizer-status", sanitize: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], diag: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], }, }, }
Ярлыки UBSan
В Android также есть два ярлыка, integer
и default-ub
, для одновременного включения набора дезинфицирующих средств. целое число включает integer-divide-by-zero
, signed-integer-overflow
и unsigned-integer-overflow
. default-ub
включает проверки, которые вызывают минимальные проблемы с производительностью компилятора: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound
. Класс целочисленного дезинфицирующего средства можно использовать с SANITIZE_TARGET и LOCAL_SANITIZE, тогда как default-ub можно использовать только с SANITIZE_TARGET.
Улучшение отчетов об ошибках
Реализация UBsan в Android по умолчанию вызывает указанную функцию при обнаружении неопределенного поведения. По умолчанию эта функция прерывается. Однако, начиная с октября 2016 года, UBSan для Android имеет дополнительную библиотеку времени выполнения, которая предоставляет более подробные отчеты об ошибках, включая тип обнаруженного неопределенного поведения, информацию о файле и строках исходного кода. Чтобы включить отчет об ошибках с целочисленными проверками, добавьте в файл Android.mk следующее:
LOCAL_SANITIZE:=integer LOCAL_SANITIZE_DIAG:=integer
Значение LOCAL_SANITIZE включает дезинфицирующее средство во время сборки. LOCAL_SANITIZE_DIAG включает режим диагностики для указанного дезинфицирующего средства. Можно установить для LOCAL_SANITIZE и LOCAL_SANITIZE_DIAG разные значения, но включены только те проверки, которые указаны в LOCAL_SANITIZE. Если проверка не указана в LOCAL_SANITIZE, но указана в LOCAL_SANITIZE_DIAG, проверка не включена и диагностические сообщения не выдаются.
Вот пример информации, предоставляемой библиотекой времени выполнения UBSan:
pixel-xl:/ # sanitizer-status ubsan sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Очистка целочисленного переполнения
Непреднамеренное переполнение целых чисел может привести к повреждению памяти или уязвимостям раскрытия информации в переменных, связанных с доступом к памяти или ее выделением. Чтобы бороться с этим, мы добавили средства очистки знакового и беззнакового целочисленного переполнения UndefinedBehaviorSanitizer (UBSan) от Clang, чтобы укрепить медиа-фреймворк в Android 7.0. В Android 9 мы расширили UBsan, включив в него больше компонентов , и улучшили поддержку системы сборки.
Это предназначено для добавления проверок арифметических операций/инструкций, которые могут переполниться, чтобы безопасно прервать процесс, если переполнение все же произойдет. Эти дезинфицирующие средства могут смягчить целый класс уязвимостей, связанных с повреждением памяти и раскрытием информации, основной причиной которых является целочисленное переполнение, например, исходная уязвимость Stagefright.
Примеры и источник
Очистка целочисленного переполнения (IntSan) предоставляется компилятором и добавляет инструменты в двоичный файл во время компиляции для обнаружения арифметических переполнений. Он включен по умолчанию в различных компонентах платформы, например /platform/external/libnl/Android.bp
.
Выполнение
IntSan использует средства очистки знакового и беззнакового целочисленного переполнения UBSan. Это смягчение включено на уровне каждого модуля. Это помогает обеспечить безопасность критически важных компонентов Android, и его не следует отключать.
Мы настоятельно рекомендуем вам включить очистку целочисленного переполнения для дополнительных компонентов. Идеальными кандидатами являются привилегированный собственный код или собственный код, который анализирует ненадежный пользовательский ввод. С дезинфицирующим средством связано небольшое снижение производительности, которое зависит от использования кода и распространенности арифметических операций. Ожидайте небольшой процент накладных расходов и проверьте, является ли производительность проблемой.
Поддержка IntSan в make-файлах
Чтобы включить IntSan в make-файле, добавьте:
LOCAL_SANITIZE := integer_overflow # Optional features LOCAL_SANITIZE_DIAG := integer_overflow LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
-
LOCAL_SANITIZE
принимает список дезинфицирующих средств, разделенных запятыми, причемinteger_overflow
представляет собой предварительно упакованный набор опций для отдельных дезинфицирующих средств переполнения целых чисел со знаком и без знака со значением BLOCKLIST по умолчанию . -
LOCAL_SANITIZE_DIAG
включает режим диагностики для дезинфицирующих средств. Используйте режим диагностики только во время тестирования, поскольку он не будет прерываться при переполнении, что полностью сводит на нет преимущества безопасности, связанные с устранением последствий. Дополнительные сведения см. в разделе «Устранение неполадок» . -
LOCAL_SANITIZE_BLOCKLIST
позволяет вам указать файл BLOCKLIST, чтобы предотвратить очистку функций и исходных файлов. Дополнительные сведения см. в разделе «Устранение неполадок» .
Если вам нужен более детальный контроль, включите дезинфицирующие средства по отдельности, используя один или оба флага:
LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow
Поддержка IntSan в файлах чертежей
Чтобы включить очистку целочисленного переполнения в файле схемы, например /platform/external/libnl/Android.bp
, добавьте:
sanitize: { integer_overflow: true, diag: { integer_overflow: true, }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Как и в случае с файлами make, свойство integer_overflow
представляет собой предварительно упакованный набор опций для отдельных дезинфицирующих средств целочисленного переполнения со знаком и без знака со значением BLOCKLIST по умолчанию .
Набор свойств diag
включает режим диагностики для дезинфицирующих средств. Используйте режим диагностики только во время тестирования. Режим диагностики не прерывается при переполнении, что полностью сводит на нет преимущества безопасности, связанные со смягчением последствий в пользовательских сборках. Дополнительные сведения см. в разделе «Устранение неполадок» .
Свойство BLOCKLIST
позволяет указать файл BLOCKLIST, который позволяет разработчикам предотвратить очистку функций и исходных файлов. Дополнительные сведения см. в разделе «Устранение неполадок» .
Чтобы включить дезинфицирующие средства по отдельности, используйте:
sanitize: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"], diag: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow",], }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Поиск неисправностей
Если вы включаете очистку целочисленного переполнения в новых компонентах или полагаетесь на библиотеки платформы, в которых есть очистка целочисленного переполнения, вы можете столкнуться с несколькими проблемами, связанными с неопасными целочисленными переполнениями, вызывающими аварийное завершение работы. Вам следует протестировать компоненты с включенной очисткой, чтобы гарантировать возможность обнаружения неопасных переполнений.
Чтобы найти прерывания, вызванные очисткой в пользовательских сборках, найдите сбои SIGABRT
с сообщениями об аварийном прекращении, указывающими на переполнение, обнаруженное UBSan, например:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/surfaceflinger <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: sub-overflow'
Трассировка стека должна включать функцию, вызывающую прерывание, однако переполнения, возникающие во встроенных функциях, могут быть не очевидны в трассировке стека.
Чтобы упростить определение основной причины, включите диагностику в библиотеке, вызывающую прерывание, и попытайтесь воспроизвести ошибку. Если диагностика включена, процесс не прервется , а продолжит работать. Отсутствие прерывания помогает максимизировать количество безопасных переполнений на конкретном пути выполнения без необходимости перекомпиляции после исправления каждой ошибки. Диагностика выдает сообщение об ошибке, которое включает номер строки и исходный файл, вызывающий прерывание:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Как только проблемная арифметическая операция обнаружена, убедитесь, что переполнение является безопасным и намеренным (например, не имеет последствий для безопасности). Вы можете устранить отмену дезинфицирующего средства следующим образом:
- Рефакторинг кода во избежание переполнения ( пример )
- Переполнение явно через функции __builtin__*_overflow в Clang ( пример )
- Отключение санации в функции путем указания атрибута
no_sanitize
( пример ) - Отключение очистки функции или исходного файла через файл BLOCKLIST ( пример )
Вам следует использовать максимально детальное решение. Например, в большой функции со многими арифметическими операциями и одной операцией переполнения следует выполнить рефакторинг одной операции, а не помещать в BLOCKLIST всю функцию.
Общие закономерности, которые могут привести к доброкачественным переполнениям, включают:
- Неявное приведение типов , при котором происходит беззнаковое переполнение перед приведением к знаковому типу ( пример )
- Удаление связанного списка, которое уменьшает индекс цикла при удалении ( пример )
- Присвоение беззнакового типа значению -1 вместо указания фактического максимального значения ( пример )
- Циклы, которые уменьшают целое число без знака в условии ( пример , пример )
Прежде чем отключать очистку, разработчикам рекомендуется убедиться, что случаи, когда дезинфицирующее средство обнаруживает переполнение, действительно безопасны и не имеют непредвиденных побочных эффектов или последствий для безопасности.
Отключить ИнтСан
Вы можете отключить IntSan с помощью BLOCKLIST или атрибутов функции. Отключайте с осторожностью и только в том случае, если рефакторинг кода необоснован или если возникают проблемы с производительностью.
Дополнительную информацию об отключении IntSan с помощью атрибутов функций и форматировании файлов BLOCKLIST см. в документации по вышестоящему продукту Clang. BLOCKLISTing должен быть ограничен конкретным дезинфицирующим средством, используя имена разделов, указывающие целевое дезинфицирующее средство, чтобы избежать влияния на другие дезинфицирующие средства.
Валидация
В настоящее время не существует теста CTS специально для очистки целочисленного переполнения. Вместо этого убедитесь, что тесты CTS проходят с включенным IntSan или без него, чтобы убедиться, что он не влияет на устройство.
Дезинфекция границ
BoundsSanitizer (BoundSan) добавляет к двоичным файлам инструменты для вставки проверок границ при доступе к массиву. Эти проверки добавляются, если компилятор не может доказать во время компиляции, что доступ будет безопасным, и если размер массива будет известен во время выполнения, чтобы его можно было проверить. Android 10 использует BoundSan в Bluetooth и кодеках. BoundSan предоставляется компилятором и включен по умолчанию в различных компонентах платформы.
Выполнение
BoundSan использует дезинфицирующее средство для границ UBSan . Это смягчение включено на уровне каждого модуля. Это помогает обеспечить безопасность критически важных компонентов Android, и его нельзя отключать.
Мы настоятельно рекомендуем вам включить BoundSan для дополнительных компонентов. Идеальными кандидатами являются привилегированный машинный код или сложный машинный код, который анализирует ненадежный пользовательский ввод. Накладные расходы на производительность, связанные с включением BoundSan, зависят от количества обращений к массиву, безопасность которых не может быть доказана. Ожидайте в среднем небольшой процент накладных расходов и проверьте, является ли производительность проблемой.
Включить BoundSan в файлах чертежей
BoundSan можно включить в файлах чертежей, добавив "bounds"
к свойству санитизации misc_undefined
для двоичных и библиотечных модулей:
sanitize: { misc_undefined: ["bounds"], diag: { misc_undefined: ["bounds"], }, BLOCKLIST: "modulename_BLOCKLIST.txt",
Диагностика
Свойство diag
включает режим диагностики для дезинфицирующих средств. Используйте режим диагностики только во время тестирования. Режим диагностики не прерывается при переполнении, что сводит на нет преимущества безопасности, связанные с устранением последствий, и приводит к увеличению затрат на производительность, поэтому его не рекомендуется использовать для производственных сборок.
ЧЕРНЫЙ СПИСОК
Свойство BLOCKLIST
позволяет указать файл BLOCKLIST, который разработчики могут использовать для предотвращения очистки функций и исходных файлов. Используйте это свойство только в том случае, если производительность вызывает беспокойство и целевые файлы/функции вносят существенный вклад. Вручную проверяйте эти файлы/функции, чтобы гарантировать безопасность доступа к массиву. Дополнительные сведения см. в разделе «Устранение неполадок» .
Включите BoundSan в make-файлах
BoundSan можно включить в make-файлах, добавив "bounds"
к переменной LOCAL_SANITIZE
для бинарных и библиотечных модулей:
LOCAL_SANITIZE := bounds # Optional features LOCAL_SANITIZE_DIAG := bounds LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
LOCAL_SANITIZE
принимает список дезинфицирующих средств, разделенных запятой.
LOCAL_SANITIZE_DIAG
включает режим диагностики. Используйте режим диагностики только во время тестирования. Режим диагностики не прерывается при переполнении, что сводит на нет преимущества безопасности, связанные с устранением последствий, и приводит к более высоким затратам производительности, поэтому его не рекомендуется использовать для производственных сборок.
LOCAL_SANITIZE_BLOCKLIST
позволяет указать файл BLOCKLIST, который позволяет разработчикам предотвращать очистку функций и исходных файлов. Используйте это свойство только в том случае, если производительность вызывает беспокойство и целевые файлы/функции вносят существенный вклад. Вручную проверяйте эти файлы/функции, чтобы гарантировать безопасность доступа к массиву. Дополнительные сведения см. в разделе «Устранение неполадок» .
Отключить BoundSan
Вы можете отключить BoundSan в функциях и исходных файлах с помощью BLOCKLIST или атрибутов функции. Лучше всего оставить BoundSan включенным, поэтому отключайте его только в том случае, если функция или файл создают большие потери производительности, а источник был проверен вручную.
Дополнительную информацию об отключении BoundSan с помощью атрибутов функций и форматировании файлов BLOCKLIST см. в документации Clang LLVM. Охватите BLOCKLISTing конкретным дезинфицирующим средством, используя имена разделов, указывающие целевое дезинфицирующее средство, чтобы избежать влияния на другие дезинфицирующие средства.
Валидация
Специально для BoundSan не существует теста CTS. Вместо этого убедитесь, что тесты CTS проходят с включенным BoundSan или без него, чтобы убедиться, что он не влияет на устройство.
Поиск неисправностей
Тщательно протестируйте компоненты после включения BoundSan, чтобы убедиться, что все ранее необнаруженные внешние доступы устранены.
Ошибки BoundSan можно легко идентифицировать, поскольку они включают в себя следующее сообщение о прекращении захоронения:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/foobar <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: out-of-bounds'
При работе в режиме диагностики исходный файл, номер строки и значение индекса выводятся в logcat
. По умолчанию этот режим не выдает сообщение об отмене. Просмотрите logcat
чтобы проверить наличие ошибок.
external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'