Security 是否曾经需要堆栈是可执行的?

Security 是否曾经需要堆栈是可执行的?,security,callstack,buffer-overflow,Security,Callstack,Buffer Overflow,多年来,让调用堆栈允许代码执行一直是许多安全问题的根源。堆栈缓冲区溢出可用于利用写得不好的软件进行攻击,从而可以执行存储在堆栈缓冲区中的代码 我只是想知道是否真的有一个原因,它不仅仅是不可执行的?为什么调用堆栈上的任何东西都需要是可执行的 也许有某种历史原因自20世纪40年代以来,大多数计算机故意不区分可执行内存和不可执行内存。这种单一的、统一的代码和数据模型是该模型的关键方面之一。在不同的时间,在各种内存管理设计中引入了一些有限的非执行功能,事实上,今天大多数CPU和操作系统都支持将单个内存页

多年来,让调用堆栈允许代码执行一直是许多安全问题的根源。堆栈缓冲区溢出可用于利用写得不好的软件进行攻击,从而可以执行存储在堆栈缓冲区中的代码

我只是想知道是否真的有一个原因,它不仅仅是不可执行的?为什么调用堆栈上的任何东西都需要是可执行的


也许有某种历史原因

自20世纪40年代以来,大多数计算机故意不区分可执行内存和不可执行内存。这种单一的、统一的代码和数据模型是该模型的关键方面之一。在不同的时间,在各种内存管理设计中引入了一些有限的非执行功能,事实上,今天大多数CPU和操作系统都支持将单个内存页标记为不可执行。

自20世纪40年代以来,大多数计算机故意不区分可执行内存和不可执行内存。这种单一的、统一的代码和数据模型是该模型的关键方面之一。在不同的时间,在各种内存管理设计中引入了一些有限的非执行功能,事实上,今天大多数CPU和操作系统都支持将单个内存页标记为非可执行。创建非可执行堆栈需要硬件的帮助。早期的英特尔处理器没有NX位,直到386或奔腾才真正有用。(早期的处理器没有执行保护,但并不普遍。)

在不同的时期,人们利用可执行堆栈甚至可写代码段来编写自修改程序。我想我们都同意,自我修改代码是个坏主意,但我记得当我在80年代开始使用它时,人们对它非常感兴趣。如果你抛开烦人的限制,比如代码和数据之间的任意分隔,你真的可以编写一些非常紧凑的程序

说到这里,执行数据并在堆栈上存储大量数据的概念是Lisp的一个重要部分。有关这如何影响JIT编译器的讨论,请参见。如果您想要JIT编译一些非常小而且非常频繁的东西,那么在堆栈上分配和运行它会很方便


也就是说,正如你所说,这是一个大问题,这就是为什么人们通常会远离它。这将哈佛体系结构带回到了我们大多数人成长的冯·诺依曼体系结构中。

创建不可执行堆栈需要硬件的帮助。早期的英特尔处理器没有NX位,直到386或奔腾才真正有用。(早期的处理器没有执行保护,但并不普遍。)

在不同的时期,人们利用可执行堆栈甚至可写代码段来编写自修改程序。我想我们都同意,自我修改代码是个坏主意,但我记得当我在80年代开始使用它时,人们对它非常感兴趣。如果你抛开烦人的限制,比如代码和数据之间的任意分隔,你真的可以编写一些非常紧凑的程序

说到这里,执行数据并在堆栈上存储大量数据的概念是Lisp的一个重要部分。有关这如何影响JIT编译器的讨论,请参见。如果您想JIT编译非常小且经常的东西,那么在堆栈上分配和运行它可以很方便


也就是说,正如你所说,这是一个大问题,这就是为什么人们通常会远离它。这将哈佛的建筑风格带回到了我们大多数人成长的冯·诺依曼建筑风格中。

+1有趣。我从未尝试过在堆栈上编写自修改代码,这是一种线程安全的方法。我从未尝试过在堆栈上编写自修改代码——这是一种线程安全的方法。