如何从头编译C编译器,然后从头编译Unix/Linux

如何从头编译C编译器,然后从头编译Unix/Linux

假设我在美国/英国以外的一家大型服务组织工作。我们广泛使用 UNIX 和 Linux 服务器。

通读本文它提到,在 C 编译器中插入后门很容易,那么使用该编译器编译的任何代码也将包含后门。现在,鉴于最近有关 NSA/GCHQ 授权在所有加密方法、硬件和软件中设置后门/弱点的泄密事件,编译器现在成为了一个关键的故障点。所有标准 UNIX/Linix 发行版都可能受到损害。我们不能让我们的系统、数据和客户数据被流氓政府破坏。

有了这些信息,我想从头开始构建一个可信的编译器,然后我就有一个安全的基础来构建,这样我就可以使用该编译器从源代码构建操作系统和应用程序。

问题

从源代码编译编译器(看似先有鸡还是先有蛋的情况)然后从头开始编译可信的 Unix/Linux 发行版的正确(且安全的方法)是什么?

您可以假设我或其他人有能力阅读和理解源代码的安全缺陷,因此源代码在编译之前将首先经过审查。我真正想要的是一份工作指南,用于安全地从头开始生成这个编译器,并可用于编译内核、操作系统和应用程序的其他部分。

如果我们要对在该堆栈上运行的操作系统或应用程序有信心,则安全堆栈必须从基础级别开始。是的,我知道可能存在硬件后门,可能会在编译器构建时将一些微代码插入到编译器中。目前我们对此无能为力,除非使用非美国设计的芯片。让我们首先对这一层进行排序,并假设我可以在插入任何后门之前在旧计算机上构建它。

正如布鲁斯·施奈尔所说:“我对工程师们说:我们建造了互联网,我们中的一些人帮助颠覆了它。现在,我们这些热爱自由的人必须修复它。”

额外链接:

答案1

AFAIK 完全确保安全性的唯一方法是用汇编语言(或直接自己修改磁盘)。只有这样你才能确保你的编译器没有插入后门——这是有效的,因为你实际上完全消除了编译器。

从那里,您可以使用从头开始的编译器来引导例如 GNU 工具链。然后您可以使用自定义工具链来编译Linux 从头开始系统。

请注意,为了让事情变得更容易,您可以拥有第二个用 C(或任何其他语言)编写的中间编译器。因此,您可以在汇编中编写编译器 A,然后用 C/C++/Python/Brainfuck/其他语言重写该编译器以获得编译器 B,您将使用编译器 A 对其进行编译。然后您将使用编译器 B 来编译 gcc 和朋友。

答案2

一种可能的方法是回归根源,尽管在实践中需要很长时间。 GNU 的开发始于 1984 年,Minix 的原始版本(在早期 Linux 开发过程中用于引导目的)于 1987 年发布。

整个答案基于您的前提,即“[您]或其他人有能力阅读和理解源代码的安全缺陷,因此源代码在编译之前将首先经过审查”,并且您可以信任此类分析的结果。如果没有这个,这个答案可能比毫无价值更糟糕,因为你将花费大量的时间而绝对没有任何好处。

如果您可以找到带有源代码的 Minix 原始书籍的副本,则可以从书中输入它。编译它,然后在不同的系统上使用不同的反编译器来验证编译器是否生成预期的机器语言二进制输出。 (代码只有12000行,大概是C语言,所以这样做比较耗时,但还在以内原因如果您认真对待这样一个项目。)您甚至可以编写自己的反汇编程序;那应该不是很困难。

获取您可能掌握的 GNU 实用程序的最旧版本(因为这些版本可能具有较少的代码和对外部库的依赖性较少),浏览代码,为 Minix 构建它(不过,这可能需要一些工作;您可以做什么)绝对要避免的是对源代码进行调整,因为这将使以后添加补丁非常容易出错)并经历 GNU 工具类似的反汇编验证周期。此时,您信任操作系统和工具链,因此您只需要查看补丁集中的源代码(补丁集中没有的任何内容都已被信任),但与您使用的工具相比,这些工具仍然非常原始和粗糙到今天。例如,不要指望系统工具的最基本功能能够正常工作。现在将所有内容转移并迁移到 Minix,并开始应用补丁,一次一个版本,重建每个版本之间受影响的所有内容,并在下一次使用新版本。阅读大量 XKCD。

在某个时候,您将拥有一个可以编译和引导早期版本的 Linux 内核的系统,就像 20 世纪 90 年代初 Linux 开始受到黑客欢迎时所做的那样。我建议此时迁移到 Linux(针对 Linux 重建系统库和工具链,构建 Linux 内核,启动到 Linux 并可能在 Linux 中重建 Linux 内核和 GNU 工具链;最后证明系统现在是自我修复的。托管),但这很大程度上取决于您。不断验证补丁、修补内核、库和基本 GNU 工具并重建,直到达到现代版本。

这时您就拥有了可用于构建现代软件的值得信赖的基本操作系统和编译器。届时,您可以按照例如Linux 从头开始构建能够执行的系统的指南有用任务。

“编译器”系统在任何时候都不能以任何方式连接到网络(包括作为联网主机上的虚拟机);您将面临渗透任何支持网络的组件(包括内核)的风险。如果您担心汤普森编译器攻击,您必须预料到任何 VM 主机也可能受到损害。使用sneakernet从您正在编译的物理主机获取源代码和二进制文件。至少在实现 USB 大容量存储支持之前,预计在系统上进出文件时会遇到麻烦。如果您真的很偏执,请打印源代码列表并手动输入它们(并希望打印机驱动程序和打印机中没有类似的代码)他们),或者在一台计算机显示器上读取代码并将其输入到物理上位于其旁边但未与其连接的另一台计算机中。

是的,这需要很多的时间。但这种方法的优点是每一步都是渐进的,这意味着任何恶意行为都很难逃脱,除非它是在许多版本的一段时间内逐渐引入的;这是因为每个步骤的更改相对较小,因此更容易检查。将补丁集与变更日志进行比较,确保您可以准确确定哪个变更日志条目对应于源代码中的每个更改。同样,这确实假设您有能力(可能通过您信任的人)验证此类更改尚未潜入代码库,但是它应该让您尽可能接近受信任的系统,就像除固件之外的纯软件方法一样。

答案3

如果您需要一个值得信赖的编译器,您可以看看学术著作,例如计算机证书项目。它是由 INRIA(法国 IT 公共实验室)构建的编译器,旨在“经过认证”,即生成语义上与代码完全等效的可执行文件(当然,它已经在数学上得到了证明)。

答案4

虽然手动创建自己的编译器作为起点是最安全的,但另一种选择是从 5(或 10)年前的安装 CD 安装系统,您相信该安装 CD 是在这些漏洞利用之前创建的。然后使用它作为基础来编译新的审计源。

相关内容