
Усиленный аллокатор, разработанный для современных систем. Он интегрирован в Bionic libc от Android и может использоваться извне с musl и glibc в качестве динамической библиотеки на других платформах на базе Linux. Со временем он приобретёт большую переносимость и интеграцию.
Это ориентированный на безопасность универсальный аллокатор памяти, предоставляющий API malloc вместе с различными расширениями. Он обеспечивает существенное усиление защиты от уязвимостей повреждения кучи. Ориентированный на безопасность дизайн также приводит к гораздо меньшим накладным расходам на метаданные и потерям памяти из-за фрагментации, чем более традиционный дизайн аллокатора. Он нацелен на достойную общую производительность с акцентом на долгосрочную производительность и использование памяти, а не на микробенчмарки аллокатора. Он обеспечивает масштабируемость за счёт настраиваемого количества полностью независимых арен, при этом внутренняя блокировка внутри арен дополнительно разделена по классам размеров.
В настоящее время этот проект поддерживает Bionic (Android), musl и glibc. В будущем возможна поддержка других не-Linux операционных систем. Для Android существует пользовательская интеграция и другие функции усиления защиты, которые также планируются для musl в будущем. Поддержка glibc будет ограничена заменой реализации malloc, поскольку musl является гораздо более надёжной и чистой базой для построения и может покрыть те же сценарии использования.
Этот аллокатор задуман как преемник предыдущей реализации, основанной на расширении OpenBSD malloc различными дополнительными функциями безопасности. Он по-прежнему в значительной степени основан на дизайне OpenBSD malloc, хотя и не на существующем коде, за исключением повторного использования реализации хеш-таблицы. Основные различия в дизайне заключаются в том, что он сосредоточен исключительно на усилении защиты, а не на поиске ошибок, использует более мелкозернистые классы размеров вместе с размерами slab, превышающими 4k, для уменьшения внутренней фрагментации, не полагается на наличие в ядре мелкозернистой рандомизации mmap и нацелен только на 64-битные системы, чтобы агрессивно использовать большое адресное пространство. Существует множество более мелких различий в подходе к реализации. Он включает предыдущие расширения, сделанные для OpenBSD malloc, включая добавление отступов к выделениям для канареек (отличающихся от текущих канареек OpenBSD malloc), обнаружение записи после освобождения, привязанное к существующей очистке при освобождении, очереди наряду с существующими рандомизированными массивами для карантина выделений и надлежащее обнаружение двойного освобождения для карантинированных выделений. Области памяти для каждого класса размеров с собственными случайными базами были вдохновлены разделением по размеру и типу в PartitionAlloc. Запланированные изменения в OpenBSD malloc оказались слишком обширными и инвазивными, поэтому этот проект был начат как новая реализация, лучше способная достичь поставленных целей. Для 32-битных систем вместо этого можно использовать порт OpenBSD malloc с небольшими расширениями, поскольку этот аллокатор принципиально не поддерживает такую среду.
Debian stable (в настоящее время Debian 13) определяет наиболее древний набор поддерживаемых зависимостей:
Для Android поддерживаются ветки Linux GKI 6.1, 6.6 и 6.12.
Однако настоятельно рекомендуется использовать более свежие выпуски. Более старые версии зависимостей могут быть совместимы в данный момент, но не тестируются и явно не будут поддерживаться.
Для внешней замены malloc с musl требуется musl 1.1.20. Однако в будущем появится кастомная интеграция, обеспечивающая лучшую производительность, а также другие меры усиления для реализации стандартной библиотеки C.
Для Android будет поддерживаться только текущее поколение активно
разрабатываемой ветки сопровождения Android Open Source Project,
что в настоящее время означает android17-release.
Скрипт preload.sh можно использовать для тестирования с динамически
связанными исполняемыми файлами, использующими glibc или musl:
./preload.sh krita --new-image RGBA,U8,500,500
Может потребоваться существенно увеличить sysctl vm.max_map_count, чтобы
вместить большое количество отображений, вызванных guard-слэбами и крупными
областями защиты выделений. Количество отображений также можно радикально
сократить путём значительного увеличения CONFIG_GUARD_SLABS_INTERVAL, но эта
функция имеет низкую стоимость по производительности и использованию памяти, поэтому
это не рекомендуется.
Она может обеспечить немного лучшую производительность при интеграции в стандартную библиотеку C, и есть другие возможности для аналогичного усиления в реализациях стандартной библиотеки C и динамического компоновщика. Например, можно реализовать область библиотеки для обеспечения аналогичной изоляции динамических библиотек, какую этот аллокатор обеспечивает для различных классов размеров. Предполагается, что это будет предложено в составе усиленных вариантов стандартных библиотек C Bionic и musl.
Предоставляется набор простых автоматизированных тестов, которые можно запустить командой make следующим образом:
make test
Требуется OpenSSH 8.1 или выше, чтобы разрешить системные вызовы mprotect PROT_READ|PROT_WRITE
в фильтре seccomp-bpf вместо завершения процесса.
В GrapheneOS hardened_malloc интегрирован в стандартную библиотеку C как стандартная реализация malloc. Другие операционные системы на базе Android могут повторно использовать код интеграции для его предоставления. При желании jemalloc можно оставить в качестве опции конфигурации времени выполнения, используя hardened_malloc только условно, чтобы дать пользователям выбор между производительностью и безопасностью. Однако это снижает безопасность для моделей угроз, где постоянное состояние не является доверенным, то есть проверенной загрузки и аттестации (см. родственный проект аттестации).
Обязательно также существенно увеличьте vm.max_map_count, чтобы вместить очень
большое количество guard-страниц, создаваемых hardened_malloc. Это можно сделать в
init.rc (system/core/rootdir/init.rc) рядом с другой конфигурацией виртуальной памяти:
write /proc/sys/vm/max_map_count 1048576
Это не нужно, если вы установите CONFIG_GUARD_SLABS_INTERVAL в очень большое
значение в конфигурации сборки.