Jan 27, 2019

[stack guard-page] Preventing stack guard-page hopping reading notes

Reference:
Preventing stack guard-page hopping

The stack area in a running process is, on most architectures,
placed at a relatively high virtual address; it grows downward as the process's stack needs increase.

A virtual-memory region that automatically grows as a result of page faults brings some inherent risks; in particular, it must be prevented from growing into another memory region placed below it.

In a single-threaded process, the address space reserved for the stack can be large and difficult to overflow.

Multi-threaded processes contain multiple stacks; those stacks are smaller and are likely to be placed between other virtual-memory areas of interest.

An accidental overflow could corrupt the area located below a stack; a deliberate overflow, if it can be arranged, could be used to compromise the system.

The kernel has long placed a guard page — a page that is inaccessible to the owning process — below each stack area.

A process that wanders off the bottom of a stack into the guard page will be rewarded with a segmentation-fault signal, which is likely to bring about the process's untimely end.

The world has generally assumed that the guard page is sufficient to protect against stack overflows but, it seems, the world was mistaken.

The fundamental problem with the guard page is that it is too small.
There are a number of ways in which the stack can be expanded by more than one page at a time.

  • make large alloca() calls
  • with large variable-length arrays or other large on-stack data structures.


It turns out to be relatively easy for an attacker to cause a program to generate stack addresses that hop over the guard page, stomping on whatever memory is placed below the stack.

Partial solution: extend the guard page size: 4KB -> 1MB
Configurable at boot time:
stack_guard_gap

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.