在高层次上,操作系统和管理程序的任务是管理计算机系统的资源,以便构建安全基础。有关机密性、完整性和可用性的应用程序。就安全性而言,软件堆栈的这些最低层的主要作用是提供安全域的隔离和可能违反隔离的所有操作的调解。理想情况下,操作系统将任何单个进程与所有其他进程隔离开来。例如,外围进程不应该能够访问分配给主进程的内存,知道与该主进程相关的活动的任何信息,除了那些进程选择显示或阻止进程使用其分配的资源(例如CPU时间)无限期。一些操作系统甚至可以调节信息流,这样绝密数据就不会在没有适当许可的情况下泄露给进程,或者机密数据不能被没有适当权限级别的进程修改。深入挖掘,我们可以区分控制平面和数据平面操作,我们发现操作系统中的隔离涉及两者。在内存隔离中,操作系统在配置MMU(内存管理单元)的同时在控制平面上运行,然后在操作系统不参与的情况下负责隔离。在大多数其他交互中,例如,在非特权安全域提供的系统调用参数上运行时,操作系统在两个平面上运行。平面之间缺乏分离很容易导致漏洞,例如当操作系统决定在另一个域中重用以前属于一个安全域的内存页(由MMU强制执行访问隔离)时,没有正确覆盖(可能敏感的)数据。设计操作系统的方法有很多种。图1说明了四种极端的设计选择。图中。如图1(a)所示,操作系统和应用程序在没有任何隔离的情况下运行在单个安全域中。早期的操作系统以这种方式工作,但今天的许多嵌入式系统也是如此。在这种情况下,系统中不同组件之间几乎没有隔离,应用程序可能会破坏文件系统(FS)、网络堆栈、驱动程序或系统的任何其他组件的活动。图1(b)显示了大多数现代通用操作系统的配置,其中大多数操作系统驻留在单个安全域中,与应用程序严格隔离,并且每个应用程序也与所有其他应用程序隔离。例如,这是Windows、Linux、OSX和原始UNIX的许多后代的结构。由于操作系统的几乎每个组件都在一个安全域中运行,因此该模型运行良好,因为组件仅通过函数调用和共享内存进行交互。只要每个组件都是良性的,该模型也是安全的。但是,如果攻击者设法破坏单个组件(例如驱动程序),则所有安全措施都将变得毫无用处。通常,设备驱动程序和其他操作系统扩展(例如,Linux内核模块)是系统安全的重要考虑因素。通常由第三方编写并且比核心操作系统代码更具有缺陷,在操作系统的单一安全域中运行的扩展可以完全危及系统的安全性。有趣的是,在此类系统中,内核与其他安全域之间的界限往往有些模糊,因为操作系统可以绕过内核进行高速联网,或者将非性能关键操作系统组件实现为用户进程。示例包括UNIX操作系统中的用户空间文件系统(FUSE)和Windows中的用户模式驱动程序框架(UMDF)。即便如此,大多数操作系统功能仍然形成一个单一的整体安全域。图1(c)显示了在多服务器操作系统中构成操作系统的所有组件在单独进程中的极端分解。这种配置可能比以前的模型效率低,因为操作系统不同组件之间的所有交互都涉及进程间通信(工业计算机)。此外,操作系统作为分布式系统运行,任何曾经构建过分布式系统的人都知道事情会变得多么复杂。然而,多服务器系统的优势在于,例如,受感染的驱动程序无法轻易破坏系统的其余部分。此外,虽然从概念的角度来看多服务器看起来像分布式系统,但真正分布式系统的许多复杂性是由于不负责任的通信造成的,这在多服务器系统中是不存在的。普遍的观点是,基于微内核的多服务器设计比单体和单域设计具有安全性和可靠性优势,但会产生更高的开销——安全性的代价。最后,图1(d)显示了与图1(a)类似的情况:应用程序运行在最小内核之上的最小“库操作系统”(libOS),多路复用底层资源。libOS包含的代码通常是操作系统的一部分,但直接包含在应用程序中。这种配置允许应用程序完全根据他们的需要定制操作系统,并忽略他们无论如何都不打算使用的所有功能。图书馆操作系统最早是在1990年代提出的(例如,在MIT的Exokernel和剑桥的Nemesis项目中)。在相对默默无闻几年后,它们再次流行起来——尤其是在它们通常被称为Unikernel的虚拟化环境中。在安全性方面,Unikernel很难与基于微内核的多服务器系统相提并论。一方面,它们没有操作系统组件的极端分离。另一方面,它们允许(库)操作系统代码更小更简单——它只需要满足这个应用程序的需要。此外,该库不能妥协隔离:它是该应用程序的可信计算基础的一部分,而不是其他库。关于哪种设计更好的争论可以追溯到1992年的AndrewTanenbaum和LinusTorvalds。到那时,由Tanenbaum开发的小型类UNIX操作系统MINIX已经出现了大约五年,并在世界范围内获得关注作为教育操作系统——特别是因为贝尔实验室的原始UNIX是作为商业产品出售的,具有限制性许可,禁止用户修改它。MINIX用户之一是当时的芬兰学生Torvalds,他在Usenet的comp.os.minix新闻组中宣布了新的操作系统内核。1992年1月,Tanenbaum批评该设计缺乏可移植性,并把矛头对准了Linux的整体设计,声称Linux从一开始就已经过时了。Torvalds回应了他自己对MINIX的批评。这场激烈的交锋包含了越来越复杂的论点,其中许多论点一直存在到今天,以至于谁赢得辩论的问题仍然没有答案。图1:操作系统的极端设计选择:(a)单域(有时用于嵌入式系统),(b)单体操作系统(Linux、Windows和许多其他操作系统),(c)基于微内核的多服务器操作系统系统(例如Minix-3)和(d)单核/库操作系统,即Linux已经变得如此流行,以至于很少有人会认为它已经过时。同样明显的是,来自MINIX等多服务器系统的想法已被纳入现有的操作系??统和基于管理程序的系统中。有趣的是,在撰写本文时,即使是MINIX本身也作为一个微型操作系统运行在一个称为管理引擎的独立微处理器上,位于数以亿计的英特尔处理器中。此外,如今现代系统中的CPU变得越来越复杂。片上系统(SoC),硬件本身开始看起来像一个分布式系统,一些研究人员明确主张设计一个操作系统。所以重点是消息传递,而不是通信的内存共享。通常,虚拟化环境的情况与操作系统的情况相当。我们已经看到,在极端情况下,带有应用程序和精简操作系统的整个虚拟机可以形成一个域。更常见的是,在支持一个或多个操作系统(例如Linux或Windows)的虚拟机中有一个最低级别的管理程序。换句话说,这些管理程序给每个操作系统一种在专用硬件上运行的错觉。在光谱的另一端,我们发现整个系统被分解成单独的、相对较小的虚拟机。事实上,一些操作系统,例如QubesOS,通过允许将各个用户进程隔离在自己的虚拟机中,从而完全集成了虚拟化和操作系统的概念。最后,正如我们已经看到的,Unikernel在管理程序之上的虚拟化环境中很流行。顺便说一句,虚拟机的缺点之一是每个操作系统映像都使用存储并增加冗余,因为每个系统都会认为它是硬件山丘之王,而实际上它是共享资源。此外,虚拟机中的每个操作系统都需要单独维护:更新、配置、测试等。因此,一种流行的替代方法是在操作系统级别进行虚拟化。在这种方法中,多个环境(称为容器)在单个共享操作系统上运行。容器之间尽可能相互隔离,有自己的内核命名空间、资源限制等,但最终共享底层操作系统内核,通常是二进制文件和库。容器比虚拟机更轻量级。然而,如果我们暂时忽略管理方面,虚拟机通常被认为比容器更安全,因为它们非常严格地划分资源并且只共享管理程序作为两者之间的薄层。硬件和软件。另一方面,有人认为容器比虚拟机更安全,因为它们非常轻量级,我们可以将应用程序分解为容器中具有定义良好接口的“微服务”。此外,需要保护的东西更少,从而减少了整体的攻击面。容器(或“操作系统级虚拟化”)的早期工作可以在chroot调用中找到,它于1979年首次添加到版本7Unix中。2000年,FreeBSD发布了Jails,它在操作系统虚拟化方面更进了一步。今天,我们有许多容器实现。一个流行的是Docker。最后一类操作系统明确针对小型和资源受限的设备,例如物联网(IoT)中的设备。虽然每个人对物联网意味着什么以及从智能手机到智能尘埃应考虑哪些设备都有不同的看法,但人们一致认为大多数资源受限的设备都应该是其中的一部分。即使是精简的通用操作系统对于此类设备来说也可能过于庞大,而且操作系统预计只能运行几千字节。举个极端的例子,RIOT等流行的物联网操作系统可能小于10KB,运行在从8位微控制器到通用32位CPU的系统上,有或没有内存管理单元(MMU)。)和其他高级功能。我们要求Windows和Linux等操作系统提供的丰富功能和应用程序隔离可能在这些操作系统中不存在,但可能支持实时调度或低功耗网络等功能,这些功能在许多嵌入式系统中都很重要。由于我们对操作系统提供的安全保证感兴趣,因此我们假设存在多个安全域。在下一节中,我们将从既定安全原则的角度说明不同设计的优缺点。我们的重点将放在设计安全性和我们可以防止攻击的方法上,但在此之前要观察到在这个级别上有更多的安全性。特别是,系统的管理和可维护性(在更新、扩展、配置等方面)起着重要作用。
