Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
423 views
in Technique[技术] by (71.8m points)

segmentation fault - Understanding stack overflow handling in C

I was curious about how to catch stack overflows in C and stumble across the GNU libsigseg library.

This library can catch stack overflows on a lot of platforms and provides an implementation example.
In order to install a stack overflow listener with this library, one must first reserve some space for an alternate stack. From what I understood, this alternate stack is used to run the listener because the real stack is unusable.

The alternate stack is reserved in altstack.h (line 40), and looks like this:

[][      ][             ][      ]
|    |           |          |
|    |           |          crumple_zone (8 KiB)
|    |           usable_space (16 KiB)
|    crumple_zone (8 KiB)
offset (31 B)

The usable space is what is actually used and the crumple zones are here to prevent an overflow on the alternate stack: If it overflows, it does it into allocated space, preventing a segfault, and one might have time to detect it.

But,

  1. I don't understand why there is a crumple zone before AND after the stack; The stack grows in only one direction. Is it because some platforms have stack that grows in one direction, and other platforms in the other direction?
  2. I don't understand why there is an offset.

Here is the explanation given by the author:

glibc says: Users should use SIGSTKSZ as the size of user-supplied buffers. We want to detect stack overflow of the alternate stack in a nicer manner than just crashing, so we overallocate in comparison to what we hand libsigsegv. Also, we intentionally hand an unaligned pointer, to ensure the alternate stack still ends up aligned.

The last statement lost me a bit: "... we intentionally hand an unaligned pointer, to ensure the alternate stack still ends up aligned". How can the stack ends up aligned if we make so it's unaligned?

question from:https://stackoverflow.com/questions/65865908/understanding-stack-overflow-handling-in-c

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't understand why there is a crumple zone before AND after the stack;

The stack is declared as a global char mystack_storage[...].
Assuming that stack grows down, you need the crumple zone at the low end of storage to detect overflow of the alternate stack itself.

Question: what follows the mystack_storage[] array?
Answer: you don't know.

What if there is another array immediately after, and what if that array is written out of bounds (e.g. with something like other_array[-20] = 'a';)?

To detect such underflow, you need the crumple zone on the other end as well.

How can the stack ends up aligned if we make so it's unaligned?

The mystack pointer is intentionally misaligned. If it was used directly as the alternate stack, it would violate stack alignment requirements on many platforms, and would most likely cause a crash.

To prevent this, the library must not be using mystack directly, but aligning it somewhere else.

The code you pointed to is intended to test that the other code is working properly.

Update:

I still don't understand the offset. Why the mystack pointer would violate stack alignment requirement if used without offset?

Without offset, mystack's alignment is unknown. It may happen to be aligned on 16-byte, 8-byte, or even 1-byte boundary.

With the offset, it is guaranteed to be misaligned (aligned on 1-byte boundary).

Why it isn't the other way around: by adding the offset it's intentionally misaligned and violate stack alignment requirement.

Yes, the pointer is intentionally misaligned.

The point was: the code which actually uses mystack (that code is elsewhere, I didn't look for it), is already prepared for dealing with misaligned mystack, by properly aligning it (let's call that "alignment code"). And the code you pointed to is intended to exercise that other "alignment code".

Now, where is that "alignment code"?

I thought it's somewhere else in the library, but I was wrong. The misaligned mystack pointer is used directly here.

So who is doing the required alignment then? The kernel does!

From man sigaltstack:

 ss.ss_sp
    This field specifies the starting address of the stack.  When a signal
    handler is invoked on the alternate stack, the kernel automatically
    aligns the address given in ss.ss_sp to a suitable address boundary
    for the underlying hardware architecture.

So the "other code" that the misalignment of mystack is intended to exercise is not in the library, it's in the kernel.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...