Маркированные указатели

Начиная с Android 11, для 64-разрядных процессов все выделения кучи имеют тег, определенный реализацией, установленный в верхнем байте указателя на устройствах с поддержкой ядра для игнорирования верхнего байта ARM (TBI). Любое приложение, которое изменяет этот тег, завершается, когда тег проверяется во время освобождения. Это необходимо для будущего оборудования с поддержкой расширения тегов памяти ARM (MTE).

Игнорировать верхний байт

Функция игнорирования верхнего байта ARM доступна для 64-битного кода во всем оборудовании Armv8 AArch64. Эта функция означает, что оборудование игнорирует верхний байт указателя при доступе к памяти.

TBI требует совместимого ядра , которое правильно обрабатывает помеченные указатели, передаваемые из пользовательского пространства. Общие ядра Android версии 4.14 (Pixel 4) и выше содержат необходимые исправления TBI .

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

Готовность расширения маркировки памяти

Расширение маркировки памяти (MTE) ARM помогает решить проблемы безопасности памяти. MTE работает путем пометки 56-59-го адресных битов каждого выделения памяти в стеке, куче и глобальных переменных. Аппаратное обеспечение и набор команд автоматически проверяют, используется ли правильный тег при каждом доступе к памяти.

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

Поддержка разработчиков

Если в вашем приложении произошел сбой и вам была предложена эта ссылка, это может означать одно из следующих:

  1. Приложение попыталось освободить указатель, который не был выделен системным распределителем кучи.
  2. Что-то в вашем приложении изменило верхний байт указателя. Верхний байт указателя изменить нельзя, и для решения этой проблемы необходимо изменить код.

Примеры неправильного использования или изменения указателя верхнего байта.

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

Некоторые приложения могут зависеть от библиотек, которые ведут себя неправильно при установке верхнего байта указателя. Мы понимаем, что быстрое устранение этих основных проблем в библиотеках может оказаться нетривиальной задачей. Таким образом, в приложениях, использующих targetSdkLevel < 30 , тегирование указателей не будет включено по умолчанию. Мы также предоставляем аварийный выход для приложений, созданных с targetSdkLevel >= 30 , чтобы облегчить переходный период.

Аварийный люк используется путем добавления следующего в файл AndroidManifest.xml :

  <application android:allowNativeHeapPointerTagging="false">
  ...
  </application>

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