Обнаружено ли переполнение стека аппаратным или программным обеспечением?

26

Является ли задачей программного обеспечения (операционной системы) обнаружение переполнения стека или аппаратное переполнение стека, вызывающее исключение в ЦП?

gilianzz
источник
Я бы сказал, аппаратная, через ошибки MMU на большинстве процессоров. x86 в 32-битном режиме имеет сегментацию в дополнение к разбиению на страницы, и «сегмент стека» ассоциируется, как сегменты Code, Data, Ext ..., с базовым адресом и размером. Любой доступ за пределами этого диапазона вызовет ошибку.
TEMLIB

Ответы:

25

Это может быть программное или аппаратное обеспечение, или и то, и другое.

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

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

+---------------+---------------+---------------+---------------+
| stack                         | unmapped      | other stuff   |
|    ----> direction of growth  |               |               |
+---------------+---------------+---------------+---------------+
^               ^               ^               ^               ^  page boundaries

Таким образом, если программное обеспечение пытается получить доступ к данным за пределами страницы (будь то из-за того, что указатель стека перешел за границы или из-за того, что доступ к массиву выходит за границы и за границы), это вызовет ошибку, получив доступ к не отображенной области , Это происходит только в том случае, если переполнение достаточно мало: если величина переполнения слишком велика, программа может в конечном итоге получить доступ к другим данным на другой стороне промежутка в адресном пространстве.

Недостатками аппаратного подхода является то, что он не является полностью надежным, поскольку переполнение большого объема может не обнаруживаться, и что он не обнаруживает переполнения массива, которые остаются в адресуемом пространстве.

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

Самый безопасный и дешевый способ избежать переполнения стека - это вычислить объем стека, который понадобится программе перед началом его выполнения, путем статического анализа. Однако это не всегда практично: объем стека, необходимый программе, в общем, неразрешим, и зависит от данных, которыми манипулирует программа.

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

Жиль "ТАК - перестань быть злым"
источник
4
Я бы не стал обращаться к массиву за пределами доступа к переполнению стека, даже если массив находится в стеке. Это просто особый случай переполнения буфера.
CodesInChaos
Не выделение элементам основного стека, на которые имеются ссылки относительно не-стека / указателя кадра или непостоянного смещения, позволит избежать традиционных переполнений стека. Использование отдельного стека адресов возврата (или стека разлива RA / регистра, такого как Itanium), по крайней мере, значительно уменьшит возможности программирования, ориентированного на возврат.
Пол А. Клейтон
Доступ вне границ более правильно называется переполнением , а не переполнением.
Бен Фойгт
3
@ awesomebing1 не каждая платформа обнаруживает переполнение стека. Вы можете просто перезаписать все, что находится после стека (аналогично любому другому переполнению буфера).
user253751
1
@CodesInChaos, иногда переполнение буфера в выделенных стеке буферах называется «переполнением стека» (для краткости). Конечно, эта терминология может быть немного запутанной без контекста.
DW