可执行堆栈如何在 x86 保护模式下工作?

How did executable stacks work in x86 protected mode?

AMD64 开发人员手册第 2 卷(系统编程)的第 4.7.2 节描述了传统模式下的代码段描述符:

Code segments establish the processor operating mode and execution privilege- level. The segments generally contain only instructions and are execute-only, or execute and read- only. Software cannot write into a segment whose selector references a code-segment descriptor.

如果代码段是唯一的可执行段,并且无法写入,那么 32 位系统上的可执行堆栈是如何工作的?

代码段是可执行的(但不可写)。堆栈段必须是 read/write(并且不可执行)。

每个段都有一个基地址和一个限制。软件将 offset/s 提供到 segment/s(例如,指令指针是 cs 段描述的区域的偏移量,堆栈指针是 [=11= 描述的区域的偏移量] 分割);其中 CPU 检查偏移量是否在段的限制内,然后将段的基地址添加到偏移量以确定(线性)地址。

如果代码段和堆栈段引用相同的内存(例如具有相同的基地址和限制);然后可以执行相同的内存(使用代码段)和 read/write(使用堆栈段)。

请注意,大多数操作系统不t/didn不使用分段(它们将所有段基地址设置为零,并将所有段限制设置为“最大”,因此它的行为就像没有段一样);而“所有段都引用同一内存”是很常见的。为了保护,大多数操作系统仅使用分页。