1.基本信息
2021S&P(A)
关键词:人机协同、API误用检测、主动学习、C/C++
作者目前是宾夕法尼亚大学的博士生,导师是Mayur Naik,这篇论文来自Mayur Naik的课题Machine Learning for Automated Program Reasoning。
简单介绍下这个课题:
Machine Learning for Automated Program Reasoning |
---|
Tools to analyze, repair, and verify programs rely on heuristics hand-engineered by experts, hindering them in aspects such as accuracy, scalability, and flexibility. This project investigates the use of machine learning techniques ranging from probabilistic graphical models to deep neural networks to overcome these limitations. |
该课题下文章:
- Arbitrar: User-Guided API Misuse Detection, S&P 2021.
- Code2Inv: A Deep Learning Framework for Program Verification, CAV 2020.
- Hoppity: Learning Graph Transformations to Detect and Fix Bugs in Programs, ICLR 2020.
- Learning Loop Invariants for Program Verification, NIPS 2018.
2.论文概述
motivation
现有的API误用检测工具要么期望有一个精确的API规范,这需要程序分析专家,要么假设正确的API用法遵循简单的习惯用法,这些习惯用法可以从代码中自动挖掘出来,而这些代码的准确性很差。
solution
提出了一种新的方法,允许常规程序员发现API的误用。
我们的方法与用户交互,对每个目标API方法的有效和无效用法进行分类。它通过使用一种主动学习算法,根据API使用的可能性对其无效进行排序,从而最大限度地减少了用户的负担。
result
在平均每个API方法的3轮用户交互中,ARBITRAR发现,40个新漏洞,其中18个补丁被接受。此外,在包含92个bug的benchmark中,ARBITRAR发现了由最先进的工具APISAN报告的所有已知bug,其假阳性率仅为51.5%,而APISAN的假阳性率为87.9%。
contribution
- 实现ARBITRAR,一个人机协同的API误用检测工具,它是精确的(即产生低误检率)、高效的(即需要几轮用户交互)和可扩展的(即在大规模的代码库中发现bug)。
- 提出了一种新的基于核密度估计的主动学习算法MD-KDE。特别是,MD-KDE选择API使用的未标记trace,该trace与API的正确使用trace的估计概率相差最大。
- 对ARBITRAR进行了广泛的评估。应用检查21个C/ C++程序中18个API method的使用,在平均每个API method 3轮用户交互后,ARBITRAR发现40个新bug。
- ARBITRAR的源代码公开于https://github.com/petablox/arbitrar
3.研究现状
该论文讨论了现有的API检测工具,API误用检测的工具大致可以分为两类。
类别A假定API的使用遵循可以从代码中挖掘的简单习惯用法。例如,APISan将扫描多个代码库,并收集一个特定API函数的所有用法。给定一个预定义的模式,它会在这些用法中找到“多数”和“少数”。如果有明显的少数,这些少数将被报告为警报。A类这些工具很容易使用。用户不需要知道任何关于工具或API的信息,因为规范是为代码挖掘的。因此,用户通常只需要一个命令就可以得到bug报告。
但现在的问题是,假设我们有大量的代码,并且有明确的多数和少数。 由于我们前面展示的实际API的复杂性,这种情况通常不成立。 如果将此应用于我们上一页PPT提到的png_destroy_write_struct函数,API将无法工作,因为首先没有大量的代码可挖掘。 此外,它依赖于预定义的模式来执行统计推理,这可能使它难以推广到任意API规范。
类别B允许用户完全控制编写API规范。这些例子包括Semmle, Sys和IMchecker。通常,这些工具为用户编写规范提供特定领域的语言。这些工具非常强大,因为用户可以编写相当复杂的规范。但问题也很明显,编写规范需要专业知识和时间。同时,如果API不太常用,人们可能会觉得不值得花时间编写规范。这也意味着这些工具的有效性取决于人写的规范的质量
4.Framework
4.1 overview
它以两阶段模式运行,第一个阶段是分析,该阶段生成包含大量围绕API method 的trace数据库。第二阶段,进入人机交互阶段,允许用户参与并发现API误用bug。
4.2 Trace Generation
problem:
在真实世界的大项目中例如linux,枚举出所有路径是不可能的,由于路径爆炸和工程限制。
solution:
使用under-constrained symbolic execution(详见2015年USENIX论文)
Finding Execution Contexts
步骤:
- 给出一个函数f中目标API method的调用点k;
- 调用这个程序的图G;
- 根据之前定义的上下文深度d,用上图算法计算执行上下文的集合Sk。
ReverseBFS:反向宽度优先搜索。
疑问点:在第6行,我们从每个计算范围中删除了目标API方法,因为我们只希望检查它是如何使用的,而不是如何实现的。
作者这里说的不是很懂,希望有小伙伴看到后可以帮忙解答下。
Under-Constrained Symbolic Execution
根据上述算法形成的上下文对
来生成。
under-constrained symbolic execution的结果是程序路径或者符号路径的集合。每个symbolic trace代表一个程序操作符号或者具体值的事件序列。
4.3 Trace Encoding
基于对各种API误用错误的分析,作者定义了用于对每个trace进行编码的feature列表。这个列表覆盖了大多数API误用。除此,作者提供了接口供用户使用Datalog自定义添加。
通过这feature表,将每个 symbolic trace转换成feature的布尔向量。
4.3 Active Learning and User Interaction
主动学习和用户交互这里使用了最大偏差的核密度估计算法(MD-KDE)。
KDE:kernel density estimation
g:acquisition function
我们这里的目标是尽可能快地提出有bug的API用法。那么主动学习算法是如何选择一条轨迹来实现这一点的呢?先假设P是用户标记的正轨迹集合N是负轨迹集合U是未标记的轨迹集合。最初所有的痕迹都没有标记。你会得到完整的输入数据集P和N是空集。随着用户提供的反馈越来越多,集合P和N将逐渐填充。
这简单地反映在下面的公式中,函数g是一个评分函数,它根据已知的正跟踪和负跟踪给每个未标记的跟踪一个评分。对于每个trace,我们只需从U中选择得分最大的x。为了选择最有可能的bug,我们做了一件非常简单的事情。也就是选择离bug最近、离非bug最远的未标记跟踪。
K选择的是一个带宽h的高斯核函数。核密度估计是非参数估计中的一种,不加入任何先验知识,根据数据本身的特点、性质来拟合分布,这样能比参数估计方法得出更好的模型。
这个图显示主动学习算法的实际运行情况。在本例中,我们希望通过函数png_destroy_read_struct找到API的误用。在第一次迭代中。我们的算法随机选择了一个标记蓝色三角形的轨迹,用户将其标记为非bug,这是由第二张图上的绿色十字表示的。在第二次迭代中,我们的算法立即遇到了一个实际的bug,它选择了距离第一个非bug最远的bug(在第三张图中用红色加号表示)。在第三次迭代中,我们的算法选择最接近前一个bug的那个,从而得到第二个bug。这个过程一直持续到用户停止使用为止。
在每一轮中,给定当前有标记的数据集,学习者首先利用采集函数计算出每个无标记数据点的排名分数,然后请专家评估得分最高的无标记数据点。直观地说,这样的数据点对应于算法认为最有可能误用目标API的跟踪(基于开发人员迄今为止提供的标签)。
5. Evolution
这个表格显示,每个API方法只需5轮迭代,就可以在benchmark中找到89%的bug,这大大超过了API标准。
这个图表显示了相对于迭代次数检测到的bug的百分比。可以看到,在零迭代的情况下,用户无法找到任何漏洞。但随着用户与系统的互动越来越多,比如在第5次迭代中,我们能够找到89%的bug。在最多20次迭代后,ARBITRAR会找到所有benchmark中列出的bug。
将ARBITRAR应用到Linux内核5.7,SSL , libpng,libbluetooth和许多依赖它们的包。总共发现了40个漏洞,平均来说,我们发现第一个漏洞时,每个用户每个API方法只进行了三轮交互。
证明了论文的主动学习算法是实时运行的。由于我们的MD-KDE算法的设计,我们能够将其优化为使用秩1更新,它在每次迭代中以线性时间复杂度执行。这使用户能够获得实时反馈,并减少了用户的等待时间,正如我们在许多其他静态分析工具中看到的那样。
6.总结
1.疑问:对于trace的处理,是否存在trace丢失问题?
作者最后在limitation中提到:与APISAN类似,只考虑对API方法的直接调用点。因此,trace生成技术可能会错过通过函数指针调用的API方法的跟踪。但是,我们可以使用point -to分析来解析函数指针目标,并在生成trace时考虑它们。
创新点:人机协同的主动学习