Skip to main content
Removed misleading comment about mmap.
Source Link
Johan Myréen
  • 13.7k
  • 1
  • 37
  • 39

Every process memory region (e.g code, static data, heap, stack, etc.) has boundaries, and a memory access outside of any region, or a write access to a read-only region generates a CPU exception. The kernel maintains these memory regions. An access outside of a region propagates up to user space in the form of a segmentation fault signal.

Not all exceptions are generated by accessing memory outside the regions. An in-region access can also generate an exception. For example, if the page is not mapped to physical memory, the page fault handler handles this transparently to the running process.

The process main stack region initially has only a small number of page frames mapped to it, but grows automatically when more data is pushed to it via the stack pointer. The exception handler checks that the access is still within the region reserved for the stack, and allocates a new page frame if it is. This happens automatically from the point of view of the user level code. (In particular, mmap has nothing to do with this.)

A guard page is placed right after the end of the stack region, to detect an overrun of the stack region. Recently (in 2017) some people realized that a single guard page is not sufficient, because a program can potentially be tricked to decrement the stack pointer by a large amount, which may make the stack pointer point to some other region that permits writes. The "solution" to this problem was to replace the 4 kB guard page with a 1 MB guard region. See this LWN article.

It should be noted that this vulnerability is not entirely trivial to exploit, it requires, for example, that the user can control the amount of memory a program allocates via a call to alloca. Robust programs should check the parameter passed to alloca, especially if it is derived from user input.

Every process memory region (e.g code, static data, heap, stack, etc.) has boundaries, and a memory access outside of any region, or a write access to a read-only region generates a CPU exception. The kernel maintains these memory regions. An access outside of a region propagates up to user space in the form of a segmentation fault signal.

Not all exceptions are generated by accessing memory outside the regions. An in-region access can also generate an exception. For example, if the page is not mapped to physical memory, the page fault handler handles this transparently to the running process.

The process main stack region initially has only a small number of page frames mapped to it, but grows automatically when more data is pushed to it via the stack pointer. The exception handler checks that the access is still within the region reserved for the stack, and allocates a new page frame if it is. This happens automatically from the point of view of the user level code. (In particular, mmap has nothing to do with this.)

A guard page is placed right after the end of the stack region, to detect an overrun of the stack region. Recently (in 2017) some people realized that a single guard page is not sufficient, because a program can potentially be tricked to decrement the stack pointer by a large amount, which may make the stack pointer point to some other region that permits writes. The "solution" to this problem was to replace the 4 kB guard page with a 1 MB guard region. See this LWN article.

It should be noted that this vulnerability is not entirely trivial to exploit, it requires, for example, that the user can control the amount of memory a program allocates via a call to alloca. Robust programs should check the parameter passed to alloca, especially if it is derived from user input.

Every process memory region (e.g code, static data, heap, stack, etc.) has boundaries, and a memory access outside of any region, or a write access to a read-only region generates a CPU exception. The kernel maintains these memory regions. An access outside of a region propagates up to user space in the form of a segmentation fault signal.

Not all exceptions are generated by accessing memory outside the regions. An in-region access can also generate an exception. For example, if the page is not mapped to physical memory, the page fault handler handles this transparently to the running process.

The process main stack region initially has only a small number of page frames mapped to it, but grows automatically when more data is pushed to it via the stack pointer. The exception handler checks that the access is still within the region reserved for the stack, and allocates a new page frame if it is. This happens automatically from the point of view of the user level code.

A guard page is placed right after the end of the stack region, to detect an overrun of the stack region. Recently (in 2017) some people realized that a single guard page is not sufficient, because a program can potentially be tricked to decrement the stack pointer by a large amount, which may make the stack pointer point to some other region that permits writes. The "solution" to this problem was to replace the 4 kB guard page with a 1 MB guard region. See this LWN article.

It should be noted that this vulnerability is not entirely trivial to exploit, it requires, for example, that the user can control the amount of memory a program allocates via a call to alloca. Robust programs should check the parameter passed to alloca, especially if it is derived from user input.

Source Link
Johan Myréen
  • 13.7k
  • 1
  • 37
  • 39

Every process memory region (e.g code, static data, heap, stack, etc.) has boundaries, and a memory access outside of any region, or a write access to a read-only region generates a CPU exception. The kernel maintains these memory regions. An access outside of a region propagates up to user space in the form of a segmentation fault signal.

Not all exceptions are generated by accessing memory outside the regions. An in-region access can also generate an exception. For example, if the page is not mapped to physical memory, the page fault handler handles this transparently to the running process.

The process main stack region initially has only a small number of page frames mapped to it, but grows automatically when more data is pushed to it via the stack pointer. The exception handler checks that the access is still within the region reserved for the stack, and allocates a new page frame if it is. This happens automatically from the point of view of the user level code. (In particular, mmap has nothing to do with this.)

A guard page is placed right after the end of the stack region, to detect an overrun of the stack region. Recently (in 2017) some people realized that a single guard page is not sufficient, because a program can potentially be tricked to decrement the stack pointer by a large amount, which may make the stack pointer point to some other region that permits writes. The "solution" to this problem was to replace the 4 kB guard page with a 1 MB guard region. See this LWN article.

It should be noted that this vulnerability is not entirely trivial to exploit, it requires, for example, that the user can control the amount of memory a program allocates via a call to alloca. Robust programs should check the parameter passed to alloca, especially if it is derived from user input.