Я предполагаю, что есть история, но почему стек растет вниз?
Мне кажется, что переполнение буфера будет намного сложнее использовать, если стек будет расти вверх ...
Я предполагаю, что есть история, но почему стек растет вниз?
Мне кажется, что переполнение буфера будет намного сложнее использовать, если стек будет расти вверх ...
Ответы:
Я полагаю, что это происходит с самых первых дней вычислений, когда память была очень ограничена, и было неразумно предварительно выделять большой кусок памяти для монопольного использования стеком. Таким образом, выделяя кучу памяти от адреса с нуля вверх и стековую память от конца памяти вниз, вы можете иметь кучи и стек совместно в одной и той же области памяти.
Если вам нужно немного больше кучи, вы можете быть осторожны с использованием стека; если вам нужно больше стека, вы можете попытаться освободить кучу памяти. Результатом, конечно, были, в основном, впечатляющие сбои, поскольку стек иногда перезаписывал кучу, и наоборот.
В те времена не было никакого интервала, поэтому не было проблемы использования переполнения буфера. (Или, по крайней мере, в той мере, в которой существовал интервез, все это находилось в пределах объектов повышенной безопасности Министерства обороны США, поэтому не нужно было много думать о возможности злонамеренных данных.)
После этого для большинства архитектур это было вопросом поддержания совместимости с предыдущими версиями той же архитектуры. Вот почему перевернутые стеки все еще с нами сегодня.
память программы традиционно устанавливается как
code
constants
heap (growing up)
...
stack (growing down)
куча и стек могут быть обменены
но переполнение буфера все еще может быть использовано, если стек пошел другим путем
взяв классику strcpyв качестве примера
foo(char* in){
char[100] buff;
strcpy(buff,in);
}
со стековой памятью как
ret foo
arg in
buff array
ret strcpy
buf pointer
in
это будет означать, что когда копирование завершено, адрес возврата для strcpyнаходится после буфера (вместо fooадреса возврата) и может быть перезаписан любым, что находится вin
Некоторое оборудование имеет кучу, начинающуюся с большой памяти, растущую вниз, в то время как стек начинается с маленькой памяти, растущей.
Аппаратура HP PA-RISC, среди прочего, делает это: http://www.embeddedrelated.com/usenet/embedded/show/68749-1.php
Почтенная операционная система Multics работала на оборудовании, на котором (возможно, много) стеки росли: см. Http://www.acsac.org/2002/papers/classic-multics.pdf , конец раздела 2.3.2:
В-третьих, стеки на процессорах Multics росли в положительном направлении, а не в отрицательном направлении. Это означало, что если бы вы на самом деле достигли переполнения буфера, вы бы перезаписывали неиспользуемые стековые фреймы, а не собственный указатель возврата, что значительно усложняло бы использование.
Это довольно интересное утверждение. Не стали ли переполнения буфера такой огромной проблемой только из-за «обычной» схемы процедуры вызова-стека-фрейма? Кроме того, сколько репутации Multics как полностью неуязвимого было просто случайностью аппаратного дизайна?