CODOMs

CODOMs——论文总结

摘要

1.当前软件系统既不安全也不可靠。
2.当前硬件提供的基本软件保护原语迫使系统在同一保护域中运行许多不可信的软件组件(例如过程,库,插件,模块),如果不是这样,需要进行地址切换,但是地址切换会导致性能的下降。
3.本文提出了codoms(以代码为中心的内存域),这是一种新颖的体系结构,它可以在组件之间提供更细粒度的隔离,并可以高效率运行,零运行开销。
4.在周期准确的全系统x86模拟器中实现codom表明,在正确的硬件支持下,细粒度的保护和性能可以和平共存。

一.介绍

复杂的软件系统包含大量相互不信任或不可靠的软件组件,它们可以跨越多种粒度和目的:单个函数、编译单元、代码库、应用程序插件或设备驱动程序。

如果不能正确的隔离这些组件,会产生严重影响,不管是恶意还是疏忽的,比如权限升级、信息泄漏、拒绝服务以及缓冲区溢出导致的数据损坏。因此,系统安全性和弹性要求单独的软件组件被隔离在单独的域中

现有的体系结构缺乏对软件组件级别的隔离。目前只支持一些粗粒度的保护机制,在单独的地址空间中隔离用户进程,在特权处理器模式下运行OS内核。这样的机制带来不可忽略的运行时开销,并且只能由操作系统管理,这使得他们不适合在共享单一地址空间的软件组件之间提供细粒度的隔离

在本文中,我们提出了以代码为中心的内存域体系结构(codoms),他为保护共享一个地址空间的多个交互软件组件提供了有效的支持,codoms是基于这样一种观察,即指令指针可以作为一种访问内存的能力

由于软件组件由代码和数据组成,组件的数据只能由他的代码访问,因此,只有当指令指针来自组件的代码时,组件指令才能访问组件的数据。

codom设计是由以下准则驱动的:
(1)软件由多个组件组成,包括可信的和不可信的,他们共享相同的地址空间。
(2)组件通过交互来执行动作。系统必须:a.支持低开销的跨域同步调用/返回。
b.提供受保护的域入口点
c.防止呼叫者和被呼叫者相互干扰
(3) 为了避免缓冲区拷贝,必须允许交互域安全地引用彼此的内部内存,这要求域能够有效的授予和撤销访问其内存区域的权限,并且能够验证所给指针的有效性。(这一部分并不是很理解)

codoms通过将每个页面与一个标记关联起来进行操作,并且多个(不一定是连续的)页面可以共享相同的标记。
代码页还与它们可以访问(以及如何访问)的标记列表以及执行特权指令的能力相关联。因此,域是以代码为中心的,指令指针本身决定它可以访问哪些页面和特权资源。此外,控制可以使用简单的调用/返回指令在可以忽略不计的运行时开销下在域之间进行切换。(代码页是什么?标记列表是什么?特权指令的能力?)

为了方便快速的跨域调用,codom允许使用应用程序控制的功能寄存器跨域就地共享数据。
这有助于安全共享任意区域(基指针和大小),此外,codom提供了对能力篡改的保护,并且可以比以前提出的系统更有效地执行选择性的、用户级的能力撤销。(啥叫能力篡改?)

我们使用一个周期精确的x86模拟器评估了codom,结果显示切换域会导致极低的开销。在更大的范围内,我们展示了codom能够将Linux内核中的每个模块隔离到自己的领域中,而运行时成本可以忽略不计。

本文的主要贡献包括:
(1)以代码为中心的域/指令指针作为功能:一种基于硬件的隔离机制,其中多个软件组件可以共享一个地址空间。
(2)简单高效的域切换:以代码为中心的组织使用简单的调用/返回指令促进了域管理和低延迟的域切换。
(3)临时访问授权:应用程序控制的能力寄存器允许跨域的细粒度、安全的内存共享,而不需要昂贵的操作系统干预。
(4)高效的访问授权撤销:codom支持用户级的高效选择能力撤销。重要的是,区分同步和异步功能可以降低撤销公共(同步)跨域调用/返回用例的开销。
(5)机制的互补性:codom机制能够有效地适应多个系统组织,并为系统逐步加强其安全性提供了一条路径。

二.CODOMS概念

codoms体系结构的目标是提供灵活的硬件机制来定义域,并支持跨域的低延迟控制和数据传输。

2.1 以代码为中心的软件组件隔离
以代码为中心的隔离包含了将软件组件作为一个单元的思想,软件组件用来识别代码、数据(动态和静态)以及用于跨组件交互的预定义接口。

域被定义为代码和数据页的任意集合,只有域的代码被允许自由访问其代码和数据。

这样使得指令指针可以作为访问域的功能,域实际上可以包含多个组件。

以代码为中心的隔离还强制域交互,如果允许一个域调用另一个域,他可以简单的调用被调用域中预定义的入口点来转移控制

在这里插入图片描述
图中显示了三个软件组件A,B,C的例程相互调用。具体来说,域A的函数funcA调用域b的函数funcB,域b调用函数funcC(域C)。
该图还说明了codom用于强制域隔离的两种机制:页表功能(PTCaps)和访问保护列表(APLs)。
PTCaps扩展页表以包含每页标记,这样组成特定域的所有页面共享一个标记值。
除了现有的每页权限(R/W/X)之外,该机制还增加了两个新的权限位,以允许特权操作和在内存中存储能力(分别为P位和S位;看到§以下4.4.1)。
例如在图中。所有标记为A的页面合成域A,这也表明域可以由不连续的内存页组成。

APLs维护了跨域访问和调用权限,通过将每个标记与一组其他标记及其组成页面上执行的操作关联起来。图中显示的APL表明域A中的代码可以调用域B的入口点,域B中的代码可以调用域C,并写入域A的页面(如果每页权限允许的话)。

当执行访问时,codoms检查:

  1. 目标页的标记是否存在于APL中,用于当前执行指令。
  2. 访问的与APL中列出的权限和每页的保护位兼容。
    这提供了在两个级别上,分层的安全性的方法:在域(APL)和页面粒度上。
    例如授权B对A的写访问权,并不允许它写入第一个内存页,因为他是写保护的。

PTCaps和APLs是在加载程序(或其模块)时有操作系统设置的,此外必须通过TLB关闭操作来维护核间的一致性,然而,由于这些机制用于长期访问授权,这些操作并不频繁。

以代码为中心的隔离的直接好处是,它为程序员和管理员提供了简单的机制来表达和执行跨域权限,同时在跨域时产生可忽略不计的运行时开销。相反,更“传统”的功能系统需要显式地管理功能,这些功能以更细的粒度工作;例如,域A对于它自己的页面需要三种不同的功能(因为它们不是连续的),加上B中的每个入口点都需要一种功能

2.2 瞬态、细粒度的隔离

软件组件通过过程调用进行通信,其参数通过值(使用寄存器)或引用(使用指向内存的指针)传递。

codoms使用功能寄存器保留了跨域的同步调用/返回语义,它们支持通过引用传递数据,从而避免昂贵的内存拷贝或页面重映射。(功能寄存器是啥?)

在这个例子中,例程funcA将一个参数传递给funcB,而funcB将其转发给funcC。如果该参数是一个指向域a内存缓冲区的指针,那么funcC将无法访问它,因为它的APL不允许它。纯隔离要求对缓冲区重新分配其标记或跨域复制。(不懂这句话啥意思)

因此,codoms提供了功能寄存器(CapRegs),这是一种应用程序管理的机制,可以临时授权对域内存的访问权,CapRegs由用户级调用程序的代码初始化,以临时授予被调用程序访问任意内存范围(以字节粒度计算)的权限。一旦被调用方被调用,它就可以访问所述缓冲区,直到它将控制权交还给调用方。

此外,允许被调用者沿着调用链传递CapRegs,以支持调用间接。codom提供了“创建”(即初始化)、复制、“削弱”(一种受控的修改形式)、激活/钝化(从内存溢出/到内存)、撤销和验证指针的指令。

codom通过将常规代码的权限限制为创建它的指令的权限,确保常规代码不能伪造功能。当一条指令创建一个功能时,该指令代码页的APL被复制到该功能中。例如,假设图1中的域B创建了一个跨最后四个页面的功能。该能力将使用B的APL,允许对给定范围内域A的所有页面进行写访问,但不允许对域C的页面进行写访问,因为它的APL排除了这样的访问(因此能力也是“稀少的”)

最后,codom通过区分同步语义和异步语义来优化功能撤销:在调用者只需要向被调用者授予临时访问权限(被调用者可以进一步委托授予)的情况下,使用同步功能。到目前为止,这些是最常见的类型。当被调用方返回时,通过确保没有将同步功能存储在内存中,同步功能会被隐式地撤销,无需任何代价;一旦被调用者返回,就不能再使用它们了。
异步功能用于授予比被调用者更持久的访问。它们在域之间的异步数据传输(例如,异步磁盘读取),或者当两个线程通过内存交换能力时非常有用。codom提供了有效的支持来选择性地撤销这种功能。

2.3 使用模型

codom提出了灵活的机制来支持多个用例,在这些用例中,域需要不同程度的隔离,允许系统根据需要调优性能。

该体系结构旨在允许程序员和系统管理员定义所需的安全性和故障隔离策略。对于程序员来说,这种负担可以是最小的,只要声明一个编译单元或一个代码库被用作一个孤立的域,并注释它的入口点——其他域可以使用的例程来与之交互。对于管理员来说,这允许强制执行系统范围的策略,例如单独使用第三方模块,以不损害系统或影响其弹性。

我们设想codom体系结构在已经存在安全感知接口的结构化场景(例如,用户/内核/管理程序分离),或者某些域是其他域的超集(例如,插件/应用程序关系)中的立即有用性。例如,通过将内核的系统调用接口实现为运行在单独域中的特权共享库,codom可以包含普遍的内核/用户环保护,允许应用程序安全地调用系统调用而不存在处理器陷阱。

codom还能够按照基于能力的寻址体系结构的精神提供细粒度组件隔离

3.内存保护和隔离的复杂性和性能

长期以来,人们一直将内存保护和隔离作为构建安全且有弹性系统的基本要素进行研究。建议的机制试图平衡使用的简单性和性能开销。
在本节中,我们将讨论之前提出的机制,同时重点讨论这种权衡的三个主要方面:
(1)定义和切换域的复杂性
(2)切换域的性能
(3)域之间共享数据的性能
现有的保护机制要么提供复杂的使用语义,要么在切换域(或两者兼备)时产生大量的性能开销。因此,程序员通常会将多个语义域推到一个物理域中,从而损害软件的安全性和弹性。

虚拟内存地址空间是域隔离最常见的机制,在操作系统的管理下,地址空间通过向进程提供几乎无限的独立机器的内存的错觉来隔离任意内存页的集合。进程抽象反过来提供了一种方便的编程抽象。

保护环(或特权级别)是一种用于隔离执行代码的公共机制。环被OS用来将自己与不受信任的用户进程隔离开来,需要使用系统调用来进行进程/OS交互。

基于功能的架构位于频谱的另一端。功能是可传播和不可伪造的令牌,用于标识和授权对资源的访问。功能允许实现细粒度的隔离,该隔离仅授予软件执行其任务所需的最小资源集(最小权限原则)。

3.1 定义和切换域的复杂性

地址空间通过在页表中编码访问权限,隐式地定义了进程的域。由于页表的使用对应用程序是透明的,地址空间提供了一个简单的编程抽象。然而,由于页表是特权资源,管理他们的成本很高,并且需要OS进行干预。
此外,进程给程序员带来了管理并发性和数据移动/共享的负担。

保护环提供了分层的域的方案。所有环(域)共享一个地址空间,一个环中的代码可以访问全部较少特权环的资源,环形域的全部有序层次结构不如单独的地址空间灵活。例如,Linux内核模块并不适合这种方案:将两个完全独立的模块放置在单独的环中将不必要地给予一个模块对另一个模块的完全访问权。

能力系统通过一组“root”能力授予对内存资源的访问权,域被定义为这些root的传递闭包,这需要使用多种功能来覆盖符合单个域的所有组件,域切换需要切换所有组件。显式地管理根会给程序员带来负担,所以这样的系统通常会在域切换硬件中嵌入高级语义。

CODOMs试图从每种机制中获取最佳效果。可分页系统用于聚合域资源,但它允许多个域共享一个地址空间,并调用特权操作。重要的是,这种设计使以代码为中心的域与现有的软件兼容。即使域由操作系统管理,它们也可以通过简单的控制流指令进行切换,从而简化它们的使用和部署。最后,功能允许域以任意粒度共享数据,从而避免昂贵的内存拷贝和操作系统管理的页表修改。

3.2 切换域的开销

域切换会重新配置一些架构资源,从而导致运行时开销,至少,引入了影响ILP的管道的RAW依赖。

在需要操作系统干预来执行切换的机制中,开销会更大,从而保证跨特权级别(地址空间和保护键)的额外往返。保护环和Mondrix在硬件中嵌入了额外的跨域语义,增加了这些开销。

传统的功能系统也会产生额外的开销,因为他们必须切换root功能,最后,除了操作系统干预开销之外,一些地址空间隔离实现还需要刷新交换机上的TLB。

codoms通过以代码为中心的保护方法来规避所有这些开销。它允许通过常规函数调用在用户级进行域切换,甚至不需要在域切换期间支付RAW风险的代价。

3.3 域之间共享数据

跨域共享数据对于有效的域交互至关重要,但是不同的隔离机制提供的共享工具会带来不同的运行时开销。

保护环只允许低权限环与高权限环轻松共享数据。在相反的方向上共享需要昂贵的缓冲区拷贝或更改页表权限。地址空间限制了共享页面粒度,并且需要昂贵的操作系统干预来修改页表。类似地,Mondrix需要os中介的表修改来建立共享内存区域。重要的是,撤销或“降级”基于表的系统上的访问将导致代价高昂的TLB击落。

能力可以看作是例程参数的一种特殊形式。为了防止伪造和篡改能力,一些系统使用类型化的段来区分常规数据和功能,其他系统通过在单词级别标记内存,允许混合数据和功能,从而影响内存和宽带利用率。在所有情况下,能力授予对连续区域的访问权,而共享非连续区域则需要设置多个能力。为了避免这种情况,数据必须小心地放在内存中,这对于动态数据结构并不总是可行的。最后,功能系统在撤消功能时会产生开销。

由于已分配的内存可以重用,因此域必须将功能撤消到未使用的内存区域,以避免信息泄漏。各种撤销方法已经被提出,其中许多需要OS干预:
(a)释放整个段并撤销该分段的所有功能
(b)避免内存复用,直到能力被垃圾收集,这将导致昂贵的内存清理
(c)使用间接表,这种表在每次使用功能时都施加额外的延迟

在除最后一种情况外的所有情况中,都不可能撤销允许特定域访问特定缓冲区的特定功能,相反,必须撤销所有授予对该缓冲区访问权的功能。

codom以代码为中心的特性需要较少的、独特的功能,因为这些功能只在访问APL编码之外的内容时需要。此外,codom确保了功能的完整性,而不需要内存标记和分段。最后,codom优化了通用同步(调用/返回)模式的撤销。

4.CODOMs 实现

codoms的设计目的是提供安全和性能,即使在高ILP无序处理器。图中说明了codom体系结构的关键元素,如下所述,一些体系结构元素必须由可信计算基础管理TCB管理,TCB是维护系统完整性和执行高级隔离策略所需的操作系统的最小子集。
在这里插入图片描述

4.1 硬件元素和保护原语

4.1.1 页表的功能(PTCaps)

页表功能(PTCaps)是作为页表扩展实现的,包括一个标记(64位)和标记存在(T),特权能力P和能力存储(S)位。后者存储在页表条目的未使用的位中,标记存储在与其扩展的页目录物理相邻的页中。T位允许为整个页表子树设置标签,最大限度地减少页表的空间和管理开销。P位指示在代码页中是否允许特权操作,以确保常规代码不能执行它们。S位标识可用于存储功能的页面。

4.1.2 访问保护水平

访问保护水平指定了四个有序的值:None,Use,Read和Write,Use是基于目标页面重载的:

  • capability storage pages:允许 加载/存储 能力 从/到 内存,不允许定期加载/存储。
  • 代码页:启用域入口点,允许调用到与系统可配置值对齐的地址。如果通过大小为0的功能访问,则表示一个未对齐的地址,并允许跨域使用任意返回地址和函数指针。

4.1.3 能力寄存器(CapRegs)

能力寄存器存储每个核有效的能力,存储在内存中的能力占用256位(32b),包括一个基地址和大小,一个两位的访问保护级别,一个撤销计数器地址,一个撤销计数器值和一个标志。
CapRegs的管理方式如下:

Create初始化一个能力寄存器,应用程序必须提供除标签之外的所有字段。标签由硬件设置(基于PC)以防止伪造,并且标签的APL缓存到CapReg,如果没有提供撤销计数器,则该功能是同步的。

Modify只能削弱访问保护级别,缩小访问能力的地址范围

Spill只允许在32b对齐的地址上,并且目标页面被标记为能力存储,可以(至少)用Use级别访问。同步功能只能被溢出到DCS,并且能力推入/弹出指令也被提供来与DCS交互。由于use级别确保代码不能直接读取或修改内存内容,这就确保了被动功能的完整性和不可伪造性

Probe使用CapReg检查对指针的解引用是否失败。

usage仅适用于有效功能,支持两种使用模型

隐式使用验证内存访问对有效能力的影响。这简化了对编译器的支持,并且可以透明地向现有的code添加功能。明确的使用是通过单独的说明来确定使用哪个CapReg。编译器可以使用它来最小化CapReg检查的数量,从而提高能源效率

4.1.4 域控制堆栈(DCS)

域控制堆栈(DCS)为溢出的权能提供内存,DCS是一种具有存储权能页的私有每线程内存结构,由于它是私有的,所以所有功能都可以被注入到它中,而不会破坏同步能力撤销。

DCS受到dcsb和dcsp寄存器的限制(图3),代码被隐式授予对该范围的Use访问权。非特权代码仅使用权能指令推/弹出间接地修改dcsp寄存器。

dcsb寄存器控制DCS框架。它只能由TCB修改,并且硬件确保pop操作不会跨DCS框架。§5.4进一步描述了DCS的操作。

4.1.5 异步功能撤销

异步功能撤销基于功能创建时设置的撤销字段,设置这些字段是一种特权操作,因为硬件使用它们来访问内存,撤销计数器的地址指向存储在内存中的撤销计数器。
只要某个功能的计数器值与存储在撤销计数器中的计数器值匹配,该功能就被认为是有效的。
当执行撤销指令时,codom首先验证该指令的标记是否与存储在功能上的标记相匹配。这确保了只有创建功能的域才能撤销它。codoms然后增加撤销计数器,通过将其保护级别设置为None,从而使所有使用相同计数器地址的功能失效。通过将不同的功能关联到不同的计数器,选择性撤销是可能的。
被动(存储在内存中)异步功能在从内存加载时,如果它们的计数器值与内存中的计数器值不匹配,则会惰性失效。

共享撤销计数器的有效的异步功能将立即失效。一种可能的实现是使用中央目录[27]来跟踪有效同步功能。在这种情况下,撤销核心向目录发出信号,这反过来会使使用同一撤销计数器的所有功能失效
由于大多数功能是同步的(而不是异步的),所以这种操作很少发生

撤销计数器可以重复使用246-1次,直到它溢出(引发异常),并且系统中可以存在248个不同的计数器。当计数器在溢出后被重用时,系统必须确保使用溢出计数器并存储在当前地址空间的容量存储页中的所有容量都无效。然而,撤销计数器(246−1)的大小使得此类事件极为罕见。更重要的是,系统不必跟踪授予访问权限的数据功能

4.2 在硬件中实现访问保护列表

最近使用的标记的APLs缓存在每个CPU的APL缓存中(第0步)。这个缓存由操作系统管理,允许多路使用标签和apl的无限空间。

缓存将PTCaps tag映射到它的硬件版本HwTag和相应APL (HwAPL)的一部分。

HwAPLs包含与缓存标签相对应的2位保护级别(如果不存在,则使用None)。
在TLB miss时,codom将标签的APL条目缓存到TLB中(第1步)。

iTLB由APL缓存表项中的tag、HwTag和hwapl扩展,以及页表项中的特权能力位扩展。
dTLB扩展了HwTag和能力存储位。这个信息可以存储在一个单独的结构上,以优化能量和延迟,因为它只在一个TLB命中之后才需要。

当获取一条指令时,来自iTLB的相关信息被存储在currdom寄存器中(第2步),该寄存器对当前域的信息进行编码。由于许多指令序列驻留在同一个页面中,因此可以对其进行优化,以减少iTLB查找的次数和传递该信息所需的存储量。

每当currdom寄存器的内容被修改时,它之前的值就被复制到prevdom寄存器,提供之前执行域的标识。(第6步)
当一个能力被创建时,currdom寄存器的标签和HwAPL被复制到CapReg中(第3步)。处于有效能力中的HwAPL永远不会存储到内存中,而是在APL缓存被激活时进行恢复(从内存加载,第5步)。
当修改APL缓存表项时,需要重新加载该CPU的TLB表项和CapRegs中的HwTag和HwAPL,不需要类似TLB击落的操作,因为每个CPU有一个独立的APL缓存,它的信息不会泄露到被动功能中。
图4描述了codom访问检查(图3 第4步)。dTLB中的HwTag用于索引currdom寄存器的HwAPL,并检索目标地址的保护级别。相反,currdom寄存器中的HwTag用于检查控制流指令。
例如,一个32个条目的APL缓存需要一个5位的HwTag和一个64位的HwAPL(32个2位条目)。这同样适用于功能,除了削弱的功能是通过使用更严格的功能和HwAPL访问保护级别来实现的。保护检查与实际的缓存访问并行执行,以隐藏它们的延迟。
在这里插入图片描述

4.3 域切换和无序执行

4.3.1 保护域检查和切换

currdom寄存器高效的完成了保护域检查和切换,iTLB提供的信息将发送到重命名阶段。
每当发生域切换时(当其内容改变时),就会重命名currdom寄存器。由于在该阶段之后不会更改寄存器,重命名阶段本身可以设置新值并将寄存器标记为就绪。
这消除了在域切换期间的RAW危险,并允许维护来自不同域的指令。实验测量表明,6个物理currdom寄存器足以消除所有RAW危害。

4.3.2 功能寄存器

功能寄存器在被修改时也可能产生原始的危险。CODOMs通过为活动功能提供一个2宽的寄存器窗口来缓解这一问题。寄存器capX用于当前指令序列,capXn用于“下一个”窗口。
写入capX也写入capXn。在保护域切换上交换窗口,从而允许软件消除capX上的原始危险。

5.系统软件:逐步提高安全性

CODOMs原语支持多个隔离粒度,从简单的用户/内核隔离到细粒度隔离,并针对每个特定情况调整性能配置文件。软件组件的隔离程度取决于代码是否可以被修改以充分利用codom以及每对域之间的信任关系。

5.1 域管理

PTCaps和APLs由TCB管理,由于域是由它们的标记标识的,所以域创建会获取一个未使用的标记,并为其构造一个APL,APL最初包含一个对自己标记的写授权。长期的跨域授权将条目添加到其他apl中,而短期授权可以通过功能直接处理。通过管理PTCaps, TCB可以精确地控制哪些页面具有存储功能,哪些页面具有访问特权指令的权限。

5.2 域边界

系统策略规定所需的域边界:哪些软件组件被分组到单个域,域之间需要什么类型的隔离。为此,动态加载的组件可以作为基础隔离单元;当前的系统广泛使用动态加载和链接,应用程序(包括操作系统内核)由可加载模块拼凑而成。域可以由一组紧密耦合的动态链接组件组成(例如,一个插件及其实用程序库),并通过调用彼此的例程进行交互。

一种简单的方法是为每个进程创建一个新域,然后可以调用TCB来创建更多的域。操作系统还可以提供声明总是与用户代码隔离的组件的机制。
例如,用户级二进制加载器可以是TCB的一部分,可以使用编码为二进制格式扩展、文件系统权限或强制性访问控制系统(如AppArmor)的线索。这适用于域关系及其入口点。

现有的加载器通过其过程链接表(PLT[18])识别动态模块的公共入口点。PLT是一个函数trampolines的数组(由加载器生成),它将入口点与调用它们的代码连接起来。
加载器可以通过只给调用者使用PLT的访问权(反过来,调用者获得对被调用者的完全访问权)来利用这一点来强制这些入口点。

5.3 例子:粗粒度隔离

在这里插入图片描述

以代码为中心的方法支持粗粒度隔离,只需对代码进行最少或不进行更改。例如,图5显示了一个与内核隔离的用户,以及相互隔离的网络和磁盘子系统。

codom包含了特权级别的实现:(1)只允许用户use access访问Tramp,一个系统调用蹦床,然后跳转到内核(类似于Linux中的vdso,或kipin L4 [16]);(2)在内核代码页上设置特权能力位;(3)给予所有内核级域对用户的完全访问权(一个简单的return可以在用户处恢复执行)。

与特权级别不同,codom还可以编码不完全有序的层次域关系。例如,本例中的网络子系统和磁盘子系统可以相互隔离。因为它们是作为Linux内核模块动态加载的,所以PLT可以用来控制它们对内核的访问,前提是它在向它们传递数据时使用功能。
考虑到codom的灵活性,有一种向后兼容的替代方案可以确保子系统的隔离性:让子系统完全访问内核,但不能在它们之间访问。

同样的技术也可以应用于用户级。例如,应用程序只能被授予对加密组件的使用访问权,而加密组件又具有对应用程序的完全访问权。这允许在不向应用程序公开加密密钥的情况下使用加密。

5.4 例子:细粒度的隔离

在这里插入图片描述

在更细粒度的场景中,关系不是分层的,需要进一步的操作:(1)双方都必须使用功能来传递对数据的引用,指针应该针对它们进行验证;(2)由于相同的堆栈跨域使用,能力被用来授予访问部分;(3)调用者或被调用者中的一些体系结构状态可能需要对另一方隐藏;(4)调用者和被调用者可能需要使用不同的DCS框架。由于策略是软件提供的(而不是硬连接的),其他组织也可能。此外,它们的需求依赖于域信任关系。

我们开发了一个概念验证编译器和链接器支持,利用现有的abi来处理这些情况。开发人员可以标记函数和数据,将它们放在特定的域中。该信息与域信任关系一起嵌入到ELF二进制文件中。此外,接口编译器为域入口点列表生成调用者/被调用者存根。例程根据域之间的信任关系进行专门化(如果域完全信任彼此,则可以达到空存根的极限)。即使它可以由链接器生成,为简单起见,接口编译器也会生成PLT代码(“门”)。与其他系统一样,缺乏高级编译器支持迫使程序员显式地管理指针验证和堆栈参数之外的数据能力。

图6显示了使用上述工具的两个域的组织。堆栈被放置在一个单独的域上,并且只能通过同步功能(CapReg0)访问。这将确保其他线程在跨域调用后不能篡改返回地址。gate代码具有特权能力bit(管理dcsframe)和对所有域的写访问权。由于用户代码不能访问以前的DCS框架,因此可以安全地使用它们存储跨域信息。在完全隔离的场景中执行完整调用/返回所需的步骤(混合软件/硬件隔离的上限开销)是:

1)调用者:调用者存根首先将所有没有作为参数使用的寄存器放入堆栈并置零,向被调用者隐藏所有不必要的信息。同样的情况也适用于功能(推送到DCS)。然后存根将任何过程参数推入堆栈(如果有必要的话),并通过从CapReg0派生CapReg1来授予它们访问权限,并调整CapReg0以禁止访问之前的框架。最后,它调用PLT, PLT执行gate代码。

2)门(调用路径):gate代码将常规堆栈指针和dcsb寄存器保存到DCS中,并通过调整dcsb和dcsp寄存器创建一个新的DCS帧。然后,它通过将调用者的返回地址保存到DCS,用指向自己的返回路径地址的指针替换它,将自己注入到被调用者的返回路径中,并为被调用者创建返回到该地址的功能(图6顶部的CapReg2;注意字号零的使用,以避免对齐检查)。最后,gate跳到被调用存根中。注意,这个跳转已经存在于动态加载对象的PLT中。

3)被调用者:被调用存根通过将所有不是结果的寄存器和功能归零来向调用者隐藏其状态,然后返回到注入的门(多亏了CapReg2)。

4)门(返回路径):gate恢复它保存的状态,展开DCS帧,并跳转到调用者的返回地址。展开DCS框架可确保隐式撤销存储在其中的所有同步功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值