Я предполагаю, что есть история, но почему стек растет вниз?
Мне кажется, что переполнение буфера будет намного сложнее использовать, если стек будет расти вверх ...
Я предполагаю, что есть история, но почему стек растет вниз?
Мне кажется, что переполнение буфера будет намного сложнее использовать, если стек будет расти вверх ...
Ответы:
Я полагаю, что это происходит с самых первых дней вычислений, когда память была очень ограничена, и было неразумно предварительно выделять большой кусок памяти для монопольного использования стеком. Таким образом, выделяя кучу памяти от адреса с нуля вверх и стековую память от конца памяти вниз, вы можете иметь кучи и стек совместно в одной и той же области памяти.
Если вам нужно немного больше кучи, вы можете быть осторожны с использованием стека; если вам нужно больше стека, вы можете попытаться освободить кучу памяти. Результатом, конечно, были, в основном, впечатляющие сбои, поскольку стек иногда перезаписывал кучу, и наоборот.
В те времена не было никакого интервала, поэтому не было проблемы использования переполнения буфера. (Или, по крайней мере, в той мере, в которой существовал интервез, все это находилось в пределах объектов повышенной безопасности Министерства обороны США, поэтому не нужно было много думать о возможности злонамеренных данных.)
После этого для большинства архитектур это было вопросом поддержания совместимости с предыдущими версиями той же архитектуры. Вот почему перевернутые стеки все еще с нами сегодня.
память программы традиционно устанавливается как
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 как полностью неуязвимого было просто случайностью аппаратного дизайна?