What is the difference between a segmentation fault and a stack overflow? - c

For example when we call say, a recursive function, the successive calls are stored in the stack. However, due to an error if it goes on infinitely the error is 'Segmentation fault' (as seen on GCC).
Shouldn't it have been 'stack-overflow'? What then is the basic difference between the two?
Btw, an explanation would be more helpful than wikipedia links (gone through that, but no answer to specific query).

Stack overflow is [a] cause, segmentation fault is the result.
At least on x86 and ARM, the "stack" is a piece of memory reserved for placing local variables and return addresses of function calls. When the stack is exhausted, the memory outside of the reserved area will be accessed. But the app did not ask the kernel for this memory, thus a SegFault will be generated for memory protection.

Modern processors use memory managers to protect processes from each other. The x86 memory manager has many legacy features, one of which is segmentation. Segmentation is meant to keep programs from manipulating memory in certain ways. For instance, one segment might be marked read-only and the code would be put there, while another segment is read/write and that's where your data goes.
During a stack overflow, you exhaust all of the space allocated to one of your segments, and then your program starts writing into segments that the memory manager does not permit, and then you get a segmentation fault.

A stack overflow can manifest as either an explicit stack overflow exception (depending on the compiler and architecture) or as a segmentation fault, i.e., invalid memory access. Ultimately, a stack overflow is the result of running out of stack space, and one possible result of running out of stack space is reading or writing to memory that you shouldn't access. Hence, on many architectures, the result of a stack overflow is a memory access error.

The call stack is being overflowed, however the result of the overflowing is that eventually call-related values are pushed into memory that is not part of the stack and then - SIGSEGV!

Related

Is buffer overflow the only possible bug associated with program stack?

Is buffer overflow the only possible bug associated with C/C++ program stack? are there any other bugs which can happen at program stack in a single/multi threaded C/C++ program.
I was reading this paper (Learning from Mistakes — A Comprehensive Study on Real World Concurrency Bug Characteristics) on concurrency bugs, and started thinking that such concurrency bugs do not happen at stack as it is private to threads.
Thanks
You can attempt to use too much stack, typically resulting in a segmentation fault (a report by the hardware that the program has attempted to access memory that is not mapped or not mapped for the type of access attempted and that the operating system does not handle by changing the memory mapping to provide access).
You can use pointers or array indices incorrectly (not just buffer overflows but “underflows” going in the other direction or other incorrect address calculations), corrupting the stack, which can alter program execution in a variety of ways, causing transfer of program control to undesired locations or corrupting data and causing undesired computations.

Is putting an array on the heap rather than the stack, going to remove possibilities of segmentation faults?

That is my question. Say my array is size 10, and I get a segmentation fault when I loop through and fill the array to 13, because I corrupted some important information on the stack. If I stuck it on the heap instead, am I immune to segmentation faults? This is more of a conceptual question.
No. If you overrun the allocated space, you are using memory that does not belong to the application, or which belongs to some other part of the application.
What then happens is undefined. I would be surprised in either case if overrunning by just three bytes directly caused a segmentation fault - the page granularity is not that small. Seg-faults are a function of the processor and operating system not the C language, and occur when you access memory not allocated to the process.
In the case of a stack buffer overrun, you will most likely corrupt some adjacent data in the current or calling function, if a seg-fault occurs it will be due to acting upon the corrupted data, such as popping an invalid return address to the program-counter for example, rather than the overrun itself.
Similarly if you overrun the heap allocation, the result depends on what you are corrupting and how that is subsequently used. Heap corruption is particularly insidious, because the results of the error may remain undetected (latent), or result in failure long after the actual error in some unrelated area of the code - typically when you attempt to free or allocate some other allocation where the heap structures have been destroyed. The memory you have corrupted may be part of some other existing allocation, and the error may manifest itself only when that corrupted data is utilised.
The error you observe is entirely non-deterministic - an immediate seg-fault is perhaps unlikely in the scenario you have described, but would in fact be the best you could hope for, since all other possible manifestations of failure are particularly difficult to debug. A failure from a stack data overrun is likely to be more localised - typically you will see corrupted data within the function, or the function will fail on return, whereas a heap error is often less immediately obvious because the data you are corrupting can be associated with any code withing your application. If that code does not run, or runs infrequently, you may never observe any failure,
The "solution" to your problem is not to write code that overruns - it is always and error, and using a different type of memory allocation is not going to save you from that. To use a coding practice that simply "hides" bugs or makes them less apparent or deterministic is not a good strategy.

the difference between segment fault and Stack smashing detected

I have experienced two kind of error,one is segmentation fault, another is Stack smashing detected. I want to know what different between them and the different reasons caused them.
This is typically Undefined behavior.
Segmentation fault is typically when your process is accessing memory location to which it doesn't have permission to access, or that location does not exist.
Stack smashing is an alert (generated by gcc for instance) that warns about an access out of bounds, for instance, on the stack. Typically that happens when the stack is written to where it shouldn't, like a local array written to at an index out of bounds.
Stack overflow is a kind of "stack smashing" that may also trigger this alert. Stack overflow usually happens when the memory allocated for the stack is not large enough to hold functions local variables, return addresses... Typically happens in recursive functions going too deeply (too much accumulation of return addresses and local data). Or if the local variables take too much space in the stack (like huge arrays).
There is a problem in your code that produces undefined behavior. Maybe you could share it with us so that we can help you.
Check in particular:
Out of array bounds accesses
NULL pointers
The size of local variables too important ; these variables should either be stored in the heap, or be dynamically allocated (malloc() ...).
Segmentation fault is a fault raised by hardware with memory protection, notifying an operating system (OS) about a memory access violation. Stack smashing is reported when there is overflow of data in your program's call stack. Generally program's call stack is of fixed length.
stack overflow and stack smashing both problems are related to faulty code or value found in the variables.
For example when a loop run as that it run over extras index of the array and
overwrite the value of another variable of the code then , it become problem
to the function prolog and epilog to continue to next function hence the current function become unable to return to calle function because overrun of llop has just overwrite the return address of calle instruction and hence EIP pointing to somewhere it not allowed to fetch instruction .All codes into OS are run in memory protection schems , hence you get stack overrun or stack smashing .
Segmentation fault is problems is normal situation when dealing with array and pointer in Linux OS .
Try this http://www.drdobbs.com/security/anatomy-of-a-stack-smashing-attack-and-h/240001832
Both are memory access violation.
Segmentation fault is more general, means you are accessing something you are not allowed to.
stack smashing is more specific, means something wrong in your stack.
Actually, stack smashing can cause segmentation fault.
you can refer to:
https://en.wikipedia.org/wiki/Segmentation_fault
or
Stack smashing detected

Is the heartbleed bug a manifestation of the classic buffer overflow exploit in C?

In one of our first CS lectures on security we were walked through C's issue with not checking alleged buffer lengths and some examples of the different ways in which this vulnerability could be exploited.
In this case, it looks like it was a case of a malicious read operation, where the application just read out however many bytes of memory
Am I correct in asserting that the Heartbleed bug is a manifestation of the C buffer length checking issue?
Why didn't the malicious use cause a segmentation fault when it tried to read another application's memory?
Would simply zero-ing the memory before writing to it (and then subsequently reading from it) have caused a segmentation fault? Or does this vary between operating systems? Or between some other environmental factor?
Apparently exploitations of the bug cannot be identified. Is that because the heartbeat function does not log when called? Otherwise surely any request for a ~64k string is likely to be malicious?
Am I correct in asserting that the Heartbleed bug is a manifestation of the C buffer length checking issue?
Yes.
Is the heartbleed bug a manifestation of the classic buffer overflow exploit in C?
No. The "classic" buffer overflow is one where you write more data into a stack-allocated buffer than it can hold, where the data written is provided by the hostile agent. The hostile data overflows the buffer and overwrites the return address of the current method. When the method ends it then returns to an address containing code of the attacker's choice and starts executing it.
The heartbleed defect by contrast does not overwrite a buffer and does not execute arbitrary code, it just reads out of bounds in code that is highly likely to have sensitive data nearby in memory.
Why didn't the malicious use cause a segmentation fault when it tried to read another application's memory?
It did not try to read another application's memory. The exploit reads memory of the current process, not another process.
Why didn't the malicious use cause a segmentation fault when it tried to read memory out of bounds of the buffer?
This is a duplicate of this question:
Why does this not give a segmentation violation fault?
A segmentation fault means that you touched a page that the operating system memory manager has not allocated to you. The bug here is that you touched data on a valid page that the heap manager has not allocated to you. As long as the page is valid, you won't get a segfault. Typically the heap manager asks the OS for a big hunk of memory, and then divides that up amongst different allocations. All those allocations are then on valid pages of memory as far as the operating system is concerned.
Dereferencing null is a segfault simply because the operating system never makes the page that contains the zero pointer a valid page.
More generally: the compiler and runtime are not required to ensure that undefined behaviour results in a segfault; UB can result in any behaviour whatsoever, and that includes doing nothing. For more thoughts on this matter see:
Can a local variable's memory be accessed outside its scope?
For both me complaining that UB should always be the equivalent of a segfault in security-critical code, as well as some pointers to a discussion on static analysis of the vulnerability, see today's blog article:
http://ericlippert.com/2014/04/15/heartbleed-and-static-analysis/
Would simply zero-ing the memory before writing to it (and then subsequently reading from it) have caused a segmentation fault?
Unlikely. If reading out of bounds doesn't cause a segfault then writing out of bounds is unlikely to. It is possible that a page of memory is read-only, but in this case it seems unlikely.
Of course, the later consequences of zeroing out all kinds of memory that you should not are seg faults all over the show. If there's a pointer in that zeroed out memory that you later dereference, that's dereferencing null which will produce a segfault.
does this vary between operating systems?
The question is vague. Let me rephrase it.
Do different operating systems and different C/C++ runtime libraries provide differing strategies for allocating virtual memory, allocating heap memory, and identifying when memory access goes out of bounds?
Yes; different things are different.
Or between some other environmental factor?
Such as?
Apparently exploitations of the bug cannot be identified. Is that because the heartbeat function does not log when called?
Correct.
surely any request for a ~64k string is likely to be malicious?
I'm not following your train of thought. What makes the request likely malicious is a mismatch between bytes sent and bytes requested to be echoed, not the size of the data asked to be echoed.
A segmentation fault does not occur because the data accessed is that immediately adjacent to the data requested, and is generally within the memory of the same process. It might cause an exception if the request were sufficiently large I suppose, but doing that is not in the exploiter's interest, since crashing the process would prevent them obtaining the data.
For a clear explanation, this XKCD comic is hard to better:

stack pointer vs application

Most architectures have a memory map where the user application grows towards
lower memory where the stack grows to the opposite direction. I am wondering what
is happening when I write such a big C-program that all the space for the application
and the is taken away, ie, that stack pointer and application try to write to the same
region in memory? I assume in C something like a segmentation fault occurs? Is there
any processor support that tries to avoid such a problem from happening?
Thanks
No, in C you can get out of memory, which you only notice directly if you actually check the return value of malloc et al. If not, you probably get to dereference a null pointer somewhere, making your app crash. But possibly there may be no immediate visible signs, only your memory gets silently corrupted. Since the memory space for the application is managed by the app itself, the processor/OS can't detect such errors. In modern OSs memory space of the OS itself and of other apps is protected from your app, so if you accidentally try to write to memory outside your own memory space, you are likely to get segmentation fault. But inside your own memory space, it is up to yourself to protect your memory.
The stack pointer is limited. Once it tries to go further than allowed, you typically get a StackOverflow exception or interrupt, leading to program termination. This most commonly happens with runaway recursive functions.
Similarly, space for the stack is reserved, and not accessible to the heap allocator. When you try to do a heap allocation (malloc or new) without enough space, the allocator will typically return NULL or throw an OutOfMemory exception.
I disagree with the answer that says "there will be no immediate visible signs, only your memory gets silently corrupted."
You'll either get a StackOverflow or OutOfMemory, depending on which resource was exhausted first.
Abelenky is correct, modern architectures will trap the stack growing past some limit much smaller than all available address space (this is easy to test with a simple recursive function)
Also, "App grows down, stack grows up" doesn't really describe the memory mapping of multithreaded systems anyway, each thread has it's own stack, which has a pre-set maximium size, and the heap is one or more seperately mapped areas of address space.
The easiest way to figure this stuff out is to attach a debugger to a simple test program; you can see the memory regions used by your process in any decent one. be sure to look where your libraries and code are loaded, as well as more than one thread worth of stack.

Resources