Native Client: 用于便携式,不受信任的x86本机代码的沙箱(二)

Native Client: 用于便携式,不受信任的x86本机代码的沙箱(二)

Native Client: A Sandbox for Portable, Untrusted x86 Native Code
原文:https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/34913.pdf
注意!本文有删节,见谅!

书接上文 :Native Client: 用于便携式,不受信任的x86本机代码的沙箱(一)

3 NC实现

3.1 沙盒

在本节中,我们将解释NaCl如何实现软件故障隔离。设计仅限于显式控制流程,用机器代码中的调用和跳转表示。其他类型的控制流(例如异常)在NaCl服务运行时中管理,在不可信代码外部,如下面的NaCl运行时实现所述。

我们的内部沙箱使用一组可靠的拆卸规则,一个遵守这些规则的修改后的编译工具链,以及一个确认遵循规则的静态分析器。这种设计允许一个小的可信代码库(TCB)(PS:什么是TCB?Trusted computer system evaluation criteria),TCB外部的编译工具,以及一个小到足以允许彻底检查和测试的验证器。我们的验证器实现需要少于600个C语句(分号),包括x86解码器和cpuid解码。这编译成大约6000字节的可执行代码(Linux优化构建),其中大约900字节是cpuid实现,1700字节是解码器,3400字节是验证器逻辑。这个过程中验证器必须解决四个子问题:

  • 数据完整性:数据沙箱外无负载或存储
  • 可靠的拆卸
  • 没有不安全的指令
  • 控制流程完整性

为了解决这些问题,NaCl建立在先前关于CISC故障隔离的工作之上。我们的系统将80386分段存储器[14]与之前的CISC软件故障隔离技术相结合[40]。我们使用80386段来约束对虚拟32位地址空间的连续子范围的数据引用。这使我们能够有效地实现数据沙箱,而无需加载加载和存储指令的沙箱。 VX32 [20],[21]以类似的方式实现其数据沙箱。请注意,NaCl模块是32位x86可执行文件。不支持更新的64位可执行模型。

NaCl二进制执行文件的约束

C1 一旦加载到内存中,二进制文件就不可写,在执行期间由操作系统级保护机制强制执行。
C2 二进制文件在起始地址为零时静态链接,文本的第一个字节为64K。
C3 所有间接控制传输都使用nacljmp伪指令(在下面定义)。
C4 使用至少一个hlt指令(0xf4)将二进制文件填充到最近的页面。
C5 二进制不包含与32字节边界重叠的指令或伪指令。
C6 所有有效的指令地址都可以通过从加载(基址)地址开始的直通反汇编来到达。
C7 所有直接控制传输都针对有效指令。

上文列出了NC对不受信任的二进制文件的约束。约束C1和C6一起使拆卸可靠。通过可靠的拆卸作为工具,检测不安全的指令非常简单。 NC不允许的部分操作码包括:

  • syscallint。不受信任的代码无法直接调用操作系统。
  • 所有修改x86段状态的指令,包括lds,远程调用等。
  • ret。使用沙盒se-实现返回
    以间接跳跃结束的quence。

除了促进控制沙箱之外,如果在堆栈上检查了返回地址,则排除 ret 还可以防止由于竞争条件而导致的漏洞。类似的论点要求我们在间接的jmpcall指令中禁止内存寻址模式。 NC允许使用hlt指令。它永远不应该由正确的指令流执行,并且会导致模块立即终止。作为一个安全问题,我们不允许所有其他特权/ring-0指令,因为在正确的用户模式指令流中从不需要它们。我们还限制x86前缀使用仅允许已知的有用指令。根据经验,我们发现这消除了与CPU勘误相关的某些拒绝服务漏洞。
第四个问题是控制流完整性,确保程序文本中的所有控制传输都针对在反汇编期间识别的指令。对于每个直接分支,我们静态地计算目标并根据约束C6确认它是有效指令。我们的间接分支技术将80386分段存储器与简化的沙盒序列相结合。根据约束C2和C4,我们使用CS段将可执行文本约束到从零开始的地址范围,大小为4K字节的倍数。在文本范围受分段存储器约束的情况下,根据约束C3和C5,简单的常量掩码足以确保间接分支的目标与 mod 32 对齐:

and %eax, 0xffffffe0
jmp *%eax

我们将这个特殊的两个指令序列称为nacljmp。编码为三字节and以及两字节jmp,它与以前的CISC沙盒实现相比有利[40],[41],[56]。如果没有分段存储器或从零开始的文本,沙盒控制流通常需要两个六字节指令(一个and和一个or),总共十四个字节。

NaCl验证器的伪代码

// TextLimit = the upper text address limit
// Block(IP) = 32-byte block containing IP
// StartAddr = list of inst start addresses
// JumpTargets = set of valid jump targets
// Part 1: Build StartAddr and JumpTargets
IP = 0; icount = 0; JumpTargets = { }
while IP <= TextLimit:
  if inst_is_disallowed(IP):
    error "Disallowed instruction seen"
  StartAddr[icount++] = IP
  if inst_overlaps_block_size(IP):
    error "Block alignment failure"
  if inst_is_indirect_jump_or_call(IP):
    if !is_2_inst_nacl_jmp_idiom(IP) or
      icount < 2 or
      Block(StartAddr[icount-2]) != Block(IP):
      error "Bad indirect control transfer"
  else
    // Note that indirect jmps are inside
    // a pseudo-inst and bad jump targets
    JumpTargets = JumpTargets + { IP }
  // Proceed to the fall-through address
  IP += InstLength(IP)
// Part 2: Detect invalid direct transfers
for I = 0 to length(StartAddr)-1:
  IP = StartAddr[I]
  if inst_is_direct_jump_or_call(IP):
    T = direct_jump_target(IP)
    if not(T in [0:TextLimit))
       or not(T in JumpTargets):
      error "call/jmp to invalid address"

我们接下来断言然后证明我们的设计对于控制流完整性的正确性。假设有问题的文本没有错误验证,让S成为StartAddr列表中的指令集地址。

定理:S包含从S中具有地址的指令可以到达的所有地址。
证明:矛盾。假设在执行期间从S中具有地址的前驱指令A到达不在S中的地址IP。因为执行受到x86分段的约束,所以IP必须通常在[0:TextLimit中]。因此,IP只能通过三种方式之一达成。

情况1:通过从A落下来达到IP。这意味着IP是InstAddr(A)+ InstLength(A)。但是这个地址应该是在第1部分的S中。矛盾。

情况2:通过直接跳转或从S中的指令A调用来到达IP。然后IP必须在JumpTargets中,这是由构造的第2部分检查的条件。观察JumpTargets是S的子集,来自构造的第1部分。因此,IP必须在S.矛盾中。

情况3:通过从S中的A指令的间接转移到达IP。由于A处的指令是间接调用或跳转,所以A的执行总是紧跟在执行a和。在和计算出的地址对齐0 mod 32.因为没有指令可以跨越0 mod 32边界,所以[0,TextLimit]中的每个0 mod 32地址必须在S中。因此IP在S.矛盾中。

因此,从S中的指令到达的任何指令也在S中。

请注意,此分析仅涵盖显式的同步控制流程。第3.2节讨论了例外情况。
如果验证器过于缓慢,可能会阻止人们使用该系统。我们发现我们的验证器能够以大约30MB /秒的速度检查代码(在1.2秒内为35.7 MB,在带有MacOS 10.5的MacBook Pro,2.4GHz Core 2 Duo CPU,常温文件系统缓存上测量)。在此速度下,与下载时间相比,验证的计算时间通常非常小,因此不是性能问题。
我们相信这个内部沙箱需要非常强大。我们已经使用随机指令生成以及有效x86指令的详尽枚举来测试它以解码缺陷。我们还使用“模糊测试”来随机修改测试可执行文件。最初这些测试暴露了关键的实现缺陷,尽管测试仍在继续,但最近没有发现任何缺陷。我们还测试了各种x86微处理器实现,担心处理器勘误可能导致可利用的缺陷[31],[38]。我们确实发现CPU缺陷的证据导致系统“挂起”,需要电源循环来恢复机器。这发生在早期版本的验证器允许相对不受限制地使用x86前缀字节,并且由于将其限制为仅允许已知的有用前缀,我们无法再现这些问题。

3.2 异常处理

不允许出现硬件异常(segmentation faults, floating point exceptions)和外部中断,部分原因是Linux,MacOS和Windows中的异常和不兼容的异常模型。 Linux和Windows都通过%esp依赖x86堆栈来传递这些事件。遗憾的是,由于NaCl修改了%ss段寄存器,因此堆栈似乎对操作系统无效,因此它无法传递事件并且相应的进程立即终止。将x86分段用于数据沙箱有效地阻止了从这些类型的异常中恢复。因此,NaCl不可信模块将故障安全策略应用于异常。每个NaCl模块都在其自己的OS过程中运行,以实现异常隔离。 NaCl模块不能使用异常处理来从硬件异常中恢复,并且必须对于此类错误条件或突然终止的风险是正确的。在某种程度上,这很方便,因为在将这些事件安全地传递给不受信任的代码时存在非常具有挑战性的安全问题。
虽然我们目前无法支持硬件异常,但NC确实支持C++异常[57]。由于这些是同步的并且可以完全在用户级实现,因此没有实现问题。 Windows结构化异常处理[44]需要非便携式操作支持,因此不受支持。

服务运行时是由NPAPI插件调用的本机可执行文件,该插件还支持服务运行时和浏览器之间的交互。它支持Windows,MacOS和Linux上的各种Web浏览器。它实现了动态实施,维护内部沙箱的完整性,并提供资源抽象,以将NaCl应用程序与主机资源和操作系统接口隔离开来。它包含可信代码和数据,这些代码和数据在与包含的NaCl模块共享进程时,只能通过受控接口访问。服务运行时通过x86内存段和页面保护的组合来防止不受信任的代码进行不适当的内存访问。

加载NaCl模块时,将其置于服务运行时地址空间内的分段隔离256MB区域中。 NaCl模块的第一个64 KB的地址空间(NaCl“用户”地址空间)保留用于服务运行时的初始化。前4 KB是读写保护的,用于检测NULL指针。剩余的60 KB包含可信代码,用于实现我们的“蹦床”呼叫门和“跳板”返回门。在此64 KB区域之后立即加载不受信任的NaCl模块文本。 %cs段设置为约束从零基础到NaCl模块文本末尾的控制转移。其他段寄存器设置为限制对256 MB NaCl模块地址空间的数据访问。
因为它源自受信​​任的服务运行时并由受信任的服务运行时安装,所以允许trampoline和跳板代码包含在不受信任的可执行文本中禁止其他地方的指令。该代码在运行时作为NaCl模块加载过程的一部分进行修补,使用段寄存器操作指令和far call指令来启用不可信用户代码和可信服务运行时代码之间的控制传输。由于NaCl用户空间的前64 KB中的每个0 mod 32地址都是潜在的计算控制流目标,因此这些是我们的系统调用"蹦床"表的入口点。其中一个入口点被hlt指令阻塞,因此剩余空间可用于只能从服务运行时调用的代码。这为跳板返回门提供了空间。

调用trampoline将控制从不可信代码转移到可信代码。 trampoline序列重置%ds然后使用far call重置%cs段寄存器并将控制转移到可信服务处理程序,重新建立服务运行时代码所期望的传统平面寻址模型。一旦超出NaCl用户地址空间,它将重置其他段寄存器,如%fs%gs%ss,以重新建立本机代码线程环境,完全禁用此线程的内部沙箱,并加载堆栈寄存器%esp,包含可信堆栈的位置,供服务运行时使用。请注意,每线程可信堆栈位于不受信任的地址空间之外,以防止其受到不受信任的NaCl模块中其他线程的攻击。
就像"蹦床"允许从不信任代码到可信代码一样,"跳板"允许在另一个方向上交叉。"跳板"由可信运行时使用

  • 将控制权转移到任意不受信任的地址,
  • 启动一个新的POSIX风格的线程,和
  • 启动主线程。

对齐确保不能通过不受信任的代码直接调用跳板。跳转到任意不受信任的地址的能力用于从服务调用返回。从trampoline调用返回需要从堆栈顶部弹出未使用的trampoline返回地址,恢复段寄存器,最后对齐并跳转到NaCl模块中的返回地址。

在这里插入图片描述

上图显示了“null”系统调用的开销。 156ns的Linux开销略高于Linux 2.6 getpid系统调用时间,在相同的硬件上,为138 ns(通过vsyscall表并使用sysenter指令实现)。我们注意到用户/内核传输在x86架构的整个生命周期中不断发展。相比之下,NaCl蹦床使用的段寄存器操作和“远程调用”稍微不那么常见,并且可能对x86架构的历史记录的考虑较少。

3.4 通讯IMC

在这里插入图片描述

IMC是进出NaCl模块的通信基础。该实现围绕一个NaCl套接字构建,提供类似于Unix域套接字的双向,可靠,有序数据报服务[37]。不可信的NaCl模块在创建时接收其第一个NaCl插槽,可通过用于创建它的Document-Object Model对象从JavaScript访问。 JavaScript使用套接字将消息发送到NaCl模块,也可以与其他NaCl模块共享。 JavaScript还可以通过打开和共享NaCl套接字作为NaCl描述符来选择将模块连接到其可用的其他服务。 NaCl描述符也可用于创建共享内存段。

在这里插入图片描述

使用NaCl消息,NC的SRPC抽象完全在不受信任的代码中实现。 SRPC提供了一种方便的语法,用于声明JavaScript和NaCl模块之间或两个NaCl模块之间的过程接口,支持一些基本类型(int,float,char)以及除NaCl描述符之外的数组。不支持更复杂的类型和指针。诸如XDR [18]或协议缓冲器[26]之类的外部数据表示策略可以很容易地在NaCl消息或SRPC之上分层。
我们的NPAPI实现也在IMC之上分层,并支持公共NPAPI接口的子集。形成当前实现的特定要求是能够读取,修改和调用浏览器中脚本对象的属性和方法,支持简单的光栅图形,提供 createArray()方法以及打开和使用URL等功能文件描述符。选择当前实施的NPAPI子集主要是为了方便,但我们可能会进一步限制和扩展它,因为我们会提高对相关安全考虑因素和应用程序要求的理解。

3.5 开发者工具

3.5.1 建立NaCl模块

我们修改了标准GNU工具链,使用gcc编译器[22],[29]和binutils [2.1] 2.18版本的4.2.2版生成符合NaCl标准的二进制文件。我们使用生成的工具链从newlib2构建了一个引用二进制文件,重新托管使用NaCl蹦床来实现系统服务(例如,read()brk()gettimeofday()imc sendmsg())。 NC支持不安全的“调试”模式,该模式允许额外的文件系统交互,否则不允许安全代码。
我们通过将函数条目(-falign-functions)的对齐方式更改为32个字节并将目标分支(-falign-jumps)的对齐方式更改为32个字节来修改本机客户端的gcc。我们还改变了gcc以使用nacljmp进行间接控制传输,包括间接调用和所有返回。我们对汇编程序进行了更重要的更改,以实现NC的块对齐要求。为了实现返回,汇编程序确保调用指令始终出现在32字节块的最后字节中。我们还修改了汇编程序,通过将nacljmp伪指令扩展为正确对齐的连续字节块来实现间接控制传输序列。为了便于测试,我们增加了对使用更长的nacljmp序列的支持,对齐文本库,并使用和或使用重定位作为掩码。这允许通过在命令行上运行它们来测试应用程序,并且已经用于运行整个gcc C/C++ 测试套件。我们还更改了链接器以根据NaCl加载程序(今天为64K)的要求设置图像的基址。
除了直接使用之外,工具链还用于通过示例记录如何修改现有工具链以生成NaCl模块。这些更改是通过在gcc和binutils中修补不到1000行来实现的,这证明了将编译器移植到 NC 的简单性。

3.5.2 分析和调试

NC 的开源版本包括一个简单的分析框架,用于以最小的性能开销捕获完整的调用跟踪。这种支持基于gcc的-finstrument-functions代码生成选项与rdtsc时序指令相结合。此分析器是可移植的,完全以不受信任的代码实现。根据我们的经验,在此框架中分析的优化构建的性能介于-O0和-O2之间。可选地,应用程序员可以使用类似于printf的方法来注释探查器输出,其中输出出现在跟踪而不是stdout中。

NC 目前不支持NaCl二进制模块的交互式调试。通常我们通过使用标准工具和将所有接口导出到NaCl服务运行时的库来调试NaCl模块源代码,允许我们从相同的源构建调试和NaCl模块。随着时间的推移,我们希望改进对释放NaCl二进制文件的交互式调试的支持。

此处有删节

6.相关工作

安全执行第三方代码的技术通常分为三类:系统请求审核,故障隔离(包括虚拟化)和信任与身份验证。

6.1 系统请求审核

基于内核的机制,如基于用户ID的访问控制,systrace [50]和ptrace [60],是类Unix系统中常见的工具。许多以前的项目已探索使用这些机制来包含不受信任的代码[24],[33],[34],[36],[52],最近的Android [9],[27]来自Google和Xax [17]来自Microsoft调研。 Android使用沙箱运行第三方应用程序。每个Android应用程序作为不同的Linux用户运行,并且包含系统将系统调用活动划分为权限组,例如“网络通信”和“您的个人信息”。在安装第三方应用程序之前,需要用户确认所需的权限。用户分离固有地否认了潜在有用的相互通信。为了提供相互通信,Android在Binder进程间通信机制,Intent sytem和ContentProvider数据访问模型之上形成了一个权限模型。 [9]
Xax可能是目标方面与NC最相似的工作,尽管它们的实现方法完全不同,使用基于Linux上的ptrace和Windows上的内核设备驱动程序的系统调用拦截。我们在工作的早期就​​考虑过这种基于内核的方法,但由于担心可支持性而将其视为不切实际。特别要注意的是,Xax Windows实现需要一个内核模式设备驱动程序,必须针对每个支持的Windows版本进行更新,即使操作系统供应商自己实现,我们也会想到这个计划。在xtra没有解决的ptrace包含6中存在已知缺陷。虽然Xax的作者确实在他们的论文中认识到了这样一个问题,但是在Mitre的常见漏洞和暴露网站7中进行简单搜索可以记录41个与ptrace相关的不同问题。由于其纯粹的用户空间内部沙箱,NC不易受到这些困难的内核问题的影响。 Xax还容易受到基于x86勘误表的拒绝服务攻击,这种攻击可能导致计算机挂起或重启[31],[38]。因为NC检查每个指令并拒绝模块,并且发现它发现可疑的指令,所以它显着减少了无效指令的攻击面,并且还包括相关机制,以便在发现它们时防御新攻击。
由于Xax沙箱在进程边界处起作用,因此当操作系统非自愿地注入共享应用程序组件(如DLL)时,它无法隔离不受信任的代码,这是安全性和不可信代码的可移植性的问题。相反,NC内部沙箱在本机操作系统进程中创建安全子域。除了这些安全性差异之外,我们注意到Xax不支持线程,考虑到多核CPU的趋势,我们认为这是必不可少的。
Linux seccomp8工具还限制系统调用接口上的Linux进程,允许进程进入只允许exit()read()write()系统调用的模式。

6.2 故障隔离

NC应用了研究文献中广泛讨论的软件故障隔离和携带证明代码的概念。我们的数据完整性方案是英特尔80386 [14]中实现的分段存储器的简单应用。我们目前的控制流完整性技术建立在Wahbe,Lucco,Anderson和Graham [62]的开创性工作之上。与Wahbe等人一样,NC直接在本机机器指令中表达沙盒约束,而不是使用虚拟机或其他ISA便携式表示。 NC利用McCamant和Morrisett [40]首先描述的几种技术,利用特定机制扩展了之前的工作,以实现x86 [4],[14],[32] ring-3指令集架构(ISA)的安全性。NC使用静态验证器而不是可信编译器,类似于为其他系统描述的验证器[19],[40],[41],[49],应用了携带证明代码的概念[46]。
在Wahbe等人推广软件故障隔离概念之后,研究人员描述了互补和替代系统。一些[1],[19],[40],[41],

[49],[56]直接使用x86机器代码。其他基于中间程序表示,如类型安全语言[28],[45],[47],[59],抽象虚拟机[3],[20],[21],[39],或编译器中间表示[53]。它们使用便携式表示,允许ISA可移植性,但通过直接使用机器代码来创建我们避免的性能障碍。在机器代码中直接表示沙盒的另一个优点是它不需要可信赖的编译器。这大大减小了可信计算库的大小[61],并且不需要来自编译器的加密签名。除了简化安全实现之外,NC还可以将系统打开到第三方工具链。
与NC相比,CFI [1]提供了更细粒度的控制流完整性。虽然我们的系统仅保证间接控制流将针对文本段中的对齐地址,但CFI可以将特定控制转移限制为相当任意的已知目标子集。虽然这种更精确的控制在某些情况下可能是有用的,例如确保从高级语言翻译的完整性,但它对NC没有用,因为我们打算允许相当任意的控制流,甚至是手工编码的汇编程序,如执行仍然在已知文本中并且目标是对齐的。与此同时,CFI开销平均高出三倍(在SPEC2000上为15%对比5%),这并不奇怪,因为它的仪器序列比NC的长度要长得多,无论是在尺寸还是指令数量方面。 XFI [19]将数据沙箱添加到CFI控制流检查中,并增加了额外的开销。相比之下,NC可以从x86段免费获取数据完整性。
最近的其他系统已经探索了通过测量信任来实现安全副作用的机制。 NaCl资源描述符类似于EROS等系统中的能力[55]。奇点渠道[30]起着类似的作用。 DTrace [11],Systemtap [49]和XFI [19]都有相关的机制。
许多项目已经探索过隔离不受信任的内核扩展。 SPIN和VINO采用不同的方法来实现安全性。 SPIN选择了一种类型安全的语言Modula-3 [47]和一个可信赖的编译器工具链来实现扩展。与NC和Wahbe等人的原创作品一样,VINO使用基于机器指令沙箱的软件故障隔离。与NC一样,VINO使用修改后的编译工具链将沙盒指令添加到x86机器代码中,使用C ++实现扩展。与NC不同,VINO没有二进制验证器,依赖于可信赖的编译器。我们注意到VINO的验证器比NC更难,因为它的验证器必须强制执行数据引用完整性,在具有80386段的NC中实现。
Nooks系统[58]通过使用称为Nooks Isolation Manager(NIM)的透明OS层将可信内核代码与不可信设备驱动程序模块隔离,从而增强了操作系统内核的可靠性。与NC一样,NIM使用内存保护来隔离不受信任的模块。由于NIM在内核中运行,因此x86段不可用。 NIM使用每个扩展模块的专用页表。要更改保护域,NIM会更新x86页表基址,该操作具有刷新x86转换后备缓冲区(TLB)的副作用。通过这种方式,NIM使用页表提示了NC使用的段保护的替代方法。虽然对这两种方法的性能分析可能会暴露出有趣的差异,但这种比较在x86上没有实际意义,因为一种机制只能在内核中使用,而另一种机制只能在内核之外使用。 Nooks和NC之间的一个重要区别是Nooks的设计只是为了防止意外错误,而不是滥用。相比之下,NC必须能够抵制未经尝试的故意滥用,强制要求我们的机制进行可靠的x86反汇编和控制流完整性。这些机制在Nooks中没有模拟。
有许多基于虚拟机架构的环境提供安全执行和一些本机性能[3],[6],[7],[20],[28],[39],[53],[ 63]。虽然我们认识到这些系统提供了出色的故障隔离功能,但我们在NC中对虚拟化进行了深思熟虑的选择,因为它通常与我们的操作系统中立性,浏览器中立性和最高本机性能目标不一致或无关。
最近,内核扩展已用于操作系统监视。 DTrace [11]将一个VM解释器整合到Solaris内核中以便安全执行,并提供了一组内核检测点和输出设施,类似于NC的安全副作用。 Systemtap [49]提供与DTrace类似的功能,但使用x86本机代码进行扩展而不是VM中的解释语言。

6.3 信任身份验证

也许在Web内容中使用本机代码的最流行的例子是Microsoft的ActiveX [15]。 ActiveX控件依赖于信任模型来提供安全性,控件使用Microsoft专有的Authenticode系统进行加密签名[43],并且只有在用户表明他们信任发布者时才允许运行。通常利用这种对做出谨慎信任决策的用户的依赖。 ActiveX不能保证可信控制是安全的,即使控件本身不是恶意的,控制中的缺陷也可以被利用,通常允许执行任意代码。为了缓解这个问题,微软维护了一个被认为不安全的黑名单[42]。相比之下,NC旨在防止此类攻击,即使对于有缺陷的NaCl模块也是如此。

7 结论

本文介绍了NC,这是一个将不受信任的x86本机代码合并到Web浏览器中运行的应用程序的系统。除了创建防止不良副作用的屏障外,NaCl模块还可跨操作系统和Web浏览器移植,并支持面向性能的功能,如线程和矢量化指令。我们相信NaCl内沙箱非常坚固;无论我们提供额外的冗余机制来提供纵深防御。
根据我们的经验,我们发现将现有的 Linux/gcc 代码移植到NC非常简单,并且沙箱的性能损失很小,特别是在系统设计的计算限制方案中。
通过在这里描述NC并将其作为开源提供,我们希望鼓励社区审查和贡献。我们相信这些反馈以及我们的持续努力将使我们能够创建一个比以前的原生代码网络技术实现更高安全性的系统。

此处有删节

玩~

猜你喜欢

转载自blog.csdn.net/yeshennet/article/details/83792533