NX-бит: не только защита, но и причина загадочных сбоев
The NX bit is not just about security
В гостевом посте Соня рассказывает, как при разработке гипервизора для ARM64 на MediaTek MT6735 столкнулась с необъяснимыми зависаниями при перехвате регистра CTR_EL0. Методом бинарного биссектрирования она выяснила, что проблема возникает только при динамическом вызове функции через blr, а не при статическом bl. Разгадка оказалась в спекулятивном исполнении: предсказатель переходов мог угадать адрес 0x0, что приводило к сбою. Это демонстрирует, что NX-бит, запрещающий исполнение кода в неисполняемых областях, защищает не только от атак, но и от подобных микроархитектурных ошибок.
Как динамические вызовы отличаются от статических? Динамические используют предсказание переходов, статические знают, куда ведут, заранее и не могут ошибиться в предсказании.
- repiret
"Спекулятивная выборка инструкций из памяти устройства приводит к сбою устройства" — в моём списке любимых багов. Я столкнулся с этим на Cortex-M4 без MPU, так что не мог даже исправить атрибуты памяти, единственным решением было перекроить скомпилированный код, чтобы предотвратить спекулятивную выборку.
Безумие, что Armv8/9-A допускает спекулятивную выборку инструкций из памяти устройства. Настолько безумно, что мне пришлось искать это, чтобы поверить:
"Аппаратное обеспечение не предотвращает спекулятивную выборку инструкций из области памяти с любыми атрибутами Device, если эта область также не помечена как execute-never для всех уровней исключений." — ARM DDI 0487K.a § B2.15.2
Спецификация Armv7-M менее ясна. В ней говорится: "Архитектура не допускает спекулятивных обращений к памяти, помеченной как Device", в отличие от Armv8/9-A, где аналогичное утверждение уточняется "обращения к данным". Но затем говорится: "Для обеспечения корректности места, чувствительные к чтению, должны быть помечены как неисполняемые". (Это всё из ARM DDI 0403E.e § A3.5.7)
У меня нет под рукой более старой версии v7-A, чтобы сравнить, что там сказано.
- asveikau
В продолжение темы, что дело не только в безопасности: если у вас есть баг вроде use-after-free, и он случайно затрагивает указатель на функцию, бит NX может гарантировать, что при переходе по этому указателю вы получите чистое исключение как можно ближе к точке сбоя. Если бы он вслепую исполнял устаревшие байты как код, возможно, сбой и стек-трейс выглядели бы не так красиво.
Но и многие подобные баги корректности также являются проблемами безопасности.
- anyfoo
В наши дни считается дурным тоном отображать что-либо по адресу 0... теперь вы знаете одну из причин!
В известном мне случае с тождественным отображением адресного пространства 1:1 физическое адресное пространство на самом деле тоже не содержит ничего по адресу 0, так что отображать его всё равно не нужно.
- mubbicles
Я оценил эту статью. Я спрашивал нашего специалиста по CSP о разнице, но это помогает мне лучше понять разницу между device и ns. Также ценю, что это не выглядит написанным ИИ.
- eqvinox
Честно говоря, это похоже на ошибку проектирования в ARM. Где вообще имеет смысл, чтобы память Device не допускала предварительную выборку данных, но допускала предварительную выборку инструкций? По моему мнению, она должна запрещать любую предварительную выборку...