没有合适的资源?快使用搜索试试~ 我知道了~
1307本作品采用知识共享署名国际4.0许可协议进行许可。DangZero:通过直接页表访问进行弗洛里斯·戈特f.c. vu.nl阿姆斯特丹自由大学科恩·科宁koen. vu.nl阿姆斯特丹自由大学赫伯特·博斯ertb@cs.vu.nl阿姆斯特丹自由大学克里斯蒂亚诺·朱夫里达giuffrida@cs.vu.nl阿姆斯特丹自由大学摘要释放后再释放的漏洞仍然难以检测和缓解,使其成为流行的漏洞利用来源 现有的解决方案存在不切实际的性能/存储器开销,需要专门的硬件,和/或仅保证保护,但不保证检测。在本文中,我们提出了DangZero,这是一种新的解决方案,可以在漏洞发生时检测使用后释放漏洞。 DangZero建立在传统的页面保护和别名方案之上,在该方案中,对象在释放后无法访问,并且随后的访问被立即检测到。与使用基于别名的检测的先前解决方案相比,DangZero依赖于环0中的直接页表访问来提供更有效的实现。关键的思想是,通过让程序的分配器直接访问页表,我们可以有效地管理和无效易受攻击的对象。为了安全地实现这一点,我们构建了一个类似于unikernel的设计,其中虚拟化提供了ring-0(来宾模式)访问、隔离以及与现有Linux程序的兼容性。此外,我们显示直接页表访问作为一个有效的构建块垃圾收集风格的别名回收。这样做可以安全地重用释放的区域,并解决最先进的基于别名的解决方案中的可伸缩性问题。 我们的实验结果证实,DangZero提供了准确的检测保证,其开销显著低于竞争的最先进的解决方案(例如,长期运行的程序(如Nginx Web服务器)的饱和吞吐量下降18%)。CCS概念• 安全和隐私→软件安全工程。关键词内存安全,释放后重命名检测,页面权限ACM参考格式:Floris Gorter,Koen Koning,Herbert Bos,and Cristiano Giuffrida.2022年。 Dang-gZero:通过直接页表访问进行高效的释放后检测。 在2022年ACM SIGSAC计算机和通信安全会议(CCS '22)的会议记录中,2022年11月7日至11日,美国加利福尼亚州洛杉矶。ACM,纽约州纽约市,美国,15页。https://doi.org/10.1145/3548606.3560625CCS©2022版权归所有者/作者所有。ACM ISBN978-1-4503-9450-5/22/11。https://doi.org/10.1145/3548606.35606251介绍临时存储器错误仍然是计算机系统保护中的一个重要问题。在CWE软件中最常见和最具影响力的25个问题中,释放后修复(UAF)错误排名第7 [40]。此外,Microsoft报告称,UAF漏洞是漏洞的第二大常见根本原因,并且仍然是首选的攻击目标[39]。 防御这些威胁的方法可以分为立即检测或(仅仅)防止利用。提供错误检测在离线(例如,测试)和在线(例如,sampling [51])部署场景,以及bug分类。不幸的是,这两类现有的解决方案都存在问题。保证UAF保护通常比即时检测更有效,并且现有的保护系统试图通过各种技术来最小化其性能影响:类型安全内存重用[5,52](然而,其只能保持类型安全),引用计数[50](然而,其不适用于任意C/C++程序),一次性分配[54](然而,其不能绑定内存使用)和垃圾收集风格(GC)解决方案[4,19,23,34]。 虽然GC风格的解决方案已经获得了报告效率的动力,但最近的研究证明了GC风格技术的重要基础成本-通常隐藏在并发性和慷慨的内存/计算能力配置之后[14]。进一步的缺点是,许多解决方案不能防止不依赖于内存重用的漏洞利用[5],而大多数基于编译器的解决方案(例外[4,5,19,54])不能处理未修改的二进制文件。最重要的是,这类解决方案中没有一种能够提供强大的UAF检测保证。大多数以UAF检测为重点的系统依赖于编译器工具来跟踪并使指向已释放对象的指针无效[30,49,53,55]。尽管进行了专门的优化[53],但这样的解决方案仍然会带来不小的性能开销。成本较低的解决方案依赖于特殊的硬件支持[22,57](限制可部署性)或对象ID [9,13,15,22,25,41](或中毒值[47])来检测UAF(仅),直到发生预定数量的内存重用事件(限制安全保证)。在这里,大多数基于编译器的解决方案也不能处理未修改的二进制文件。尽管如此,文献[17,18]中这种解决方案为每个内存分配创建一个新的虚拟页(别名),并将其映射到与原始对象相同的物理页因此,每个对象都接收一个唯一的(未使用的)指针,并且对象(及其指针)可以很容易地通过撤销页面映射而在释放时无效。不幸的是,这种基于别名的解决方案依赖于内核来进行页面保护和别名,并且由于额外的CCSFloris Gorter、Koen Koning、Herbert Bos和Cristiano Giuffrida1308系统调用和内核管理成本。此外,由于虚拟内存地址空间耗尽,最先进的解决方案[17]仍然存在不切实际的可伸缩性问题-正如我们将展示的那样,在负载沉重的Web服务器上,这在几天内就会发生。在本文中,我们介绍了DangZero,一个高效,可扩展,二进制兼容的UAF检测系统。关键思想是依赖于环0中的直接页表访问(即,通常仅运行OS内核的最高特权级别)以更有效的方式实现传统的基于别名的方案。DangZero从现代的类unikernel设计[29]中汲取灵感,依靠虚拟化扩展和特权后端(如Kernel Mode Linux(KML)[36])来提供对页表的直接访问。这种策略允许我们透明地运行(和隔离)任意用户空间程序在环0来宾模式,同时安全地提供他们直接访问自己的(来宾)页表。我们表明,直接访问页表可以从两个方面使基于别名的UAF检测系统变得实用首先,通过授予程序的内存分配器页表访问权限,它可以通过直接更新页表映射来有效地管理别名。这样做消除了操作系统参与和相应的(系统调用和内核管理)开销的需要。其次,页表已经跟踪了关于程序的虚拟内存地址空间的重要元数据,并且还可以容纳额外的应用程序特定的元数据。 我们使用该观察结果来设计有效的别名回收系统,并解决先前基于别名的解决方案的虚拟存储器地址空间耗尽问题[17]。目标是允许安全地重用虚拟地址,一旦我们确认指向对象(别名)的悬空指针不再存在。我们的设计在精神上类似于先前的GC式解决方案[4,19],但有两个关键区别。首先,DangZero当前位精确定位驻留页以扫描悬空指针)。此外,由于DangZero回收虚拟别名而不是物理内存中的对象,因此我们的回收策略不倾向于GC风格技术的典型性能/内存权衡[14]。事实上,正如我们将看到的,我们的别名回收策略非常有效,允许DangZero(检测系统)在长期运行的基准测试(通常具有频繁,短暂的分配)上甚至超越最先进的GC式保护系统[4,19],而不必诉诸内存过度配置或在空闲CPU核心上并发回收我们已经在标准基准测试(SPECCPU 2006和2017)和长期运行的 应 用 程 序 基 准 测 试 ( 特 别 是 Nginx Web 服 务 器 ) 上 对DangZero进行了在SPEC CPU 2006上,DangZero报告的几何性能开销仅为16%(在SPEC CPU 2017上为22%),而最先进的基于别名的UAF检测系统为40%[17]。在Nginx上,DangZero报告的饱和开销低至11- 18%,显著低于最先进的UAF保护/检测系统,并且内存开销始终适中(且有限)。概括起来,我们做出了以下贡献:基于虚拟化直接页表访问的别名分配检测释放后使用漏洞的新方法。• 一种新的别名回收解决方案• 一个使用KML作为特权后端的DangZero原型i n t* ptr = malloc( s i z e o f( i nt)); free(ptr);int tb = * ptr ;清单1:释放后重新加载示例一项评估表明,DangZero在长期运行的基准测试中显着优于现有的检测系统,甚至是最先进的GC式保护系统• 代码可在:https://github.com/vusec/dangzero2背景2.1Use-after-Free释放后释放(UAF)错误是在不安全的语言(如C和C++)中出现的临时内存错误,由于堆分配的对象在已经被释放后被解引用而引起。 这些错误是可能的,因为(所谓的悬空)指向释放对象的指针保持不变,即使所指向的内存位置不再有效。攻击者通常利用UAF漏洞和相应的悬空指针,在释放后但在使用前强制内存重用。然而,根据分配器的设计,不重用内存的攻击(分配器元数据扮演目标对象的角色)是可能的[5]。清单1显示了一个UAF错误的简单这些bug的时间特性使得它们很难检测,无论是在代码中还是通过程序分析,并且许多旨在消除UAF bug的缓解设计都受到显着(运行时/内存)开销的影响。在本文中,我们表明这样的成本是不是根本和直接的页表访问可以解锁一个有效的和可扩展的基于别名的解决方案。2.2页表页 表 是 一 种 软 件 维 护 的 数 据 结 构 , CPU 的 内 存 管 理 单 元(MMU)使用它来描述如何将虚拟内存映射到物理内存。在大多数常见的体系结构中,页表被存储为分层树,其中虚拟地址的某些位用于选择页表的相应级别中的条目。 页表条目(PTE)将地址存储到树的下一级,或者(对于最后一级)存储地址转换的结果。此外,PTE存储有限数量的元数据位,例如该映射的许可以及条目是否有效(“存在”)。最后,每个PTE都包含一些被硬件忽略的位,因此可以被操作系统用于其他信息。大多数64位架构使用4级页表,每个表由512个条目组成,产生48位(256 TB)虚拟地址空间。一些现代的CPU还具有5级页表,但为了简单起见,本文的其余部分我们假设为4级页表结构。有许多不同的名称来指代这些结构的不同级别;在本文中,我们简单地将它们称为L4到L1(L4是根/第一个表,L1是叶子/最后一个级别)。通常,每个进程都有自己的一组页表,描述该进程的地址空间Linux将可用地址空间分成两半,将下半部分留给用户空间,将上半部分留给自己的数据。 这意味着每个用户进程有128 TB的可用虚拟地址。为了请求新的映射或更改现有的映射,进程(及其内存分配器)发出系统调用,如brk、mmap和mremap。在页面顶部··DangZero:通过直接页表访问进行高效的释放后检测CCS1309表,Linux还维护自己的数据结构,包含每个连续虚拟内存区域(VMA)的当使用硬件虚拟化扩展来运行虚拟机(VM)时,存在两个级别的页表:客户机页表和主机上的扩展页表(EPT)前者的行为与上面描述的完全一样,并给客户机一种直接在硬件上运行的错觉。 EPT由管理程序管理,与普通页表类似,不同之处在于它将每个客户机物理地址转换为主机物理地址。2.3访问特权CPU功能为了实现直接页表访问,DangZero需要访问通常为Ring 0保留的特权功能 Dune [6]项目通过使用轻量级虚拟环境提供了一个实际的实现。特别地,应用在专用“虚拟进程”环境的环0(客户模式)这为应用程序提供了对所有特权特征的访问(例如,客户页表),同时仍然通过管理程序与(主机)系统的其余部分隔离Dune使用了一个小型的库操作系统(libOS)在客户机中与应用程序一起运行,以管理基本的内核任务,以便未修改的Linux二进制文件可以运行。此外,一个专门的(基于KVM的)虚拟机管理程序映射了来宾通过VM发出的系统调用,并将其退出到主机上的Linux系统调用。类似的精神是内核模式Linux(KML)[36]项目,它允许程序在环0中与Linux内核一起运行。KML的优点是不需要为每个系统调用都提供昂贵的VM出口。 与Dune类似,KML仍然需要一个虚拟环境来进行隔离,也就是保护系统的其余部分。由此产 生 的 设 计 有 效 地 将 Linux 转 换 为 libOS , 并 将 过 程 转 换 为unikernel- 最近的应用程序优化工作表明KML 可以有效地使用[29]。3威胁模型我们假设一个标准的威胁模型,攻击者试图利用受害者二进制程序(用不安全的语言编写)中的任意释放后使用漏洞,以实现信息泄露、权限升级等目的。我们考虑任意释放后使用漏洞,无论内存重用和其他利用技术(例如,记忆按摩)。我们假设程序没有其他漏洞(例如,缓冲器溢出)或以其它方式利用正交缓解来针对它们硬化。4DANGZERODangZero通过为每个堆分配的内存对象创建不同的虚拟地址,立即防止UAF错误发生。每当一个对象被释放时,它的内存就会通过使虚拟内存映射无效而变得不可访问。这是通过页面保护标志完成的,并使进一步(UAF)访问无效。为了减少物理内存开销,我们允许对象仍然共享物理页面。 由于映射的最小粒度是在页面级别,因此我们为每个分配的对象创建新的唯一的别名,这些别名可以在释放时无效。图1提供了Dan-gZero的主要组件及其交互的概述。在DangZero的核心是一个覆盖虚拟存储器地址空间页表0xff96000120(化名)0x500120(canonicallibc_malloc()马略卡0xff96000120(化名)用户应用客人戒指0取料机覆盖分配器默 认 内存 分 配器别名进程内存安装后端操作系统(主机环0)图1:DangZero的组件概述分配器,其用作默认存储器分配器的扩展(例如, glibc),并且可以直接访问正在运行的进程的页表。拦截堆分配请求,以便创建别名页并将其返回给用户。堆释放请求又被拦截,以使别名映射无效。特权后端提供对受限特性的访问,特别是直接页表访问 DangZero不需要对程序进行插装,也不需要底层的分配器,因此可以在现成的二进制文件上工作。覆盖分配器。 DangZero的覆盖内存分配器可以被视为用户空间程序和故障内存分配器之间的代理。在请求存储器分配时(例如,malloc),DangZero首先将此请求中继到默认内存分配器。 默认分配器可以从操作系统请求虚拟(和物理)内存(通常通过brk或mmap),并最终将分配的堆槽的虚拟地址(我们称之为对象的规范地址)返回给覆盖分配器。然后,我们的分配器在虚拟内存地址空间的未使用区域中创建一个或多个别名页,计算我们所称的对象的别名地址。由于我们的分配器可以直接访问进程页表,因此它可以直接有效地创建这些别名映射。最后,我们透明地将相应的别名地址返回给用户程序,用户程序像往常一样使用这个地址引用分配的对象,而不知道这涉及到别名。当程序释放对象时,我们执行类似的操作。 在截获一个free(或等效)调用时,我们首先直接在页表中使别名映射无效。然后,我们计算对象的规范地址并将其传递给原始free,以便其物理内存可以由默认分配器重用。回收垃圾。 为每个对象提供它自己唯一的别名地址最终会导致虚拟内存耗尽。即使在现代系统的大型虚拟地址空间上,在重负载的服务器程序上运行几天内也会发生中断。为了应对这一挑战,DangZero依靠CCSFloris Gorter、Koen Koning、Herbert Bos和Cristiano Giuffrida1310obj-N目标2目标1obj-N目标2目标1obj-N目标2目标1浏览虚拟页面标准虚拟页面图2:页面别名:每个对象一个虚拟别名页面别名回收器,以实现别名地址的安全重用回收器周期性地标记无效(即, 如果它确定指向别名空间的(悬空的)指针不再存在,则将别名空间的(先前释放的)区域作为可重用的以用于将来的别名创建。 这个组件在精神上类似于(保守的)垃圾收集器,但只回收虚拟(而不是物理)内存,并与覆盖分配器以及页表数据结构紧密集成。在本节的其余部分,我们将更详细地描述DangZero的操作和组件4.1通过页面保护实现时间安全DangZero的核心思想是使用页面保护作为一种机制来防止和检测释放后使用错误。 通过移除应用程序对释放内存的访问,硬件中的内存管理单元(MMU)将在检测到无效访问时自动引发异常。然而,MMU在页面(典型地,4096字节)粒度上 将每个对象放置在它自己的(物理上支持的)页面上会导致由碎片引起的大量内存开销。因此,DangZero建立在别名的思想上[18],每个对象都有自己的虚拟别名,但多个对象共享同一个底层物理页面。图2显示了不同页面之间的关系。我们将默认内存分配器返回的虚拟页面称为规范页面。根据设计,这些页面可以包含多个内存对象(4K页面上最多128个对象支持规范页面的物理页面与对象匹配然后,对于每个单独的对象,都有一个不同的别名页,其页内偏移量与规范页相匹配。 如果原始分配跨越多个页,则结果对象将具有相同数量的对应别名页。在释放别名时,我们需要相应的规范地址,这样我们就可以启动默认分配器的释放过程并释放物理内存。 为此,我们用规范地址指针填充每个内存分配。实际上,这意味着我们将每个malloc ( n ) 调 用 都 更 改 为 malloc ( n+sizeof(void*))。4.2创建别名并使其无效虚拟地址映射在进程页表中维护,由操作系统内核管理。通常,对于更新映射的进程,它需要通过系统调用,这是一个昂贵的操作。Linux等操作系统也不是为创建(大量)自定义映射,并且因此在可以设置什么方面是限制性的此外,由于为每个别名映射保留的元数据(如VMA数据结构),内核内存使用经常爆炸式增长。使用DangZero,我们可以直接从覆盖分配器修改页面表,完全不受操作系统的控制DangZero接管虚拟地址空间中未使用的区域,该区域从未被内核触及,并直接写入对应于该区域的页表页条目。为了方便对(通常)受限资源的访问,我们的特权后端提供了安全访问。DangZero的设计与所使用的确切机制无关,但通常它必须支持对页表的直接读写访问,并允许TLB刷新,同时确保系统其余部分的安全性和隔离性。 我们的主要后端使用运行内核模式Linux(KML)的客户机将Linux转换为libOS;第5.1节提供了有关这些底层机制的更多细节。为了在请求内存分配时创建别名页,我们必须考虑请求分页的影响。由于Linux在其内存系统上应用了请求分页,因此堆分配在实际使用之前没有物理支持。但是,如果不知道分配的物理地址,我们就无法创建别名映射因此,分配器接触规范页面,以便强制为规范对象提供物理支持,之后我们可以设置页面表,以确保别名页面指向相同的物理页面。实际上,我们没有观察到强制填充页面的开销损失,因为页面通常由默认分配器使用或在分配后不久使用。如果这种方法会给某些工作负载带来困难,那么另一种设计可以使用自定义页面错误处理程序,这样就可以创建别名页面只要堆分配接收到物理支持。4.3取料机为了支持可能耗尽别名空间的长时间运行的应用程序该组件的主要目标是允许安全地重用以前释放的别名页。如果没有引用(即,指针)存在于与别名页面相关联的对象相反,如果曾经存在一个10页的大对象,现在被释放了,并且程序中的任何地方都存在一个指向这10页中任何一页的(悬空)指针,那么没有一个被认为是安全的。回收机的主要设计目标,除了安全重复使用,是轻量化。回收器很少运行,因此,它的正常操作(当不需要清理时)在性能和内存开销方面应该是最小的。因此,我们的设计灵感来自保守的垃圾收集器(GC)[10],但为DangZero的环境量身定制。与传统的GC不同,回收器对于系统的物理内存开销并不重要当达到预定义的无效页面数量时,别名回收程序将自动运行。由于我们永远无法回收仍在使用的内存(即,未释放),则水印排除任何此类页面。与保守GC类似,回收器由标记和清除阶段组成在标记期间,扫描程序的所有存储器和寄存器以寻找指向别名空间的可能指针对于任何指向已释放别名对象的指针,我们标记DangZero:通过直接页表访问进行高效的释放后检测CCS1311L1页表图3:页面表中的缓存回收器元数据该对象仍然被引用。然后,在扫描过程中,我们覆盖别名空间中所有释放的对象,并将所有未标记的对象返回到覆盖分配器的别名空间。回收器忽略所有未释放的对象,对象在释放时归零,以避免标记[19]时的循环依赖当跨分配重用物理页时,归零对象还可以防止未初始化读取泄漏数据目前,标记和扫描阶段需要暂时停止-ping世界,这意味着目标应用程序实际上是暂停的。这是垃圾收集中的一个常见范例,用于获得程序内存的一致视图还有其他可能的优化,例如并发和并行标记和扫描。特别是,直接页表访问实现了快速脏位扫描等优化[6]。然而,我们选择了更简单的stop-the-world方法,因为回收的开销足够低,我们不认为更复杂的并发回收是一个需要优先考虑的特性回收器必须跟踪特定的元数据,以便正确执行其标记和清除操作首先,它需要了解每个别名页面的状态:它是可用的(可用于创建新别名)、正在使用的(由活动对象使用)还是无效的(使用free()显式释放的死对象的一部分)。此外,回收器需要知道无效对象的对象边界在哪里,因为指向对象中任何位置的指针都不允许重用它的任何页面。最后,在标记阶段,回收器需要记住哪些对象在扫描阶段被标记。回收器将所有这些信息存储在页表本身中,实际上不会产生内存开销,如图3所示。 我们免费获得此存储,因为无效的别名页(即,在调用free()之后)在它们各自的页表条目(PTE)中被设置为不存在,这意味着PTE中的所有其他位都未被使用并被硬件忽略因此,我们使用PTE位之一来区分可用条目和无效条目。此外,我们使用另一个位来标记每个对象的结束。因此,可以通过查看来重建对象边界对于此位未置位的连续PTE,后跟一个置位。 图3在右边显示了一个带有几个PTE的L1页表,其中当前位由P列表示,无效位存储在一个忽略位中,指示对象结束的位也是如此。该图描绘了使用中对象(例如,前两个条目)、无效对象(条目3-5和条目8)以及可用条目(条目6-7)。页表回收和压缩。 如果页表的512个条目中的任何一个仍然是有效映射(即, 当前位被设置),则需要保持整个页表,并且因此它为我们的元数据位提供空闲存储空间。然而,当所有条目都不存在时(即,可用或无效),仅为元数据位保留它会浪费大量空间。一个4K的页表有512个64位的条目(每个条目描述一个页面),但是我们的元数据每个条目只需要2位。因此,当所有条目都不存在时,我们将页表压缩为128字节的数据,并释放原始页表。 我们可以将32个这样的压缩页表放入一个4K页中,并使用slab分配器管理这些内存块[11]。然后,我们将L2页表指向这个压缩条目,并在页表条目中设置一个特殊位来指示它的存在(图3中的cpt)。在此之上,我们确定了页表可以处于的两种常见状态,这允许进一步压缩。通常,一个(压缩的)页表完全被无效的对象填满。另外,页表通常仅包含其中每个页是单独对象或每个页属于同一大对象的条目(即,分别设置所有或不设置对象结束位)。在所有这些情况下,整个压缩页表(128个字节)被压缩成单个位,存储在更高级别的页表中(图3中最后一个L2条目中的ca)。 正如我们将在第6节中展示的那样,压缩大大减少了DangZero的内存开销。5执行我们将DangZero实现为一个共享库,它通过LD_PRELOAD覆盖故障内存分配器.此外,DangZero需要一个后端来直接访问页表,我们将在下面的部分详细描述。5.1安装后端DangZero的关键组件之一是它的特权后端,它负责从(用户空间)分配器直接访问特权直接修改页表(并发出相应的TLB刷新)的能力对我们的系统性能至关重要。为 此 , DangZero 这 有 效 地 将 Linux 转 变 为 一 个 高 效 的unikernel [29]。 它还为应用程序提供了系统上的所有特权,允许它调用内核代码(例如,alloc_page用于分配物理页面)并写入任何内存。然而,KML仍然是Linux的底层,因此受益于所有现有的Linux驱动程序并支持所有现有的Linux二进制文件。但是,为任意用户空间程序提供内核权限本质上是不安全的:程序中的错误或漏洞可能会影响或破坏系统上的任何其他程序和用户addr0x54000x5401L2页表地址P奥布延0x12341符号P11投资者0投资者0投资者000对象inv 00x7820 10xabcd cpt 0CA 0压缩表I O I O I O I O...1 0 1 0 1 1 0 0 1 0...CCSFloris Gorter、Koen Koning、Herbert Bos和Cristiano Giuffrida1312ffff8000000000← 128 TB →ffffffffffffff几百GB的RAM,大部分区域都没有使用。因此,我们可以保留大部分未使用的区域来托管别名页表。64 TB的直接映射对应于最高级别(L4)页表条目273至400。假设系统最多使用27x 512 GB物理内存(对于可预见的未来来说,这是一个图4:内核空间虚拟内存布局。因此,像其他单内核系统一样,我们在一个(轻量级)虚拟机(VM)中运行我们的系统,它将客户机与系统的其他部分隔离开来 通过将客户系统专用于单个进程,我们考虑单个安全域,因此滥用正交漏洞的攻击者不能利用页表访问来危害其他安全域(例如,其它应用或主机)。此外,这种设置可以提供比裸机基线更高的性能,因为KML内核可以专门针对在虚拟化硬件上运行单个应用程序进行调整[29]。DangZero不包括这样的优化,以公平地评估其设计引入的开销。对于DangZero,我们使用了最新的Linux内核和可用的KML补丁,即,v4.0。 我们对KML内核应用了两个补丁,以便它可以在当时(20.04)的最新LTS版本的Ubuntu上正常运行。 KML项目在glibc2.11中引入了一个补丁,将系统调用改为直接调用,我们将其移植到glibc 2.31(所用操作系统的默认值)。glibc的现代版本允许我们在我们的操作系统(9.4.0)上使用默认的gcc版本。对于某些功能,我们需要访问内核数据结构(例如,遍历VMA 结构)。 这可以方便地在内核模块中实现,由于KML,我们可以通过常规函数调用直接从分配器调用该模块。5.1.1替代后端:沙丘。 除了KML,我们还为DangZero实现了一个替代后端,以展示其设计的广泛适用性。 为此,我们选择了Dune [6],这是一个旨在授予用户应用程序访问特权硬件功能的hypervisor和libOS。我们基于沙丘的DangZero原型在SPEC基准测试中表现出与KML几乎相同的性能。但是,在系统调用密集型应用程序(例如,Nginx),Dune基线本身报告了显著的性能开销(高达60%),因为Dune必须将系统调用转换为更昂贵的VM退出,导致DangZero/Dune的总体开销更高。因此,本文的其余部分仅使用DangZero的KML后端进行评估。5.2网页表格虽然KML允许我们的分配器直接访问内核内存,比如页表数据结构,但它不能轻松地完全控制它们。特别是,Linux本身并不知道DangZero,并且会覆盖我们的分配器在用户空间映射中所做的任何更改。相反,DangZero在Linux内核地址空间的一个通常保留的区域中运行(设计上不受内核影响)。 这种策略有两个优点:它不需要修改内核来允许页表访问共享,并且它不会减少用户态可用的虚拟内存量。图4显示了一个(简化的)内核空间虚拟内存布局。内核保留64TB的虚拟内存区域,用于直接映射所有物理内存。因为大多数机器最多条目300到400可用于我们的虚拟别名页面。此区域最多可托管50 TB的虚拟别名空间,相当于最多125亿个并发4K别名页面。5.3承载叉直接在进程的页表中创建别名映射时绕过内核的缺点是,内核在执行诸如fork之类的操作时不知道这些页。 fork系统调用创建一个子进程,其中父进程和子进程的页面是共享的。在修改共享页面时,写入时复制(CoW)技术确保使用页面的副本不幸的是,别名页不会被复制到子进程的页表中,即使它们被复制了(例如,通过存在于诸如VMA之类的正常内核数据结构中),它们将错误地保持与父的物理页的别名。解决这个问题的直觉是,我们在子进程中的所有规范页面上强制触发CoW,使页面获得新的物理支持。在此之后,我们可以创建适当的别名页面,并使它们指向子页面中的这些新物理页面。然而,在子页面中重新创建别名映射以指向新的物理页面是困难的,因为我们既没有规范到阴影的映射,也没有父物理到子物理的映射。对于fork这样的不常见操作来说,维护这样的数据结构将是非常昂贵的。为了克服这个问题,我们将以下算法作为结尾应用于fork库调用(也如清单2所示)。我们创建一个父物理地址到规范地址的临时映射,通过遍历父地址中每个规范地址的页表并读取结果PTE中的物理页来生成该映射。使用这个物理-规范地址对的映射,我们重新构造子进程中的别名页表对于父页面中的每个别名页面,我们通过页面遍历获得其物理地址,并使用物理地址作为键在映射中查找相应的规范地址然后,我们触摸虚拟地址以触发CoW,从而在孩子中产生新的物理支持接下来,我们使用子对象中的规范地址的页面遍历来查找新的子对象物理地址。最后,我们在子节点的别名空间中创建相应的页表条目,以便新的别名页指向新的物理备份。在整个算法中,我们同步父节点以等待子节点完成这些操作,从而使内存状态保持一致。5.4优化页面条目查找直接访问页表使我们能够优化设计,专门用于管理别名页。 由于我们通常可以线性增长别名空间,因此我们可以对页面遍历的细节进行假设。 更具体地说,我们可以将指针缓存到中间页表级别,以避免不必要地重复这些查找。这种优化得益于这样一个事实,即在线性设计中,直接映射物理量管理程序vmallocKASAN核心文本DangZero:通过直接页表访问进行高效的释放后检测CCS1313//构造物理->正则映射(pre-CoW)为canon_addressin堆:phys_addr = page_walk(canon_addr)map[ phys_addr ] = canon_addr// reconstruct子级中的别名映射为 别名地址在alias_space:phys_addr =page_walk(alias_addr)canon_addr =map [ phys_addr]* canon_addr ;//触发CoW强制新的备份 child_phys_addr=page_walk(canon_addr)pt_map(alias_addr,child_phys_addr)清单2:在fork之后在子进程中重新创建别名映射。(L4和L3)条目很少更改即使是最低页表级别的查找(L2到L1)也仅每512个别名页改变一次实际上,每次创建一个新别名时,我们都会增加L1页表索引。 如果该索引达到512,则我们绕回,对L2到L1执行新的查找,并在必要时以级联方式递增先前的级别。这种优化显著减少了查找的数量,并将它们与更便宜的增量操作交换。6评价我们使用不同的基准测试评估了DangZero的安全性、性能和内存对于我们的安全评估,我们使用Juliet测试套件并确认检测到已知的CVE。 对于我们的性能/内存开销评估,我们使用了SPECCPU 2006和CPU 2017基准测试(针对CPU和内存密集型现实世界程序的混合)以及Nginx和Apache Web服务器(代表长时间运行,系统调用和分配器繁重的程序)。所有报告的数值均为5次运行的中位数,以降低噪音(除非另有说明)。对于SPEC基准测试套件,我们使用所有基准测试的几何平均值(geomean)对结果进行平均。6.1安全评估我们根据经验证实,DangZero可以通过运行NIST Juliet Test Suitev1.3 [26]来准确检测和缓解释放后使用错误。该测试套件包含数百个测试用例,按漏洞类型(CWE)分类,并测试误报和漏报。DangZero成功地检测到测试套件(分别为CWE416和CWE415)中的所有释放后使用和双重释放错误,具有(或不具有)别名回收,并且没有误报,没有无限内存使用,无论是否重复使用。除了Juliet测试套件,DangZero还正确识别了400.perlbench测试工作集中包含的use-after-realloc bug(SPEC CPU 2006)[47]。此外,我们成功地证实了DangZero能够从CVE中检测出六种不同的释放后使用,以及PHP和Python等程序中报告的问题[1通过一个信号处理程序,我们验证了由use-after-frees触发的内存访问错误源于DangZero无效的页表条目最后,DangZero的代码库相对较小,只有3,100 KB,这表明所提出的设计可以用小型可信计算基础来实现。6.2性能基线在我们的实验中,我们使用未启用KML的虚拟化环境作为基准-有关虚拟化本身的开销(和加速机会),请参见下文。因此,所测量的每千次开销是运行KML的成本以及由覆盖分配器引起的减速。 尽管我们最初期望KML提供一致的加速(因为它消除了在系统调用接口处进行模式切换的需要),但在实践中,我们观察到了总体的边际影响。事实上,对于SPEC CPU 2006,我们观察到运行时的几何平均变化为0%,极端情况是一个二进制文件的加速率为8%,而另一个二进制文件的速度降低了4%。 我们观察到KML对其他基准测试的类似影响。此外,虽然我们确实使用了KML修补的glibc来执行直接调用而不是系统调用,但我们观察到这在实践中并没有提供加速 虽然我们确认glibc补丁确实减少了微基准测试中系统调用所需的CPU周期数,但在更复杂的工作负载下,这种加速会降低,与之前的工作中观察到的结果相匹配[29]。考虑到所有这些,我们相信与客户机内的无KML基线进行比较可以准确地表示我们系统的开销。 对于所有竞争系统,我们使用了带有默认系统分配器的裸金属基线(MineSweeper [ 19 ]除外,它使用了预期的jemalloc [ 21 ]基线),与它们的主要部署场景相匹配。6.3SPEC CPU2006我们在具有以下配置的机器上运行SPEC CPU 2006基准测试:Intel i7-6700(Skylake)CPU@3.40GHz,在使用QEMU/KVM的虚拟机内,其中VM接收24 GB的RAM,由hugepages支持,并 在 Linux v4.0-KML 内 核 上 运 行 Ubuntu 20.04 我 们 为QEMU/KVM提供了hugepage支持,以避免由于透明的hugepage而导致的高差异。我们还禁用了所有可选的CPU缓解措施以避免干扰。由于SPEC CPU2006只包含短期应用程序,因此从未达到别名回收程序的配置水印。6.3.1在头顶上。 每个SPEC CPU2006二进制文件的开销如图5所示。不包括别名回收,DangZero在SPEC CPU 2006上报告了14%的几何平均运行时开销。在每个程序结束时强制执行一个别名回收操作(标记和扫描)会使几何平均值为16%。对于寿命相对较短的SPEC应用程序,不使用别名回收器运行是可持续的。尽管如此,仅2个存储点的几何增长证实了别名回收管理是有效的。6.3.2部件堆积。接下来,我们通过分别测量DangZero的每个组件来查看开销的来源,如图5所示。 我们将设计分为五个核心要素:(1)使用内核模式Linux,(2)创建别名,(3)使用别名,(4)停用别名,以及(5)回收别名。启用内核模式Linux对二进制文件的性能有不同的影响虽然429.mcf的运行速度提高了8%,但458.sjeng的运行速度却降低了4%。但是,如前所述,总体上启用KML的几何平均值为0%。接下来,创建别名需要我们从内核请求页面,将它们插入别名地址空间,CCSFloris Gorter、Koen Koning、Herbert Bos和Cristiano Giuffrida1314400.perlbench401.bzip2403.gcc429.mcf433.milc444.namd445.gobalan447.dealII450.soplex453.povray456.hmmer458.sjeng启用KML创建别名使用别名禁用别名462.libquantum464.h264r
下载后可阅读完整内容,剩余1页未读,立即下载
cpongm
- 粉丝: 5
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 构建基于Django和Stripe的SaaS应用教程
- Symfony2框架打造的RESTful问答系统icare-server
- 蓝桥杯Python试题解析与答案题库
- Go语言实现NWA到WAV文件格式转换工具
- 基于Django的医患管理系统应用
- Jenkins工作流插件开发指南:支持Workflow Python模块
- Java红酒网站项目源码解析与系统开源介绍
- Underworld Exporter资产定义文件详解
- Java版Crash Bandicoot资源库:逆向工程与源码分享
- Spring Boot Starter 自动IP计数功能实现指南
- 我的世界牛顿物理学模组深入解析
- STM32单片机工程创建详解与模板应用
- GDG堪萨斯城代码实验室:离子与火力基地示例应用
- Android Capstone项目:实现Potlatch服务器与OAuth2.0认证
- Cbit类:简化计算封装与异步任务处理
- Java8兼容的FullContact API Java客户端库介绍
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功