SecDCP: Secure dynamic cache partitioning for efficient timing channel protection
摘要
多核处理器并发进程共享LLC提高资源利用率,但容易收到定时信道攻击。静态缓存分区可以消除定时信道但是开销大;本文使用动态缓存分区在运行时更改缓存分区大小,安全的同时保证性能。与静态缓存分区相比,性能提高43%,平均提高12.5%。
介绍
安全问题:最后一级核心是共享的,不同应用程序通过逐出彼此的缓存条目来互相干扰,并发起定时攻击。
现有方法:
- 静态缓存分区,共享缓存静态划分为多个分区,每个进程使用自己的分区,消除缓存干扰;但是分区大小无法适应每个应用程序变化的缓存行为,性能开销大。
- 先前的动态缓存分区技术,根据应用程序的运行需求动态改变分区大小,分区策略依赖应用程序的运行时行为,容易受到缓存定时信道攻击。
- 本文提出动态缓存分区,提供数据流的单向保护,防止信息从机密应用泄漏到公共应用,但允许信息从公共应用流向机密应用。使用公共应用程序的缓存需求来更改分区大小,不泄露机密应用的运行需求,系统性能也会整体提高。
相关工作
- 软件解决方案:依赖于重写软件来删除已知的定时通道,因此它们是针对特定攻击的,并且会产生显着的性能开销。
- 随机化方法:内存到缓存的映射被随机化以混淆攻击者的测量,并不能隐藏缓存访问的数量,随机化无法防御隐蔽通道攻击(在隐蔽通道攻击中,攻击者故意操纵缓存访问的数量来发送机密信息)。
- 分区方法:缓存被静态地划分为多个分区。每个分区只能被一个进程使用,从而消除了受害者和攻击者之间的缓存干扰。开销大,分区大小无法适应每个进程的运行时缓存行为。
- 动态分区:利用每个应用程序的运行时缓存需求信息来调整分区大小,很容易受到定时信道攻击。
威胁模型
目标:消除多核处理器中不同应用程序之间的缓存计时通道。
底层操作系统为每个应用程序分配一个安全类别,信息流动受限:信息不能在同一安全层中的两个安全类之间流动;允许信息从较低安全层流向较高安全层。安全策略定义了安全类之间允许哪些信息流,目标是防止不允许的信息流通过缓存计时通道。
SecDCP 假设一个强攻击者模型。
- 攻击者能够测量其自己的单独缓存访问的时间
- SecDCP 还处理隐蔽通道攻击,防止高安全层的受损应用程序将信息泄露给低安全层的应用程序
- SecDCP 假设硬件计数器由操作系统或虚拟机管理程序控制,并且用户进程无法访问,攻击者无法通过直接访问缓存硬件计数器来推断受害者的缓存行为。
SECDCP设计
挑战
- 1.分区大小取决于机密应用程序的需求
- 2.更改分区大小并未严格执行(以前的动态缓存分区方法在替换时强制执行新的分区大小。如果缓存分区的大小减小,缓存行不会立即被驱逐,它们保留在高速缓存中,直到来自另一个进程的某些高速缓存行替换它们。这意味着一个进程的缓存行的驱逐取决于其他进程的缓存访问——这是定时通道攻击的一个漏洞。)
分层安全策略本质上是不对称的,SecDCP利用这种不对称能解决上述问题。
两个安全级别的SecDCP
为了说明 SecDCP 的思想,我们首先描述具有两个安全类的简单层次结构的 SecDCP 设计。
设计规则:
- 1 分区大小与机密应用程序无关
- 2 更改分区大小的操作不会泄露机密应用程序的信息。
主要算法:
- 分区分配算法(PAA):负责在运行时分配每个分区的大小
- 分区执行机制(PEM):负责在PAA选择新的缓存分配后强制执行新的分区大小。
PAA分区分配算法
每个epoch结束,PPA使用L的需求分配分区大小;epoch内,利用监控器(UMON)记录L利用率得到未命中曲线,如下图。利用曲线可以计算增加缓存大小的收益和减少缓存大小的损失。假设一个epoch内L的缓存未命中次数为N,当前分区大小为X路,收益和损失定义如下:
gain=[MISS(X)-MISS(X+1)]/N
loss=[MISS(X-1)-MISS(X)]/N
把gain和loss喂到PAA,PAA定义了两个阈值$th_{inc}$和 $th_{dec}$来决定划分的cache路数,如果gain大于阈值$th_{inc}$则增加一路。
PAA只考虑L的需求,防止信息从H泄漏到L。L增加,H减少,尽管H性能减少,L性能增加的比更大,整体性能增大。为防止不公平和饥饿,总体设计总是为H保留一路。
PEM分区执行机制
PAA分配分区后,PEM执行新的分配,防止信息从H泄漏到L。
简单的方法是重新分配时刷新整个cache way,性能开销大。
把每一cache line和1bit的ID关联去表示哪个安全类获取cache line。当L的分区大小减少时,PEM检查ID并刷新所有属于L但要重分配给H的cache line。L的分区大小增加时,PEM不刷新从H分配给L的cache line。H’的缓存行可以被L的缓存行驱逐,H可以学习到L的缓存访问。然而信息流是无害的,
这一优化方法提高了H的性能,通过允许H在L分区的缓存行中缓存命中直到L驱逐他们。
效率分析
SecDCP 通过利用来自公共应用程序的缓存需求信息在运行时动态分区缓存;以前的动态缓存分区方案(例如基于实用程序的分区[12])使用来自所有应用程序的信息来决定分区大小。以下对两者进行比较分析:
我们将应用阶段分为缓存敏感阶段和缓存不敏感阶段。假设机密应用程序与公共应用程序同时运行。并发应用阶段的状态(PublicApp、ConfidentialApp)可以分为四种情况(I不敏感,S敏感):
- (I,I):对性能影响不大,SecDCP 和“基于实用程序的分区”实现相似的性能
- (I,S):两种方案都将大部分缓存分配给机密应用,因为公共应用不需要缓存
- (S,I):“基于实用程序的分区”将大部分缓存分配给公共应用,SecDCP 阈值选择得当,分配将达到相同的结果
- (S,S):“基于实用程序的分区”找到对两个应用程序都有利的分配; SecDCP 的分配取决于阈值
当公共应用程序对缓存不敏感时,SecDCP 实现的性能与基于实用程序的分区几乎相同。对于另外两种情况,SecDCP的性能依赖于阈值的准确性。我们的分析和实验结果表明,在许多情况下,使用一侧的信息足以进行动态分区。
一般情况下的SecDCP
为通用安全策略扩展 SecDCP 似乎很简单,但事实证明这种扩展并非易事。
PAA分区分配算法
PAA使用UMON跟踪每个安全类的缓存需求。如果一个安全类需要增加分区大小,它从更高级别的安全类获取缓存路,存在安全风险。
不安全设计
不失通用性地考零分三个安全级的不安全设计。
case 1:L1想增加分区大小,M1想减小分区大小,M2想保持分区大小不变。算法往往会将M1的缓存路分配给L1,如果M2知道L1是缓存不敏感的,但观察到它没有损失缓存路,能够推测M1可能在减少它的缓存路,因此M2可以学M1的运行时缓存需求。
case 2:假设M1想增加分区大小,M1通常从Hi得到缓存路直到Tier 3没有可用的缓存路。现在的安全类M2开始请求更大的缓存大小,Tier 3没有更多的缓存路则M2得不到,如果M2知道Tier的应用是缓存不敏感的,M2可以推测Tier 2存在更高的缓存需求。
分配漏洞总结如下:1.不同安全类型的动态仲裁基于缓存需求;2.先到先得分配原则
安全分配设计
避免先前提到的分配漏洞,假设通用的安全策略包括N层,每一层有Ki个不同的安全类型,为了描述的的简便,使用$c_{i,j}$表示安全层i的第j个安全类。
如果安全类$c_{i,j}$想要增加它的分区大小,PAA首先检查第i+1个安全层,有$K_{i+1}$个安全类。假设每个安全类最初有P个缓存路可以分配给其他安全应用,第i+1个安全层一共有$K_{i+1}*P$个缓存路可供分配。
为了避免先到先得的分配漏洞,PAA给每个不同安全类保存一定数量的缓存路。因为i层有$K_i$个不同的安全类,每个安全类最多能从第i+1层得到$K_{i+1}*P/K_i$个缓存路。PAA为安全类检查保留的缓存路。如果存在一个缓存路目前被一个安全类$c_{i’,j’}$占用,i’>i,则可以将该缓存路重新分配给 $c_{i, j}$,。如果多个缓存路满足条件,PAA 会使用严格的循环策略选择一个缓存路,从而避免基于缓存需求进行动态仲裁的问题。如果没有缓存方式满足条件,则 $PAA$ 将移动到层 $(i+2)$ 并重复相同的过程。该算法遍历从层 $(i+1)$ 到层 $N$ 的安全层;并在找到目标缓存方式或搜索达到第 $N 层时终止。
如果安全类 $c_{i, j}$想要减小其分区大小,PAA 将简单地将额外的缓存路重新分配给层 $(i+1)$ 中的一个安全类。如果层 $(i+1)$ 中有多个安全类,则 PAA 使用严格的轮询策略选择一个安全类。
PEM
分区大小增加时,PEM不会刷新缓存方式,但是分区大小减少时,PEM需要刷新特定缓存行,避免定时侧信道攻击。假设安全类$c_{i, j}$ 放弃缓存行重新分配给另一个安全类 $c_{i+1, j}$,PEM 会以重新分配的缓存方式检查每个缓存行,如果缓存行的安全等级不等于或低于 $c_{i+1, j}$,则需要刷新该缓存行。
评估
实验方法
使用架构模拟器gem5。
运行了由 SPEC CPU2006程序组成的多程序工作负载。
性能
将 SecDCP 与其他三种方案进行了比较。第一种方案是静态分区,它将缓存静态划分为两个大小相等的分区。第二种方案是无分区,其中使用 LRU 替换来管理整个缓存。最后一种方案是基于实用程序的分区,使用两个程序的缓存需求动态地对缓存进行分区。静态分区和 SecDCP 是安全的,而无分区和基于实用程序的分区是不安全的。
SS 工作负载的性能。
SS 工作负载是两个缓存敏感程序的混合。我们将每个方案的加权加速归一化为静态分区的加权加速。对于这些工作负载,SecDCP 平均比静态分区提高了 12.5%。在某些情况下,改进可以达到 40%。这是因为 SS 工作负载对缓存敏感,需要有效利用有限的缓存空间。静态分区会产生高性能开销,因为它无法调整分区大小以满足每个程序不断变化的缓存需求。当 $L$ 程序能够通过更大的分区大小提高其性能时,SecDCP 会增加 $L$ 的分区大小。另一方面,SecDCP 在不会对 $L$ 程序的性能造成太大影响的情况下减小了 $L$ 的分区大小,从而为 $H$ 程序提供了更多的缓存空间,从而可以机会性地提高其性能。平均而言,SecDCP 实现的性能与无分区和基于实用程序的分区相似。
SI 工作负载的性能。SI 工作负载是随机选择的缓存敏感程序和缓存不敏感程序的组合。平均而言,SecDCP 比静态分区提高了 11.4%。对于 SI 工作负载,SecDCP 会逐渐减小缓存不敏感程序的分区大小,大大提高缓存敏感程序的性能。基于实用程序的分区也可以实现相同的目标,这就是为什么我们看到每个工作负载的 SecDCP 和基于实用程序的分区之间都有类似的加速。我们还看到,在某些情况下(例如,bzi_lib),SecDCP 的性能比静态分区差。这是因为我们选择的阈值(即 20%)与 bzip2 的缓存需求不匹配。在此工作负载中,bzip2 不断减小其分区大小,因为损失(在公式 2 中定义)小于 20%。但是,libquantum 是一个流式处理程序,无法利用不断增加的缓存大小。因此,系统性能会降低。
II 工作负载的性能。两个程序都对缓存不敏感。由于程序的性能与缓存大小的依赖性不大,因此所有方案的性能都类似。我们将 SecDCP 与静态分区进行比较。静态分区方案将缓存划分为四个分区,每个分区为四向缓存。我们选择了 32 个四程序工作负载,包括 SS、SI 和 II 类型(每个类别两个程序)。结果表明,与静态分区相比,SecDCP平均提高了6.4%。对于相当多的基准,改进可以达到 20%。但是,我们确实看到某些工作负载的 SecDCP 性能比静态分区差。这又是由于阈值(20%)的不精确性。
阈值和安全策略
尝试了 {2%、5%、10%、15%、20%、25%} 集合中的不同阈值。我们发现阈值会显著影响大多数工作负载的性能,因此选择一个好的阈值很重要。对于大多数工作负载,阈值 20% 的性能良好,平均在最佳阈值的 2.5% 以内。
结论
我们提出了 SecDCP,这是一种安全的动态缓存分区方案,可提高静态缓存分区的性能,同时满足分层安全策略指定的安全要求。SecDCP 仅使用公共应用程序的缓存需求来动态确定缓存分区大小。然后,SecDCP 仅在必要时刷新缓存行,从而安全有效地强制执行新的分区大小。SecDCP 还支持对常规安全策略的非平凡扩展。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以在下面评论区评论