Очистка целочисленного переполнения

Непреднамеренное целочисленное переполнение может привести к повреждению памяти или раскрытию информации в переменных, связанных с доступом к памяти или выделением памяти. Чтобы бороться с этим, мы добавили средства Clang UndefinedBehaviorSanitizer (UBSan) со знаковыми и беззнаковыми целыми числами, чтобы укрепить структуру мультимедиа в 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_BLACKLIST := modulename_blacklist.txt
  • LOCAL_SANITIZE принимает список дезинфицирующих средств, разделенных запятыми, а integer_overflow представляет собой предварительно упакованный набор параметров для отдельных целочисленных дезинфицирующих средств переполнения со знаком и без знака с черным списком по умолчанию .
  • LOCAL_SANITIZE_DIAG включает режим диагностики для дезинфицирующих средств. Используйте режим диагностики только во время тестирования, так как он не будет прерываться при переполнении, что полностью сводит на нет преимущество защиты от смягчения последствий. Дополнительные сведения см. в разделе Устранение неполадок .
  • LOCAL_SANITIZE_BLACKLIST позволяет указать файл черного списка, чтобы предотвратить очистку функций и исходных файлов. Дополнительные сведения см. в разделе Устранение неполадок .

Если вам нужен более детальный контроль, включите дезинфицирующие средства по отдельности, используя один или оба флага:

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,
      },
      blacklist: "modulename_blacklist.txt",
   },

Как и в случае с make-файлами, свойство integer_overflow представляет собой предварительно упакованный набор параметров для отдельных средств очистки целочисленного переполнения со знаком и без знака с черным списком по умолчанию .

Набор свойств diag включает режим диагностики для дезинфицирующих средств. Используйте режим диагностики только во время тестирования. Режим диагностики не прерывается при переполнении, что полностью сводит на нет преимущество защиты от снижения риска в пользовательских сборках. Дополнительные сведения см. в разделе Устранение неполадок .

Свойство blacklist позволяет указать файл черного списка, который позволяет разработчикам предотвращать очистку функций и исходных файлов. Дополнительные сведения см. в разделе Устранение неполадок .

Чтобы включить дезинфицирующие средства по отдельности, используйте:

   sanitize: {
      misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
      diag: {
          misc_undefined: ["signed-integer-overflow",
                           "unsigned-integer-overflow",],
      },
      blacklist: "modulename_blacklist.txt",
   },

Исправление проблем

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

Чтобы найти прерывания, вызванные очисткой в ​​пользовательских сборках, найдите сбои SIGABRT с сообщениями Abort, указывающими на переполнение, обнаруженное 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')

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

  • Рефакторинг кода, чтобы избежать переполнения ( пример )
  • Явное переполнение через функции Clang __builtin_*_overflow ( пример )
  • Отключение санации в функции указанием атрибута no_sanitize ( пример )
  • Отключение очистки функции или исходного файла через файл черного списка ( пример )

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

Общие закономерности, которые могут привести к доброкачественным переполнениям, включают:

  • Неявные приведения , при которых происходит переполнение без знака перед приведением к типу со знаком ( пример )
  • Удаление связанного списка, которое уменьшает индекс цикла при удалении ( пример )
  • Присвоение беззнакового типа -1 вместо указания фактического максимального значения ( пример )
  • Циклы, которые уменьшают целое число без знака в условии ( пример , пример )

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

Отключение IntSan

Вы можете отключить IntSan с помощью черных списков или атрибутов функций. Отключайте экономно и только тогда, когда рефакторинг кода в противном случае нецелесообразен или если есть проблемы с производительностью.

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

Проверка

В настоящее время не существует теста CTS специально для очистки целочисленного переполнения. Вместо этого убедитесь, что тесты CTS проходят с включенным IntSan или без него, чтобы убедиться, что это не влияет на устройство.