首页 > 解决方案 > C 中未初始化的局部变量中包含的值到底是什么?

问题描述

如果我们在 C 中有一个函数,其中有一个简单的未初始化ìnt变量,我们知道这个变量可能并不总是初始化为零。相反,它可能包含一些“垃圾”值。

我的问题是:究竟什么可以代表这个价值?它可能是之前终止的进程留下的一些信息(未释放的内存)?

如果是,那么这不是一个极其重大的安全漏洞吗?因为通过这种方式,任何进程都可以读取与当前进程使用相同地址空间的进程留下的信息(密码、令牌等)。

我的假设是,对于每个新进程,内核会将分配给该新进程的内存(至少对于堆栈)归零,然后将可执行文件加载到内存中。这些“垃圾”值实际上是由当前进程的加载过程生成的值(因此无法访问来自使用相同地址空间的其他进程的任何剩余数据)。

我正在与一些人就这个话题争论,我真的想要一个清晰而全面的答案(我敢肯定有一个)。我们假设内核是基于 debian/centos 的。很高兴知道不同内核/操作系统的行为是否存在差异。

恭敬地谢谢你。

标签: clinuxsecurityprocessstack

解决方案


这应该分为两个问题:

  • C 标准对未初始化对象的值有何规定?
  • 调用时内存中main的内容是什么?

第一个问题在其他 Stack Overflow 问题和答案中讨论。完整的答案很复杂,涉及对各种情况的讨论,而这个问题似乎并没有特别问这个问题,所以我将把它留给其他 Stack Overflow 问题。对于这个问题,只要说使用未初始化对象的值容易出现未定义的行为就足够了。此外,这不仅仅是因为对象的内存可能有麻烦的值,而是因为 C 标准允许 C 实现将读取未初始化值的程序以各种方式视为行为不端的程序,然后优化会进一步破坏程序.

就内存中的内容而言(假设我们有一种受支持的方式来检查它,可能使用汇编语言而不是 C 语言),那么每个提供任何类型安全性的多用户系统都会在创建内存之前擦除(或以其他方式初始化)内存可用于进程。正如问题所考虑的那样,调用当时内存中的任何值都是main加载过程或操作系统初始化的结果。(请注意,加载过程的结果包括常量数据和程序文本的加载——因此我们希望在那里找到定义的值——以及加载代码完成的工作留下的任何数据——它的变量等等。 )

这个问题需要一个明确的答案,所以让我明确一点:为用户进程提供安全性的操作系统必须先从内存中擦除先前进程的数据,然后才能将该内存提供给另一个进程。不能通过信任程序不检查给定的内存并对其进行任何操作来提供安全性。

不打算由不受信任的用户共享的基本系统当然可以在创建新进程并为它们分配内存时跳过内存的初始化。


推荐阅读