Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Provoke stack underflow in C

I would like to provoke a stack underflow in a C function to test security measures in my system. I could do this using inline assembler. But C would be more portable. However I can not think of a way to provoke a stack underflow using C since stack memory is safely handled by the language in that regard.

So, is there a way to provoke a stack underflow using C (without using inline assembler)?

As stated in the comments: Stack underflow means having the stack pointer to point to an address below the beginning of the stack ("below" for architectures where the stack grows from low to high).

like image 861
Silicomancer Avatar asked Nov 07 '17 09:11

Silicomancer


People also ask

What is stack underflow in C?

As stated in the comments: Stack underflow means having the stack pointer to point to an address below the beginning of the stack ("below" for architectures where the stack grows from low to high).

What is stack underflow with example?

Stack Underflow & Overflow Stack underflow happens when we try to pop (remove) an item from the stack, when nothing is actually there to remove. This will raise an alarm of sorts in the computer because we told it to do something that cannot be done.

What is stack underflow?

An error condition that occurs when an item is called for from the stack, but the stack is empty.

What is overflow and underflow in C programming?

Integer Overflow occurs when we attempt to store a value greater than the data type's largest value. Similarly, Integer Underflow occurs when we attempt to store a value that is less than the least value of the data type. We can detect these overflows and underflows either mathematically (or) programmatically.


2 Answers

There's a good reason why it's hard to provoke a stack underflow in C.The reason is that standards compliant C does not have a stack.

Have a read of the C11 standard, you'll find out that it talks about scopes but it does not talk about stacks. The reason for this is that the standard tries, as far as possible, to avoid forcing any design decisions on implementations. You may be able to find a way to cause stack underflow in pure C for a particular implementation but it will rely on undefined behaviour or implementation specific extensions and won't be portable.

like image 110
JeremyP Avatar answered Oct 14 '22 08:10

JeremyP


You can't do this in C, simply because C leaves stack handling to the implementation (compiler). Similarly, you cannot write a bug in C where you push something on the stack but forget to pop it, or vice versa.

Therefore, it is impossible to produce a "stack underflow" in pure C. You cannot pop from the stack in C, nor can you set the stack pointer from C. The concept of a stack is something on an even lower level than the C language. In order to directly access and control the stack pointer, you must write assembler.


What you can do in C is to purposely write out of bounds of the stack. Suppose we know that the stack starts at 0x1000 and grows upwards. Then we can do this:

volatile uint8_t* const STACK_BEGIN = (volatile uint8_t*)0x1000;  for(volatile uint8_t* p = STACK_BEGIN; p<STACK_BEGIN+n; p++) {   *p = garbage; // write outside the stack area, at whatever memory comes next } 

Why you would need to test this in a pure C program that doesn't use assembler, I have no idea.


In case someone incorrectly got the idea that the above code invokes undefined behavior, this is what the C standard actually says, normative text C11 6.5.3.2/4 (emphasis mine):

The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined 102)

The question is then what's the definition of an "invalid value", as this is no formal term defined by the standard. Foot note 102 (informative, not normative) provides some examples:

Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.

In the above example we are clearly not dealing with a null pointer, nor with an object that has passed the end of its lifetime. The code may indeed cause a misaligned access - whether this is an issue or not is determined by the implementation, not by the C standard.

And the final case of "invalid value" would be an address that is not supported by the specific system. This is obviously not something that the C standard mentions, because memory layouts of specific systems are not coverted by the C standard.

like image 30
Lundin Avatar answered Oct 14 '22 06:10

Lundin