Following my question yesterday, I tried to learn a bit more about the architecture of call stacks. Online and SO searches have not yielded the answer I’m looking for, which could be because I don’t know precisely which keywords to use. Anyway, I’m sure someone here can help me…
First, lets start with an excerpt from Wikipedia’s entry for stack buffer overflow:
In software, a stack buffer overflow occurs when a program writes to a memory address on the program’s call stack outside of the intended data structure; usually a fixed length buffer.
A colleague told me he remembered learning that, on Linux, the stack is at the very end of a process’ virtual memory and grows backwards as needed — hence it would not be a ‘fixed length buffer’. However I have not been able to confirm that. So my questions are:
- On Windows and Linux is the call
stack always a fixed size buffer? If
not, how does it grow? How does it
manage sharing the virtual memory
with the heap? - Does the
architecture of the stack depends on
the compiled language used? On the
OS? On the hardware? - Is the size
of the stack determined at
compile-time or can it be changed a
posteriori? - How and where are
individual thread’s call stacks
allocated?
Stack Buffer Overflow
A stack buffer overflow is when a program accidentally or maliciously writes outside the extents of a particular data item on the stack, such as a c-string. This has the effect of modifying the values of nearby control or data structures on the stack (not the heap), which can cause undesireable program behaviour such as crashes, bugs or changing control flow.
This does not generally refer to writing outside the extent of the stack itself, which is often protected by guard pages to prevent accidental over- or under-run.
The Call Stack on Linux
The call stack is fixed size, the actual stack itself grows and shrinks as requires within this limit.
The heap and the stack do not overlap or share memory – they are typically managed in different areas of the virtual address space.
The size of the process’s main stack is determined by the environment that exists at the point the program is run. For c functions to set this, see
man 3 ulimitand to view/set it from bash, see,ulimit -sfor details.If you create your own threads you can assume responsibility for creating their stacks (see
man pthread_attr), you can either use the system recommended size or set your own.