Automated System Call Filtering for Commodity Software 翻译

文章目录

  • 记录
  • 翻译
    • 摘要
    • 1 介绍
    • 2 背景和威胁模型
    • 3 设计与实施
      • 3.1 系统调用集提取
        • 3.1.1 分析范围
        • 3.1.2 函数调用图构造
        • 3.1.3 系统调用集构建
      • 3.2 系统调用集执行
      • 3.3 原型实现
    • 4 评估
    • 5 大规模系统调用分析
    • 6 相关工作
    • 7 总结

记录

涉及到的点: ELF结构,反汇编,系统调用图的生成,如何限制系统调用API的范围。

系统调用图咋生成


翻译

sysfilter: Automated System Call Filtering for Commodity Software

sysfilter:商品软件自动的系统调用筛选

?? 原文地址

摘要

现代操作系统为应用程序提供了丰富的服务集,这些服务主要可以通过系统调用API访问,以支持现代软件不断增长的功能。 但是,尽管事实是应用程序需要访问系统调用API的一部分(才能正常运行),但是OS内核允许完全不受限制地使用整个系统调用集。 这不仅违反了最小特权原则,而且使攻击者在掌握了易受攻击的应用程序的控制权之后可以利用额外的OS服务,或者通过利用压力较小的内核接口中的漏洞来进一步提升特权。

为了解决这个问题,我们提出了sysfilter:一个基于二进制分析的框架,该框架通过针对系统调用API实施最低特权原则,自动(1)限制攻击者可以(滥用)使用的OS服务,以及(2) 通过限制用户级进程可用的系统调用集来减少内核的攻击面。 我们为x86-64 Linux实现sysfilter,并提出了一组程序分析,用于以静态,可扩展,精确和完整(安全的过度近似)方式构造系统调用集。 此外,我们使用411个二进制文件(真实的C / C ++应用程序)和≈38.5K测试来确认其功能,从而根据正确性评估原型。 此外,我们评估了执行机制的影响,显示了最小或可忽略的运行时间减慢。

最后,我们对≈30K C/C ++应用程序的系统调用配置文件进行了大规模研究(来自Debian sid),得出了可以证明我们的设计合理的见解,并可以为将来的(基于系统调用的)管制机制提供帮助。

1 介绍

软件的复杂性和规模不断增长。/bin/true是通常在shell脚本中用作辅助的“小命令”,它最初是在Unix发行版的第七版(Bell Labs)中引入的,由零行代码(LOC)组成; 到2012年,在Ubuntu中,true已成长为2.3 KLOC [28]。 同样,bash二进制文件已从11.3 KB(Unix V5,1974)变为2.1 MB(Ubuntu,2014)[28]

不断添加到现代应用程序中的附加功能流(即特征蠕变)不仅在安全性和保护方面产生了可怕的影响[1,71],而且还需要丰富的OS服务集:应用程序需要与OS进行交互内核,并且主要是通过系统调用(syscall)API [52]来执行的,以便执行有用的任务,例如获取或释放内存,生成和终止其他进程和执行线程,与计算机上的其他程序进行通信。 相同或远程主机,与文件系统进行交互,并执行I / O和过程自省。

指示性地,在撰写本文时,Linux内核(v5.5)在x86-64中提供了对347个系统调用的支持。 但是,并非每个应用程序都需要访问完整的系统调用集。 例如,Debian“ sid”(开发版本)[86]中所有(C / C ++)应用程序的≈45%/ 65%不使用x86-64 Linux中的execve / listen。 换句话说,这些应用程序中大约有一半不需要(也不应该被允许)调用其他程序或接受网络连接。 las,操作系统内核为完整的系统调用集提供了完整且不受限制的访问权限。 这不仅违反了最低特权原则[76],而且还使攻击者能够:(a)抓住对易受攻击的应用程序的控制权后,再使用其他OS服务[69],以及(b)通过利用漏洞进一步提升其特权。 在未使用或压力较小的OS内核接口中[33-35、43、65、66]。

为了减轻上述(a)和(b)的影响,我们提出了sysfilter:一个框架,通过针对syscall API实施最低特权原则,来(自动)限制攻击者可以(ab)使用的OS服务[69] ],并通过限制用户级进程可用的系统调用集来减少OS内核的攻击面[43]。 sysfilter由两部分组成:系统调用集提取和系统调用集实施。 前者以二进制形式接收目标应用程序作为输入,自动解决对动态共享库的依赖关系,构造该程序的函数调用图(FCG)的安全(但紧密的)过度逼近,并在FCG顶部执行一组程序分析 ,以便提取开发人员预期的系统调用集。

后者强制执行提取的系统调用集,从而有效地对输入二进制文件进行沙箱处理。 我们在Egalito框架[95]之上的x86-64 Linux中实现了sysfilter,而我们的程序分析是通过Egalito中间表示形式的“通过”精心设计的,具有可扩展性,精确性和完整性。sysfilter可以在不到200s的时间内提取Debian sid中约90%的所有C / C ++应用程序的开发人员期望的syscalls集的紧密近似值(或不到30s即可提取约50%的这些应用程序的§5) )。 此外,sysfilter不需要源代码(即,它在剥离的二进制文件上运行,使用现代工具链进行编译[26,67]),并且可以对包含用不同语言(例如C,C ++)编写的组件或由以下组件编写的程序进行沙箱处理: 不同的框架(GCC,LLVM)。 重要的是,sysfilter不依赖于(任何形式的)动态测试,因为这种方法的结果通常都是不完善和不完整的[62]

此外,我们从三个维度评估sysfilter:(1)正确性,(2)性能开销和(3)有效性。 就(1)而言,我们使用了来自各种软件包/项目的411个二进制文件,包括GNU Coreutils(100,672),SPEC CINT2006(12,12),SQLite(7,31190),Redis(6,81)。 ,Vim(3、255),Nginx(1、356),GNU M4(1、236),GNU Wget(1、130)。 MariaDB(156,2059)和FFmpeg(124,3756)提取并执行其相应的系统调用集; 一旦进行沙箱测试,我们便用≈38.5K测试对它们进行了压力测试。在所有情况下,sysfilter都设法提取了各个syscall集的完整且紧密的过度逼近,这表明我们的原型可以成功处理复杂的实际软件。 (括号中的数字A; B分别表示已分析/强制执行的二进制文件的数量以及用于对其进行压力测试的测试的数量。)

关于(2),我们使用了SPEC CINT2006,Nginx和Redis,即总共19个程序二进制文件。 在所有情况下,由于系统调用筛选,沙盒版本的运行时速度减慢最少,或者可以忽略不计。 我们探索了许多不同的设置和配置,包括解释与对比。JIT编译的过滤器,以及使用线性搜索(在相应的syscall集中)实现沙箱的过滤器代码。利用基于跳过列表的方法的过滤器代码。 最后,关于(3),我们通过查询Debian sid中所有C / C ++应用程序的百分比(总计约3万个二进制文件)可以在硬化后利用23个Linux内核漏洞,来研究sysfilter如何减少操作系统的攻击面 与sysfilter。 尽管sysfilter不能防御控制流或数据流劫持[87],但我们的结果表明,它可以通过最低特权执行和(OS)攻击面减少来减轻攻击。

我们通过对≈30KC / C ++应用程序的系统调用集(Debian sid)进行大规模研究来结束我们的工作,报告有关系统调用集大小(即,每个二进制文件的系统调用数),最常用和最不常用的见解。 syscall,syscall站点分发(库与主二进制文件)等。分析的结果不仅可以指导我们的设计,还可以帮助将来的syscall管制机制。

2 背景和威胁模型

对抗能力在这项工作中,我们考虑用内存不安全的语言(例如C / C ++和汇编语言(ASM))编写的用户态应用程序。 攻击者可以在应用程序的主要二进制文件中或在后者正在使用的各种库中触发漏洞,从而导致内存损坏[87]。 请注意,我们不会将自己局限于特定类型的漏洞(例如,基于堆栈或堆的内存错误,或更笼统地说,是空间或时间内存安全错误)[59,60]或利用技术(例如,代码注入, 代码重用)[13、78、79、87、97]。

更具体地说,攻击者可以:(a)触发目标应用程序中与内存安全相关的漏洞,如果需要,可以多次触发,并构造和利用漏洞利用原语,例如任意内存写入[16]和读取[81]; (b)使用或组合这些原语来篡改关键数据(例如,函数和vtable指针,返回地址),以劫持目标应用程序的控制流,并通过代码注入的方式实现任意代码执行[83] [97]或代码重用[10、13、24、29、32、78、79]。 在对抗能力方面,我们的威胁模型与C / C ++ / ASM开发中的最新技术水平相当[41,87]。 最后,我们假设目标应用程序由良性代码组成:即它们不包含恶意组件。

强化假设这项工作的主要重点是用C,C ++或ASM(或其任意组合)编写的现代x86-64 Linux应用程序,并且通过位置链无关的[64]方式(默认情况下)通过工具链进行编译 混合代码和数据[3,4],例如GCC和LLVM.1除上述内容外,我们还假设在构成目标应用程序的ELF [12]文件中存在堆栈退卷信息(.eh_frame部分)

在第3节中,我们详细说明了这两个要求的原因-即位置无关代码(PIC)和.eh_frame部分。 但是,请注意,(a)在现代Linux发行版中默认启用PIC [14,95],而(b).eh_frame节在现代GCC和LLVM编译的代码[3,95]中存在。 (a)的主要原因是完整的ASLR(地址空间布局随机化):在位置相关的可执行文件中,ASLR将仅随机化进程堆栈以及基于mmap和brk的堆[7]。 此外,由于存在PC相对数据传输指令(%rip-relative mov)和额外的通用寄存器(x86中为16 vs. 8),x86-64中的PIC产生的性能开销可忽略不计。 就(b)而言,C ++代码要求对堆栈展开信息进行异常处理[49],而GCC和LLVM都发出.eh_frame节,甚至对于C代码也支持与C ++的互操作性[95]和某些特定功能 libc(C库)实现—例如,glibc(GNU C库)中的回溯。

最后,我们假设一个Linux内核支持seccomp-BPF(带有过滤器的安全计算)[36]。 (所有版本≥v3.5或更高版本均在x86-64中提供对seccomp-BPF的支持。)其他所有标准的userland强化功能(例如NX,ASLR,堆栈破坏保护)均与sysfilter正交; 我们提出的方案既不需要也不排除任何此类功能。 对于较不广泛的缓解措施也是如此,例如CFI [9,96],CPI [40,53],代码随机化/多样化[38、41、94]以及针对纯数据攻击的防护[68]。

3 设计与实施

sysfilter方法旨在通过限制对syscall API的访问来减轻应用程序损害的影响[52]。 这种方法的好处是双重的:(1)限制了利用后的功能[69],(2)通过利用未使用的或压力较小的内核接口中的漏洞,防止了受到入侵的应用程序进一步提升特权[33– 35、43、65、66]。

(1)背后的主要思想是应用程序需要与内核进行交互(并且它们主要是通过syscall API进行交互)才能执行有用的任务。 指示性地,在撰写本文时,Linux内核(v5.5)在x86-64中提供了对347个系统调用的支持。 (该数字不包括在64位内核或执行x32 ABI的64位进程上执行32位x86应用程序所需的syscalls。)但是,尽管事实是应用程序只需要访问以下内容即可: 要使上述API的一部分正常运行(例如,非联网应用程序不需要访问与套接字相关的syscall),则OS内核将提供对整个syscall集合的完全且不受限制的访问。

这种方法违反了最小特权原则[76],使攻击者在掌握了易受攻击的应用程序的控制权之后便可以利用其他OS服务。 通过限制对某些syscall的访问,sysfilter可以自然地限制攻击者可以(滥用)的OS服务,并针对syscall API实施最低特权原则:即,允许程序仅使用开发人员期望的syscall。

就(2)而言,多项研究反复表明,利用内核(甚至更低级别,更高特权[19,99])代码中的漏洞是特权提升攻击的重要组成部分[33– 35、43、65、66]。 为此,sysfilter通过限制可用于用户层进程的syscall集来减少OS内核的攻击面,从而有效地提供了深度防御。

概述sysfilter由两部分组成(请参见图1):(1)syscall集提取组件; (2)系统调用集执行组件。 前者以二进制形式(ELF文件)接收目标应用程序作为输入,自动将所有依赖项解析为动态共享库(.so ELF对象),并在范围内的所有对象之间构造程序FCG的安全过度近似。 最后,它在FCG顶部执行一组程序分析,以使过逼近尽可能严格,并构造有问题的syscall集。 请注意,上述任务是静态执行的,并且提取工具返回的syscall集已完成:即,在任何给定的输入下,由相应进程执行的syscall一定存在于syscall集中-这包括源自于 二进制文件本身,libc或任何其他动态加载的共享库。 后一部分将强制执行提取的系统调用集,从而有效地对输入二进制文件进行沙箱处理。 具体来说,给定一组系统调用号,强制执行工具会将其转换为与seccomp-BPF [36]一起使用的BPF程序[54]。

3.1 系统调用集提取

3.1.1 分析范围

sysfilter的syscall-set提取组件的输入是(x86-64)ELF文件,该文件与应用程序的主二进制文件相对应(请参见图1A)。 sysfilter需要PIC作为输入,这是现代Linux发行版中的默认设置[14,95]。 sysfilter验证主二进制文件确实是PIC之后,将其添加到分析范围中,然后继续解决与动态共享库有关的依赖关系。 首先检查PT_INTERP标头,该标头通常包含相应的动态链接器/加载器的路径(例如,/lib64/ld-linux-x86-64.so),然后为DT_NEEDED条目迭代.dynamic ELF节,即可完成此操作。 对应于所需共享库的名称。 这些库中的每一个都被添加到分析范围,并且它们的.dynamic节也被递归扫描,以恢复其他(库)依赖项。 解决所有显式动态库依赖关系并将相关的ELF文件添加到分析范围后,该过程将停止。

除上述内容外,还可以向sysfilter提供一组隐式动态共享对象依赖项作为输入:即,需要添加到分析范围的其他.so ELF文件的列表,无论它们是否存在 在任何已加载对象的.dynamic部分中(请参见图1B)。 为了支持对与共享库具有运行时相关性的二进制文件(例如,通过dlopen)或使用LD_PRELOAD进行分析,此功能非常重要。

3.1.2 函数调用图构造

将每个ELF对象添加到分析范围后,sysfilter继续构建整个程序的功能调用图(FCG)。 FCG包含在相应过程的任何可能输入下可到达的部分代码(功能)。 请注意,对于分析范围中每个包含的.so ELF对象,都不会使用其所有代码:例如,与libc,libpthread,libdl等链接的应用程序不会充分利用后者。 通常,仅使用库功能的一部分[1,71]。

精确反汇编要完全,精确地反汇编任意二进制程序是一项无法确定的任务[91]。 该问题源于两个主要原因:(a)无法果断地区分代码与数据[91]; (b)无法精确识别功能边界[5,6]。 幸运的是,像GCC和LLVM这样的现代工具链(1)不会混合代码和数据[3,4],并且(2)将堆栈展开信息嵌入到(x86-64)C / C ++二进制文件[95]。
sysfilter利用(1)和(2)来从分析范围内的所有ELF文件中精确地分解可执行代码,而不需要符号或调试信息(如果有此类信息,则sysfilter将使用它,但是我们的技术是 为剥离的二进制文件而设计。)

更具体地说,对于分析范围内的每个.so对象,sysfilter使用堆栈展开信息(.eh_frame部分)来获取可执行部分(例如.text,.plt)中所有函数的确切边界。 此外,要特别注意正确识别crtstuff.c(libgcc)的功能,这些功能已编译到.init和.fini节以及crtbegin.o节中。 有了关于函数边界的精确信息,并严格区分代码和数据,sysfilter在与已识别函数相对应的所有代码区域中执行线性扫描,以分解其可执行代码。 由于数据被视为代码或功能边界检测不正确,因此最终的反汇编不包含任何无效指令,也不会由于未识别的代码而错过任何指令-最终的反汇编是完整,准确和准确的。

直接调用图基于上一步中获得的精确反汇编,sysfilter继续构建输入程序的FCG。 首先,它将直接调用图(DCG)放在一起:即FCG中与直接调用的函数/代码相对应的部分。 这是通过以下方式实现的:首先将主要二进制文件的入口添加到DCG中,然后将所有地址存储在后续(ELF)节中的函数:.preinit_array,.init_array和.fini_array; .init和.fini中的代码/功能也已添加到DCG。 随后,对分析范围中的每个其他.so ELF对象重复相同的过程。
在此步骤结束时,将一组初始函数添加到DCG,这些初始函数对应于由动态链接器/加载器(ld.so)在相应过程的初始化/完成期间执行的代码的入口点。 。 还可以提供一组隐式函数依赖项作为输入(请参见图1B)。 同样,这是必需的,以帮助分析对某些功能具有运行时依赖性的二进制文件(例如,通过dlsym)或使用LD_PRELOAD。

接下来,线性扫描DCG中每个此类功能的代码,以识别针对各个ELF对象中其他功能的直接调用指令。 跨函数边界的分支指令(如(无)条件的jmp)也要考虑在内,因为它们通常用于实现尾部调用消除[84]。 每个已标识的目标功能(被调用方)也都添加到DCG中,并且重复该过程,直到无法添加其他功能为止。通过检查过程链接表(PLT)的交叉共享库调用,可以通过检查范围中的ELF文件的.dynsym和.dynstr以及“模拟” ld.so的绑定(符号解析)规则来进行处理。 2(通过PLT直接进行cross.so对象调用被视为直接进行intra.so内部函数调用。)

上面的最终结果是构成FCG的一部分,该部分包含作用域中ELF对象的入口点和初始化/完成功能(加上隐式添加的功能,如果提供的话),随后是每个 从它们可以直接访问的其他功能(即,通过遵循直接调用/ jmp指令的目标并解析PLT条目可以访问)。

地址获取的呼叫图前述过程未考虑间接呼叫/jmp指令所针对的功能。 这样的指令具有一个(通用)寄存器或存储位置的操作数,该寄存器存储目标地址(即被调用者的地址),并且通常用于解引用函数指针(C / C ++)和实现动态调度( C ++)[77]。 静态地解决间接调用/jmp指令的目标地址是一个难题[72],主要是由于指向分析的不精确性[44]。 (请注意,使用动态测试来解析目标地址甚至更成问题,因为这种方法的结果通常缺乏可靠性[62]。)从DCG开始,sysfilter会通过构造(我们称为)FCG来过分逼近FCG。 地址调用图(ACG)。 构建ACG的过程是完整的:即,它绝不排除程序可以执行的功能(在任何可能的输入下)

构建ACG的第一步是识别所有采用地址的函数:即,其地址出现在右值表达式,函数自变量,结构/联合初始化器和C ++对象初始化器中的函数,或与虚拟方法相对应的函数( C ++)。 所有地址获取(AT)函数的集合是范围内每个间接调用站点的可能目标的超集。 这是因为间接调用/跳转指令将操作数(通用)寄存器或内存位置作为操作数,它们只能保存绝对地址。 因此,为了使函数最终通过间接调用/ jmp指令被调用,首先要“获取”其地址,然后将其加载到相应的操作数中(无论是寄存器还是存储器位置)。

sysfilter利用分析范围中的每个ELF对象都被编译为PIC的事实,以便识别所有AT功能。 更具体地说,如果启用了PIC,则对应于绝对功能地址的代码或数据ELF区域中的位置必须始终具有随附的重定位条目(reloc)。 sysfilter首先确定范围内ELF对象中的所有重定位部分(即SHT_REL或SHT_RELA类型的部分)。 接下来,它处理所有重定位,搜索重定位的计算涉及一个函数的起始地址的情况(回想一下,在DCG的构建过程中,我们已经确定了范围内每个函数的边界)。 每个这样的函数(其起始地址用于重定位计算中)实际上都是一个AT函数。 相同的函数可以在不同的位置多次获取其地址(例如,函数参数,函数主体中的右值表达式或作为全局struct / union / C ++对象初始化程序的一部分)。 应用于特殊部分(例如.plt,.dynamic)的重定位将被忽略,因为它们仅与动态绑定有关。

配备了所有AT功能的集合后,sysfilter会使用与构造DCG相同的方法,从(每个)功能中计算可达功能。 ACG有效地包含发现的AT功能作为“入口点”,其次是可直接从其访问的所有其他功能。 DCG和ACG中组合的功能集是程序FCG中功能集的超集:即V [FCG]?(V [DCG] [V [ACG])。

真空调用图尽管DCG [ACG是FCG的一个安全的过度逼近,但它并不严格,因为考虑的调用图中包含的每个AT函数都可能(潜在地)通过引入范围来以相当大的方式“污染”它 本身可以达到的其他功能。 为了使过度逼近尽可能严格,sysfilter使用一种软件去膨胀技术来修剪ACG [1,71]。 特别是,我们首先观察到,每次获取函数的地址时,都会创建一个代码指针。 通过考虑创建此类代码指针的位置(ELF部分),sysfilter进一步分离了在代码(例如.text)和数据(例如。(ro)data)区域中找到的代码。 对于前者,它会迭代被视为无法访问的每个功能,并检查AT功能的地址是否仅在(严格地)不属于调用图的功能内使用。 如果此条件为真,则会从ACG中删除相应的AT功能,这可能会导致其他删除操作(例如,从已删除的AT功能可直接访问的所有内容); sysfilter反复执行上述操作,直到无法修剪其他功能为止。

对于后一种情况,sysfilter不能使用相同的方法来修剪AT函数,因为生成的代码指针可以成为封装数据结构的一部分,如果不访问符号(或调试)信息,就无法跟踪其用法。 但是,如果确实有这样的信息(请注意,现代工具链(GCC,LLVM)默认情况下在结果的ELF对象(.symtab节)中包含符号,而流行的Linux发行版为其打包的二进制文件提供了符号),sysfilter可以(更积极地 )如下消除数据部分中的AT功能。 首先,它利用符号信息来标识全局数据对象(即OBJECT / GLOBAL类型的符号)的界限([OBJ_BEGIN-OBJ_END])。 接下来,它检查是否存在以下重定位:(a)对应于AT功能; (b)落在任何全局对象的范围内。 这种方法的最终结果是识别出静态初始化的代码指针数组或包含代码指针的数据结构。 最后,sysfilter会迭代已分类为不可访问的每个函数,并检查是否仅在此类函数中使用了OBJ_BEGIN。 同样,如果此条件为真,则将与从OBJ_BEGIN开始的对象相对应的AT函数标记为不可访问,并反复执行清除过程,直到没有其他功能可以分类为不可访问为止。 我们将修剪后的ACG与DCG结合起来称为真空调用图(VCG)。 具体来说,VCG = DCG [ACG0,其中ACG0表示使用上面概述的方法修剪的ACG(请参见图1C)。 同样,VCG是真实FCG的一个完整的,严格的过度逼近:即sysfilter仅排除了程序永远无法执行的功能(在任何可能的输入下); 更正式地讲:V [FCG]?V [VCG]?(V [DCG] [V [ACG])。

图2展示了一个类似C的程序,我们将以它为例来演示VCG的构造。 sysfilter最初将包括main(ln。19)和f9(ln。5)。 DCG还将包括上述初始集合中的所有直接可达功能:f1(可从main,ln。22到达)和f10(可从f9,ln。22到达)。 因此,V [DCG] = fmain; f1; f9; f10g。 接下来,sysfilter将继续构建ACG,该ACG最初将包括所有地址获取功能:f3(ln。14),f4(ln。13),f6和f7(ln。17)。 ACG还将包括AT函数集中的所有直接可达函数:f5(从f4,ln。10可达)和f8(从f7,ln。7可达)。 因此,V [ACG] = ff3; f4; f5; f6; f7; f8g。

然后,sysfilter将继续修剪ACG,如下所示。 首先,它将删除f4,因为它的地址仅在功能f2(第13章)中获取,该地址无法访问。 这也将导致删除f5,因为它只能从f4直接到达(第10章)。 如果剥离了相应的ELF对象,则修剪过程将在此时终止,从而产生以下函数集:V [ACG0] = ff3; f6; f7; f8g。 如果提供了符号(或调试)信息,则sysfilter可以通过确定范围中的任何函数未引用fp_arr来执行更严格的修剪。 因此,还可以删除AT功能f6和f7,以及仅可从f7直接访问的f8(第7条)。 上面的最终结果是以下函数集:V [ACG00] = ff3g。

总结起来,没有符号信息,V [VCG] = V [DCG] [V [ACG0] = fmain; f1; f3; f6; f7; f8; f9; f10g,而有符号(或调试信息)可用,V [ VCG] = V [DCG] [V [ACG00] = fmain; f1; f3; f9; f10g。有兴趣的读者可以参考附录(A),以获取有关sysfilter如何处理GNU IFUNC和NSS符号,重叠代码以及手写汇编的更多信息。

3.1.3 系统调用集构建

x86-64 ABI指示使用syscall指令[30]来执行系统调用。3此外,在调用syscall期间,系统调用号位于寄存器%rax中。 借助程序的VCG,sysfilter可以如下构造有问题的系统调用集。

首先,它通过在每个函数f 2 V [VCG]中执行线性扫描以查明syscall实例,从而识别出所有包含syscall指令的功能。 一旦建立了所有可到达的syscall指令集,sysfilter就会继续执行简单的值跟踪分析,以解析每个syscall站点上%rax的确切值。 该过程依赖于使用使用定义(UD)链的标准实时变量分析[2,§9.2.5]。 具体而言,sysfilter认为syscall指令“使用”%rax,并利用UD链接查找“定义”它的所有指令。 在大多数情况下,%rax是通过常量加载指令(例如mov $ 0x3,%eax)定义的,并且通过收集此类指令并提取相应的常量值,sysfilter可以组装系统调用集。 如果%rax是通过涉及内存操作数的指令定义的,则sysfilter中止(或发出警告,如果相应地调用),因为结果系统调用集可能不完整[72]。 syscall-set提取组件的输出是JSON格式的系统调用号的集合(请参见图1D)。

我们选择以过程内方式应用上述分析,因为我们的结果表明该策略在实践中效果很好(请参阅第5节); 系统调用调用是特定于体系结构的,并且通常使用以下模式(在x86-64中)通过libc处理:’mov $ SYS_NR,%eax; syscall”,其中?$ SYS_NR = {$ 0x0,$ 0x1,…}。 一个例外是syscall()函数[48]的处理,该函数通过接收相应的系统调用号作为参数来间接执行系统调用。 如果syscall()不是VCG中的地址,则sysfilter首先识别直接调用syscall()的可访问函数,然后对寄存器%rdi(第一个参数,系统调用号)执行过程内值跟踪。 如果syscall()的地址在可访问的VCG中,则sysfilter中止(或发出警告,如果进行了相应的调用),因为生成的系统调用集可能还是不完整

3.2 系统调用集执行

sysfilter的syscall-set强制执行组件的输入是允许的系统调用集,以及与应用程序主二进制文件相对应的ELF文件(请参见图1E)。 配备了开发人员预期的系统调用集,sysfilter使用seccomp-BPF [36]在运行时强制实施。 后者接收通过prctl或seccomp传递的BPF“程序” [54]作为输入,内核在每次系统调用时都会调用它。 注意,BPF程序是由内核对BPF字节码的解释器以内核模式执行的[54],同时还支持即时(JIT)编译为本机代码[11]。 另外,Linux内核还支持两种不同的BPF变体:(a)经典(cBPF)和(b)扩展(eBPF)[46]; seccomp-BPF仅使用cBPF

seccomp-BPF程序(过滤器)的输入是一个固定大小的结构(即seccomp_data;请参见附录B中的图8),由内核传递,其中包含系统调用上下文的快照:即syscall号( field nr),体系结构(field arch)以及指令指针和syscall参数的值。 sysfilter根据nr的值执行过滤,如下所示:if(nr 2 f0; 1; ::: g)然后允许else DENY,其中f0; 1; ::: g是允许的系统调用号的集合。 给定这样一个集合,sysfilter会编译一个cBPF过滤器,该过滤器通过基于线性或跳过列表的搜索来实现上述检查。 图3描绘了使用线性搜索方法实施以下系统调用集的过滤器:读取(0),写入(1),退出(15)和sigreturn(60)。Ln。 7 – 12实现了一个标准的前导,该前言断言该体系结构确实是x86-64。 此项检查至关重要,因为它可以确保所允许的系统调用号与所执行的系统调用之间的映射是正确的。

例如,假设此检查丢失,并且getuid(102)(一种无害的系统调用)存在于允许的集中。如果目标进程(x86-64)被破坏,并且攻击者发出syscall no。 102,通过int $ 0x80(或sysenter),过滤器将允许syscall,但内核将改为执行套接字调用:即x86(32位)中编号为102的syscall,有效地提供了攻击者的网络访问功能。 签入ln。 9拒绝了所有与x86-64不同的体系结构,而ln签入。 12拒绝与x32 ABI [50] .4相对应的syscall。强制/搜索的大部分在ln中实现。 13 – 16(BPF_JEQ语句)。 请注意,cBPF不允许循环,因此sysfilter使用循环展开来实现线性搜索(即“ if-else if -…- else”构造)。 如果发生不允许的syscall,则sysfilter终止进程(第4条, SECCOMP_RET_KILL_PROCESS )。 附录(第B部分)中的图9说明了一个cBPF过滤器,该过滤器使用跳过列表方法来实现搜索。

sysfilter如下注入已编译的过滤器。首先,它生成一个动态共享对象,即libsysfilter.so。 接下来,它使用patchelf [61]将上述共享对象与主二进制文件链接起来; libsysfilter.so仅包含注册为构造函数的单个功能install_filter。 上面的最终结果是ld.so将在主二进制文件初始化期间自动加载libsysfilter.so并调用install_filter(请参见图1F)。

install_filter在装入时使用seccomp系统调用[47]附加编译的cBPF过滤器。 重要的是,在调用seccomp(使用SECCOMP_SET_MODE_FILTER)之前,将通过调用prctl(使用PR_SET_NO_NEW_PRIVS)来声明调用线程的no_new_privs属性,并禁止通过使用set-user-ID的其他执行程序来获取新特权, 设置组ID或其他功能。 最后,install_filter将参数SECCOMP_FILTER_FLAG_TSYNC [47]传递给seccomp,以使各个过滤器对所有正在执行的线程可见,同时它也使用SECCOMP_FILTER_FLAG_SPEC_ALLOW [47]来禁用推测性存储绕过(SSB)缓解措施。 注意,后者是可配置的。 但是,仅当将来源未知的BPF程序加载到内核空间中以进一步协助进行Spectre攻击时,SSB缓解才有意义[37](变量4 [25])— sysfilter cBPF程序既不是恶意程序也不是攻击者控制的程序。

使用上述方法安装过滤器后,相应的进程只能执行以开发人员为准的系统调用。 请注意,ld.so包含在分析范围内,因此在运行时(例如,通过dlopen / dlclose)对其他库的初始化/完成以及任何其他与ld.so相关的功能均受无缝支持。

至关重要的是,no_new_privs保证过滤器在其生命周期内固定到受保护的进程中,即,即使该进程被完全破坏,攻击者也无法删除过滤器。 回想一下,过滤本身是在内核模式下进行的,仅使用syscall号作为输入。 不会检查syscall参数,也不会访问用户空间内存,从而避免了与并发和(基于包装器)syscall过滤有关的陷阱[17,92]。 此外,还无缝支持使用seccomp-BPF的应用程序。 BPF过滤器是可堆叠的,这意味着一个过程可以连接多个过滤器。 如果存在多个过滤器,则内核始终强制执行最严格的操作。

处理execve sysfilter可以通过执行不同的程序来防止执行旁路。 具体来说,即使允许一个(受损的)进程调用execve,它仍然不能通过调用另一个具有(可能)更大的允许的系统调用集的可执行文件来扩展其允许的系统调用集。 如果该进程试图在文件系统中构建恶意的可执行文件,从而允许所有系统调用(或某些被阻止的系统调用)并执行它,则同样如此。 过滤器固定和堆栈对于确保进程仅根据最小特权原则[76]只能减少其允许的系统调用集至关重要,但是由于保留了进程属性,它们确实干扰了execve

例如,假设程序P1和P2具有以下syscall集。 P1:0(读取),1(写入),15(退出)和59(执行); P2:0(读取),1(写入),2(打开),3(关闭),8(搜索),9(mmap),11(munmap),56(克隆),61(wait4),79(getcwd) ),96(gettimeofday),102(getuid),115(getgroups),202(futex),292(dup3)和317(seccomp)。 如果P2是正常调用的,则它将成功运行。 但是,如果通过P1调用P2,则生成的进程将不能发出除读取,写入,退出和执行之外的任何其他系统调用(P2甚至不需要最后两个)。 为解决此问题,sysfilter支持两种不同的execve模式:(a)联合和(b)分层。

在联合模式下,给定一组程序fP1; P2; :::; PNg,可以通过execve以任何组合调用,其中SY S1; SY S2; :::; PN SN是允许的syscall集合,即sysfilter构造 一个过滤器,它强制执行SY S1; SY S2; :::; SY SN的并集并将其附加到所有它们。 这将使每个进程都能正常运行,因为它支持所需的syscall,但过于接近最小特权-每个程序都有效地继承了集合中所有其他特权(相对于syscall API)。 在上面的示例中,联合将导致使用以下系统调用集执行P1和P2:f0 – 3; 8; 9; 11; 15; 56; 59; 61; 79; 96; 102; 115; 202; 292; 317克

在分层模式下,sysfilter以与上述相同的方法开始,但是每次进程调用execve时都会进一步纠正(减少)syscall集。 在我们的示例中,这将导致以集合f0 – 3; 8; 9; 11; 15; 56; 59; 61; 79; 96; 102; 115; 202; 292; 317; 317g执行P1,并进一步减小为f0 – 3; 8; 9; 11; 56; 61; 79; 96; 102; 115; 202; 292; 317g,即将执行P2。 请注意,分层模式仍会导致某些进程(相对于访问OS服务)具有更高的特权(而不是全部)。

如果特定(一个或多个)程序需要关于execve的特殊处理,则可以将配方以及相应的syscall集提供给执行工具,以描述sysfilter如何在execve调用上运行。如果指定了联合模式,则sysfilter只会将一组不同的syscall集(通过单独的JSON文件提供)拼接在一起,并编译附加到作用域中所有程序的单个筛选器。 在分层模式的情况下,该配方描述了调用者和被调用者之间的(执行)关系,从而使sysfilter可以构造不同的过滤器,作用域内的每个程序都必须遵循上面的模型。

更重要的是,我们的结果(第5节)表明,通过采用静态值跟踪分析来解决execve调用的第一个参数,可以在某种程度上实现配方创建的自动化。 但是,请注意,sysfilter不适用于调用任意脚本或程序(例如,命令行解释器,托管的运行时环境)的沙盒应用程序; 其他方案,例如Hails [21],SHILL [56]和Web API Manager [82],则更适合此任务。

3.3 原型实现

我们的原型实现包括C / C ++的≈2:5 K LOC和Python的≈150 LOC,以及各种shell脚本(胶水代码;≈120 LOC)。 更具体地说,我们在Egalito框架之上实现了提取工具[95]。Egalito是二进制重新编译器。 它通过首先将二进制代码提升到与布局无关的,特定于机器的中间表示(IR),称为EIR,然后允许“工具”检查或更改它,从而就地重写二进制代码。

我们将提取工具实现为Egalito“通过”(C / C ++),它使用第3.1节中概述的技术来创建分析范围,构造VCG并提取相应的系统调用集。 请注意,我们没有利用Egalito的二进制重写功能。 我们仅利用框架的API精确地分解相应的二进制文件并将其代码转换为EIR形式,进而用于实现构建DCG所需的分析,识别用于构建ACG的所有AT功能,修剪不可访问的部分 用于组装VCG,识别系统调用指令,执行值跟踪等的调用图。我们选择Egalito而不是类似的框架,因为它采用了迄今为止最好的跳转表分析。

实施工具是用Python实现的,负责生成cBPF过滤器和libsysfilter.so,并使用patchelf将后者附加到主二进制文件中(请参阅第3.2节)。 最后,在sysfilter的开发过程中,我们还通过添加对手工编码的汇编的更好支持,修复了各种符号解析问题以及重新架构框架的各个部分以减少内存压力来改进了Egalito。 (我们将所有更改纳入上游。)

4 评估

我们从(1)正确性,(2)运行时性能开销和(3)有效性方面评估sysfilter。

测试平台我们在实验中使用了两台主机:(a)运行时性能测量是在配备64GB(DDR4)RAM,运行Devuan Linux(v2.1,内核v4.16)的8核Intel Xeon W-2145 3.7GHz CPU上进行的 ); (b)分析任务是在配备Arch Linux(内核v5.2)的8核AMD Ryzen 2700X 3.7GHz CPU上执行的,配备64GB(DDR4)RAM。 所有应用程序(SPEC CINT2006除外)均从Debian sid(开发发行版)[86]获得,因为它提供了最新版本的上游软件包以及调试/符号信息[93]。

正确性我们从带有sysfilter的各种程序包/项目中使用了411个二进制文件,包括GNU Coreutils,Nginx,Redis,SPEC CINT2006,SQLite,FFmpeg,MariaDB,Vim,GNU M4和GNU Wget,以提取并执行其相应的syscall集。 结果显示在表1中。沙盒化后,我们使用来自项目验证套件的≈38.5K测试对它们进行了压力测试。 (请注意,我们没有包含要求应用程序执行任意外部程序的测试,例如使用Vim脚本中使用的任意命令,Nginx中的Perl脚本以及用于在SQLite和M4中加载数据的任意shell脚本的测试。) ,sysfilter设法提取了各个syscall集的完整且紧密的过度逼近,表明我们的原型可以成功处理复杂的实际软件。

性能为了评估sysfilter对运行时性能的影响,我们使用了SPEC CINT2006(标准基准测试套件),Nginx(Web服务器)和Redis(数据存储),即总共19个程序二进制文件。 所选的二进制文件表示我们集合中性能最敏感的应用程序,非常适合演示相对开销。 我们还探索了不同的设置和配置,包括解释型和JIT编译的BPF过滤器,以及使用线性搜索实现沙箱的过滤器代码与使用基于跳过列表的方法的过滤器代码(第3.2节)。 在SPEC的情况下,我们观察到在所有条件和搜索方法下,运行时速度下降≤1%。

图4和图5说明sysfilter对Nginx(128)和Redis(103)的影响-括号中的数字表示相应的syscall集大小,而“ Binary”对应于基于跳过列表的过滤器。 我们将Nginx配置为使用4个工作进程,并使用wrk工具[23]测量了其吞吐量,并通过回送接口从4个线程(通过256个同时连接)生成了1分钟的请求。 总体而言,禁用JIT时,通过使用基于跳过列表的过滤器(与基于线性搜索的过滤器相比),sysfilter可以减少吞吐量的减少,吞吐量的最大减少分别为18%和7%。 拼版策略似乎可以通过拼版进行归一化,这表明在所有条件下最大吞吐量降低了6%。 我们使用内存工具[73]对Redis进行了类似的评估,将SET和GET请求与请求的比例为1:10进行了混合。 32字节数据元素的比率。 请求是从4个工作线程发出的,每个线程有128个同时连接,持续1分钟。 如果启用和不启用JIT,则sysfilter分别导致最大吞吐量降低11%和3%。 最后,在所有情况下,切换SECCOMP_FILTER_FLAG_SPEC_ALLOW [47](用于启用SSB缓解)都会产生额外的≈10%的开销。

有效性为了评估syscall过滤的安全性影响,我们通过询问Debian sid(约30K主要二进制文件)中所有C / C ++应用程序的百分比可以利用23个(众所周知的),研究了sysfilter如何减少OS内核的攻击面。 Linux内核漏洞-从内存泄露和损坏到直接特权升级-甚至在通过sysfilter进行加固之后也是如此。 表2中列出了受每个CVE影响的数据集中二进制文件的数量。根据确切的漏洞,仍然可以攻击内核的二进制文件的百分比范围为0.09%– 64.34%。 尽管sysfilter不能防御特定类型的攻击(例如,控制流或数据流劫持[87]),但我们的结果表明,它可以通过最低特权执行和(OS)攻击面减少来缓解现实威胁。

5 大规模系统调用分析

我们通过对Debian sid中所有C / C ++应用程序的syscall配置文件进行大规模研究来结束我们的工作,报告有关syscall集大小(例如,每个二进制文件的syscall数量),最常用和最不常用的syscall,syscall的见解。 网站分布(库与主要二进制文件)等。分析的结果不仅证明我们的设计合理,而且还可以帮助将来的系统调用策略机制。

我们考虑了来自Debian的三个主要存储库的软件包,即main,contrib和nonfree。 在撰写本文时,Debian sid发行版包含针对x86-64列出的50K软件包。 但是,我们排除了不包含可执行代码的软件包,例如文档软件包(* -doc),开发标头(* -dev)和调试符号(* -dbg,*-dbgsym); 元软件包和虚拟软件包; 不包含x8664二进制文件的与体系结构无关的软件包; 和仅包含共享库的软件包。请注意,共享库和其他排除的软件包可以在处理期间作为主要应用程序软件包的依赖项安装。 我们处理了8922个软件包中的33829个二进制文件,其中30398个(91.3%)可以成功分析。 提取工具的平均运行时间约为每个二进制文件30秒,其中90%的二进制文件在200秒内完成。 对于单次FCG传递,每个二进制文件的中值运行时间减少到约10秒

每个二进制文件的Syscall数量许多二进制文件仅使用syscall API的一小部分。 图6显示了每个已处理二进制文件使用的syscall数量的分布。在347个系统调用的总数中,一个二进制文件使用的最大系统调用数仅为215个系统调用,占系统调用API总数的62%。 我们观察到这种分布有一个长尾巴:即每个二进制文件的系统调用中位数为90个系统调用,其中第90个百分位数为145个系统调用。

除了一个例外,我们发现所有处理的二进制文件至少使用40个syscall。 唯一的例外是仅使用17个系统调用的静态链接二进制文件mtcp_restart-该二进制文件直接执行系统调用,而无需使用任何库包装程序。在一般情况下,由于加载共享库的初始化函数所包含的路径,即使是最简单的程序(例如/ bin / false)也要利用40个系统调用:例如,mmap和mprotect随处可见,因为它们始终可以从_start到达,甚至 在调用main之前。

库中的系统调用从每个二进制文件中提取系统调用时,我们记录其共享库中的哪个包含每次调用的系统调用指令。 在libc之后,第二个最常用的库是libpthread(由68.7%的二进制文件使用),在其中我们观察到40个syscalls。在进一步研究中,我们发现这是由于glibc使用宏直接调用syscalls。 接下来直接调用系统调用的最常见的库是libstdc ++(占二进制文件的37%),它直接调用futex(202)。 libnss_resolve(二进制文件的32%,3个系统调用)和libglib-2.0(17%,5个系统调用)。

虽然我们将对库系统调用的全面分析留给以后的研究,但我们注意到一些共同的主题。 库倾向于在没有可用的libc包装函数(例如futex和gettid)的情况下直接调用syscall。 我们还观察到许多库直接调用特定于其核心功能的系统调用,也许是在处理现有包装器不可用或不足的情况下。 例如,我们注意到诸如libgcrypt和libcrypto之类的密码库直接调用了与密码相关的系统调用,如getrandom和keyctl。

FCG逼近的有效性图7显示了我们使用三种FCG逼近方法(第3.1.2节)从每个二进制文件中提取的系统调用数:DCG,DCG [ACG和VCG,按VCG的计数排序。 每个二进制表示图形上的三个点(即每种方法一个点)。对于所有二进制文件,VCG的计数始终在DCG和DCG [ACG]之间。 因此,对于我们的数据集,VCG代表FCG的安全,严格的过度逼近。

dl {open,sym}和execve通过使用我们的值跟踪方法(请参见第3.1.3节),sysfilter可以解析所有dlsym参数的≈89%,所有dlopen参数的≈37%和所有execve的30%。 我们在常见的库中观察到一些情况,其中值跟踪失败,这可能得益于特殊处理(§A):例如,约50%的dlsym故障与NSS功能有关,而约5%的dlopen故障与Kerberos插件有关。 最后,我们发现了两个孤立的情况,其中sysfilter无法构造syscall集:Qemu和Stress-ng包含任意的syscall调度程序(如glibc的syscall()),鉴于它们的功能,可以预期。 否则,我们发现系统调用站点严格遵循“ mov $ SYS_NR,%eax; syscall”。

6 相关工作

系统调用使用分析 Tsai 等。 [88]进行了与我们类似的研究(在Ubuntu v15.04中的二进制文件上),以表征syscall API以及ioctl,fcntl,prctl和伪文件系统API的用法。 他们的研究重点是量化API复杂性和与安全性相关的使用趋势,例如未使用的syscall和在旧有API上采用安全API。 我们的研究专门针对syscall API,作为评估提取工具的一种手段。我们认为这项工作是相辅相成的,并专注于使分析更具可扩展性,精确性和完整性。 具体而言,与sysfilter相反,Tsai等人的调用图构造方法。 不会考虑初始化/完成代码,也不会标识属于全局struct / union / C ++对象初始化程序的AT函数。

静态系统调用筛选过去,在各种情况下都对Syscall筛选进行了广泛的研究。 确实,sysfilter与Wagner和Dean [89]的开创性工作共享了许多问题和提出的解决方案,后者使用静态分析技术将有效syscall的序列建模为非确定性有限自动机(NDFA)。这项工作以及该时代[22]的其他工作,旨在建立用于入侵检测目的的程序执行模型。
相反,sysfilter专注于通过确定总的系统调用集(独立于顺序)来构建优化的(OS可执行的)seccomp-BPF筛选器,这提供了更紧凑的表示形式,并消除了与控制流建模相关的挑战。 此外,sysfilter使用二进制分析,而Wagner和Dean的工作需要重新编译目标二进制文件和共享库,这严重限制了其方案的可部署性。

Shredder [55]对Windows二进制文件执行静态分析,以识别应用程序使用的API调用和参数。具体来说,它通过蹦床将调用限制为对syscall包装函数的调用,但需要CFI才能提供有效的保护。 Ghavamnia等人独立和并行地从事我们的工作。 提议的Confine [20] :(主要是)基于静态分析的系统,用于在“包含容器的”(即Docker)应用程序上自动提取和实施syscall策略。 Confine需要访问C库代码(例如glibc或musl),而其调用图构造方法会考虑范围内非libc代码中的每个函数。 另外,它依赖于objdump,因此需要用于精确反汇编的符号。 sysfilter可以在剥离的二进制文件上运行,而我们的FCG构造方法可以生成更紧密的syscall集。

与sysfilter类似,Zeng等人。 [98]使用二进制分析来识别有效的系统调用集,但是它们的方法缺乏健全性:其调用图近似方法部分依赖于指向分析来解析函数指针的目标。相反,sysfilter会标识所有采用地址的函数,以避免与此方法相关的印象问题。 此外,Zeng等。 使用定制的Linux内核执行强制执行以提供每个进程的系统调用表,而基于seccomp-BPF的方法在库存的Linux内核v3.5或更高版本中可用

动态系统调用筛选Systrace [69]使用动态跟踪来生成系统调用策略,并实现用于执行的用户空间守护程序。 Mutz等。 [58]和Maggi等。 [51]开发用于基于主机的入侵检测的统计模型,该模型作为设计选择会固有地产生假阴性,从而有可能阻碍程序的有效执行。Ostia [18]提供了一种系统调用沙箱机制,该机制将策略决策委派给每个进程的代理,而许多有关容器去膨胀[90]和沙箱[42,90]的早期工作也依赖于动态跟踪。 相比之下,sysfilter并不依赖于动态syscall跟踪或统计模型,它们会生成不完整的策略,而是安全地使程序的真实syscall集过分逼近,因此不会破坏程序的执行。

现有软件Firefox [57],Chrome [8]和OpenSSH [63]中的seccomp-BPF使用seccomp-BPF来通过手动制定的策略对自身进行沙箱处理,而诸如Docker和Podman之类的容器运行时允许使用seccomp-BPF 过滤容器syscall的策略。 默认情况下,Docker应用了一个过滤器,该过滤器禁用了44个系统调用[15],而Podman支持使用ptrace动态跟踪系统调用来为容器构建配置文件。 两者都完全支持用户指定的过滤器[75]。 sysfilter可以与此类软件无缝集成,从而提供用于自动/准确生成各个syscall集的设备。

Binary Debloating sysfilter与最新的软件debloing技术共享目标和分析方法。Quach等。 [71]提出了一种基于编译器的方法,该方法将依赖项信息嵌入程序中,并使用自定义加载程序选择性地仅将共享库的必需部分加载到内存中。 TRIMMER [80]专门基于用户定义的配置来设计LLVM字节码,而Koo等人的工作则是基于CVM。 [39]利用覆盖率信息基于功能指令删除代码。 C-Reduce [74],Perses [85]和CHISEL [27]使用delta-debugging技术使用一系列提供的测试用例来编译最小化的程序。 与以前的方法不同,Razor [70]不需要源代码,并且实现了动态跟踪程序,可以从一组测试用例中重建程序的FCG。 Nibbler [1]使用的分析与sysfilter最相似。 但是,Nibbler需要使用符号,而sysfilter只能在已剥离的二进制文件上运行

7 总结

我们介绍了sysfilter:一个基于静态(二进制)分析的框架,该框架通过实施最小特权原则自动限制攻击者可以(滥用)的OS服务,并通过限制可用的syscall集来减少OS内核的攻击面 用户土地流程。 我们引入了一组程序分析来以可扩展,精确和完整的方式构造syscall集,并使用411个二进制文件(来自各种实际C / C ++项目)和≈38.5K测试强调了我们的原型的正确性。 使用sysfilter进行防护时,请测试其功能。此外,我们使用SPEC CINT2006,Nginx和Redis评估了系统调用执行机制的影响,展示了最小的运行时速度。 最后,我们以约30K C / C ++应用程序的系统调用配置文件(Debian sid)进行了大规模研究。 我们认为sysfilter是一种实用且强大的工具,可为无限访问syscall API的问题提供解决方案。

Availability :sysfilter的原型实现可从以下网址获得:https://gitlab.com/brown-ssl/sysfilter

Acknowledgments : 我们感谢牧羊人Aravind Prakash和匿名审阅者的宝贵反馈。 海军研究办公室(ONR)和国防高级研究计划局(DARPA)通过N00014-17-1-2788和HR001118C0017奖项来支持这项工作。 本文所表达的任何观点,发现,结论或建议均为作者的观点,不一定反映美国政府,ONR或DARPA的观点。

来源:大1234草

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年1月18日
下一篇 2021年1月18日

相关推荐