内核符号的地址会受到影响吗?结果?

内核符号的地址会受到影响吗?结果?

长话短说:在我的发行版 linux 3.08 内核中,使用cat /proc/kallsyms我可以发现,例如 _commit_creds 函数/符号位于地址 0xc1073fe0。当:

  • 构建我的内核(选项 1)
  • 通过调整内核二进制文件(选项 2)

是吗可能的影响这些地址? (即随机化以减轻对内核的攻击?)

我是否进一步正确地假设内核提供的系统调用需要保留在可预测/已知的地址,以免破坏内核提​​供的 ABI?

长版

在部分CVE-2016-0728所提供的某些 Linux 内核的漏洞概念验证使用这两行源代码:

#define COMMIT_CREDS_ADDR (0xffffffff81094250)
#define PREPARE_KERNEL_CREDS_ADDR (0xffffffff81094550)

尽管他们扮演着自己的角色仅在发生释放后使用溢出类型的问题之后尽管如此,对于完成权限升级仍然至关重要。当然,所有内核的地址并不相同,并且基本上每个发行版都会发生变化。无论如何,它们似乎在内核行内是恒定的(即 Ubuntu 12.04 x86 的地址始终位于 0xc1073fe0)。

我的问题是了解是否可以影响这些地址以对它们进行洗牌/随机化,从而使内核的利用变得更加困难(即,在内核环 0 中有指令指针后,攻击者有些盲目)?我假设为了拥有用于系统调用的 ABI,我无法更改 sys_xxxxxxxxxx 符号的位置,但至少对于内核符号的内部,我不一定理解需要让它们可预测?

因此我在这里问如何随机化这些内核符号,或者通过

  • (1) 编译自定义内核或者,
  • (2) 更好地调整内核并移动符号(我认为这可能是更困难和更脆弱的事情)。

更改内核符号的地址会产生什么后果? (不包括系统调用 ABI 的)。

答案1

如果所有 Ubuntu 12.04 x86 都具有相同的地址,很可能是因为它们都搭载相同的 Linux 版本。如果您使用启用了优化的现代版本 GCC 来编译您自己的内核,它将随机化每个构建的地址。

事实上,这对于最近的内核来说甚至是不必要的。自从这次提交(2014 年 1 月),x86 架构上的内核地址空间甚至在每次启动时都会通过称为“内核地址空间布局随机化”的机制发生变化:http://lwn.net/Articles/569635/

因此,升级您的发行版或重新编译内核,您应该拥有随机地址。

至于后果,如果让编译器或内核加载进程来完成这项工作,就没有什么后果。如果您尝试在编译后调整构建,最可能的结果是您将无法启动它,或者更糟糕的是,它会随机崩溃。后处理编译器输出的另一个实际后果是,您将无法在编译过程中对内核进行签名(例如,这是可信启动所必需的)。

相关内容