如果我们在C中有一个函数,其中包含一个简单的单元化ìnt
变量,我们知道此变量可能并不总是初始化为零。相反,它可能包含一些“垃圾”值。
我的问题是:到底能代表什么??可能是以前终止的进程留下的一些信息(未释放的内存)?
如果是,那么这将不是一个极其重大的安全漏洞吗?因为以这种方式,任何进程都可以读取使用与当前进程相同的地址空间的进程(密码,令牌等)留下的信息。
我的假设是,对于每个新进程,内核将为该新进程分配的内存清零(至少是为堆栈分配),然后将可执行文件加载到内存中。这些“垃圾”值实际上是由当前进程的加载过程生成的值(因此,无法从使用相同进程的其他进程访问任何剩余数据地址空间)。
我正在就这个话题与一些学者争论,我真的想要一个清晰而全面的答案(我敢肯定有一个答案)。我们假设内核是基于debian / centos的。很高兴知道不同内核/ OS-es在行为上是否存在差异。
感谢您。
答案 0 :(得分:5)
这应该分为两个问题:
main
时内存中有什么?其他堆栈溢出问题和解答中讨论了第一个问题。完整的答案很复杂,并且涉及各种情况的讨论,并且这个问题似乎并没有特别询问,因此我将其留给其他Stack Overflow问题。对于这个问题,只需说使用未初始化对象的值就容易发生未定义行为。此外,这不仅是因为对象的内存可能具有麻烦的值,还因为C标准允许C实现将以各种方式将读取未初始化值的程序视为行为异常的程序,然后优化会进一步破坏程序
就内存中的内容而言(假设我们有一种受支持的方式来检查它,也许使用汇编语言而不是C),那么每个提供多类安全擦除(或初始化)内存的多用户系统在将其提供给流程之前。正如问题所考虑的那样,调用main
时内存中的任何值都是加载过程的结果或操作系统的初始化结果。 (请注意,加载过程的结果包括常量数据和程序文本的加载-因此我们希望可以在其中找到定义的值-以及加载代码完成的工作中剩下的任何数据-变量等等。 )
这个问题要求一个明确的答案,所以让我澄清一下:一个为用户进程提供安全性的操作系统,必须先从内存中删除以前进程的数据,然后再将其提供给其他用户使用处理。不能通过信任程序不检查其给定的内存并对其执行任何操作来提供安全性。
不打算由不受信任的用户共享的基本系统在创建新进程并为其分配内存时当然可以跳过内存的初始化。
答案 1 :(得分:0)
那么,局部变量存储在堆栈空间中,因此一旦完成对当前例程的调用,堆栈指针就会上移以释放所有当前例程局部变量,并且出于效率方面的考虑,不会擦除以前的内容(仅擦除堆栈指针已移动)。
如果您输入一个新例程,编译器所做的就是向下移动堆栈指针(它不会在局部变量空间上压入任何东西,只是在该空间上移动以为新的局部变量集腾出空间) ),直到代码中需要使用局部变量后才使用该空间。您需要的是如何解释以前使用堆栈段的位模式,这取决于先前使用堆栈进入当前例程的方式。可以是:
由于现在以不同的方式使用内存(如当前例程的本地空间所规定),因此无法有效解释此类内存内容,而只能是从旧代码中清除数据。