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

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

Старший байт игнорировать

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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