add new description paper for rap and hl-cfi
This commit is contained in:
parent
9e8b798645
commit
88ae21a33c
|
@ -0,0 +1,29 @@
|
|||
all: pdf
|
||||
|
||||
pdf: paper.pdf
|
||||
docx: paper.docx
|
||||
|
||||
paper.pdf: paper.md references.bib
|
||||
pandoc \
|
||||
-s \
|
||||
--pdf-engine=xelatex \
|
||||
--bibliography references.bib \
|
||||
--filter pandoc-fignos \
|
||||
--filter pandoc-tablenos \
|
||||
--filter pandoc-eqnos \
|
||||
--filter pandoc-citeproc \
|
||||
paper.md -o paper.pdf
|
||||
|
||||
paper.docx: paper.md references.bib
|
||||
pandoc \
|
||||
-s \
|
||||
--bibliography references.bib \
|
||||
--filter pandoc-fignos \
|
||||
--filter pandoc-tablenos \
|
||||
--filter pandoc-eqnos \
|
||||
--filter pandoc-citeproc \
|
||||
paper.md -o paper.docx
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
${RM} paper.pdf paper.docx
|
|
@ -0,0 +1,39 @@
|
|||
# PAX RAP and its optimizations
|
||||
|
||||
## Compiling the paper
|
||||
|
||||
By default, a PDF version will be produced. Simply run
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
This will produce `paper.pdf`. To build a DOCX file, run
|
||||
|
||||
```bash
|
||||
make docx
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* [pandoc](https://pandoc.org/): converting Markdown to PDF via LaTeX
|
||||
* [pandoc-citeproc](https://github.com/jgm/pandoc-citeproc): reference/citation support
|
||||
* [pandoc-fignos](https://github.com/tomduck/pandoc-fignos): numbering and referencing of figures
|
||||
* [pandoc-tablenos](https://github.com/tomduck/pandoc-tablenos): numbering and referencing of tables
|
||||
* [pandoc-eqnos](https://github.com/tomduck/pandoc-eqnos): numbering and referencing of equations
|
||||
* `make` (optional)
|
||||
|
||||
### Installation
|
||||
|
||||
One way, using `stack` and `pip`:
|
||||
|
||||
```bash
|
||||
stack install pandoc
|
||||
stack install pandoc-citeproc
|
||||
sudo pip install pandoc-fignos pandoc-tablenos pandoc-eqnos
|
||||
```
|
||||
|
||||
## Attribution
|
||||
|
||||
* `nature.csl` obtained from https://github.com/citation-style-language/styles
|
||||
* figure taken from https://xkcd.com/688/
|
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-GB">
|
||||
<info>
|
||||
<title>Nature</title>
|
||||
<id>http://www.zotero.org/styles/nature</id>
|
||||
<link href="http://www.zotero.org/styles/nature" rel="self"/>
|
||||
<link href="http://www.nature.com/nature/authors/gta/index.html#a5.4" rel="documentation"/>
|
||||
<link href="http://www.nature.com/srep/publish/guidelines#references" rel="documentation"/>
|
||||
<author>
|
||||
<name>Michael Berkowitz</name>
|
||||
<email>mberkowi@gmu.edu</email>
|
||||
</author>
|
||||
<category citation-format="numeric"/>
|
||||
<category field="science"/>
|
||||
<category field="generic-base"/>
|
||||
<issn>0028-0836</issn>
|
||||
<eissn>1476-4687</eissn>
|
||||
<updated>2018-10-24T14:53:43+00:00</updated>
|
||||
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
|
||||
</info>
|
||||
<macro name="title">
|
||||
<choose>
|
||||
<if type="bill book graphic legal_case legislation motion_picture report song" match="any">
|
||||
<text variable="title" font-style="italic"/>
|
||||
</if>
|
||||
<else>
|
||||
<text variable="title"/>
|
||||
</else>
|
||||
</choose>
|
||||
</macro>
|
||||
<macro name="author">
|
||||
<names variable="author">
|
||||
<name sort-separator=", " delimiter=", " and="symbol" initialize-with=". " delimiter-precedes-last="never" name-as-sort-order="all"/>
|
||||
<label form="short" prefix=", "/>
|
||||
<et-al font-style="italic"/>
|
||||
</names>
|
||||
</macro>
|
||||
<macro name="access">
|
||||
<choose>
|
||||
<if variable="volume"/>
|
||||
<else-if variable="DOI">
|
||||
<text variable="DOI" prefix="doi:"/>
|
||||
</else-if>
|
||||
<else-if type="webpage" variable="URL" match="all">
|
||||
<text term="available at" text-case="capitalize-first" suffix=": "/>
|
||||
<text variable="URL" suffix=". "/>
|
||||
<group prefix="(" suffix=")" delimiter=": ">
|
||||
<text term="accessed" text-case="capitalize-first"/>
|
||||
<date variable="accessed">
|
||||
<date-part name="day" suffix=" " form="ordinal"/>
|
||||
<date-part name="month" suffix=" "/>
|
||||
<date-part name="year"/>
|
||||
</date>
|
||||
</group>
|
||||
</else-if>
|
||||
</choose>
|
||||
</macro>
|
||||
<macro name="issuance">
|
||||
<choose>
|
||||
<if type="bill book graphic legal_case legislation motion_picture report song thesis chapter paper-conference" match="any">
|
||||
<group delimiter=", " prefix="(" suffix=").">
|
||||
<text variable="publisher" form="long"/>
|
||||
<date variable="issued">
|
||||
<date-part name="year"/>
|
||||
</date>
|
||||
</group>
|
||||
</if>
|
||||
<else>
|
||||
<date prefix="(" suffix=")." variable="issued">
|
||||
<date-part name="year"/>
|
||||
</date>
|
||||
</else>
|
||||
</choose>
|
||||
</macro>
|
||||
<macro name="container-title">
|
||||
<choose>
|
||||
<if type="article-journal">
|
||||
<text variable="container-title" font-style="italic" form="short"/>
|
||||
</if>
|
||||
<else>
|
||||
<text variable="container-title" font-style="italic"/>
|
||||
</else>
|
||||
</choose>
|
||||
</macro>
|
||||
<macro name="editor">
|
||||
<choose>
|
||||
<if type="chapter paper-conference" match="any">
|
||||
<names variable="editor" prefix="(" suffix=")">
|
||||
<label form="short" suffix=" "/>
|
||||
<name and="symbol" delimiter-precedes-last="never" initialize-with=". " name-as-sort-order="all"/>
|
||||
</names>
|
||||
</if>
|
||||
</choose>
|
||||
</macro>
|
||||
<citation collapse="citation-number">
|
||||
<sort>
|
||||
<key variable="citation-number"/>
|
||||
</sort>
|
||||
<layout vertical-align="sup" delimiter=",">
|
||||
<text variable="citation-number"/>
|
||||
</layout>
|
||||
</citation>
|
||||
<bibliography et-al-min="6" et-al-use-first="1" second-field-align="flush" entry-spacing="0" line-spacing="2">
|
||||
<layout>
|
||||
<text variable="citation-number" suffix="."/>
|
||||
<group delimiter=" ">
|
||||
<text macro="author" suffix="."/>
|
||||
<text macro="title" suffix="."/>
|
||||
<choose>
|
||||
<if type="chapter paper-conference" match="any">
|
||||
<text term="in"/>
|
||||
</if>
|
||||
</choose>
|
||||
<text macro="container-title"/>
|
||||
<text macro="editor"/>
|
||||
<text variable="volume" font-weight="bold" suffix=","/>
|
||||
<text variable="page"/>
|
||||
<text macro="issuance"/>
|
||||
<text macro="access"/>
|
||||
</group>
|
||||
</layout>
|
||||
</bibliography>
|
||||
</style>
|
|
@ -0,0 +1,264 @@
|
|||
---
|
||||
documentclass:
|
||||
- ctexart
|
||||
---
|
||||
|
||||
# PaX/Grsecurity RAP及其优化
|
||||
|
||||
### zet
|
||||
|
||||
*zet ([feqin1023@gmail.com](mailto:feqin1023@gmail.com)), HardenedLinux.org, GuangZhou, China*
|
||||
|
||||
## 简介
|
||||
|
||||
Return-Oriented Programming (ROP)是一种比较高级攻击的方式,能够利用现有代码通过找到的gadgets串来执行攻击者想进行的
|
||||
任何操作,现有的防御手段只有Control-flow integrity(CFI)是针对这种攻击进行防御的。此外常规针对存储破坏的防御canary,
|
||||
NX, ASLR等,对于这种攻击无效。
|
||||
|
||||
PaX/Grsecurity RAP是一种CFI的实现方式,本文描述了RAP的实现,以及针对RAP的优化,以及重新实现的hl-cfi的实现。
|
||||
|
||||
## 1 导引
|
||||
|
||||
Return-Oriented Programming (ROP)[@Krahmer05]是一种比较高级攻击的方式,是code-reuse attack的一种,能够利用现有代码通过找
|
||||
到的gadgets串来执行攻击者想进行的任何操作,已经有研究者表明gadgets是图灵完备的[@Shacham07]。现有的防御手段只有
|
||||
Control-flow integrity(CFI)是针对这种攻击进行防御的。此外常规针对存储破坏的防御canary, NX, ASLR等,对于这种攻击无效。
|
||||
|
||||
自从CFI[@Abadi05]提出以来,各种实现层出不群,包括gcc upstream里的vtv以及LLVM cfi。不过这些实现有明显的硬伤,vtv防御
|
||||
virtual table,LLVM cfi只是一个forward cfi实现,没有backward部分。比较而言,PaX/Grsecurity RAP[@PaX18]对于kernel级别的
|
||||
防护是最理想的选择,不经包括forward而且包括backward实现,backward cfi的实现应该是业界第一个也是唯一一个可以进入生产环境
|
||||
的。
|
||||
|
||||
### 贡献
|
||||
本文主要是贡献是从编译器角度分析PaX RAP以及Hardlinux hl-cfi[@Hardenedlinux18]的改进以及实现。
|
||||
|
||||
### 内容
|
||||
本文的内容安排包括:2 背景,3 算法与实现,4 结论以及未来工作。
|
||||
|
||||
## 2 背景
|
||||
Return-Oriented Programming (ROP)[@Krahmer05]是return-into-libc[@Pincus04]的一种一般形式,也就是最终的目标不是进入libc。
|
||||
ROP的攻击由串接执行一连串的gadgets进行,gadgets是一些几条汇编语言的代码片段,一般来说以 __ret__ 指令结尾,因为ROP gadgets
|
||||
是图灵完备的[@Shacham07],理论上来说,ROP可以按照攻击者的目的来做任何计算。
|
||||
|
||||
下图简要描述了一个常规的ROP攻击图示,图片来源于[@Carlini14]。左边的Stack是用户stack初始化为gadgets的地址,右边的
|
||||
Instructions以ret结尾就是gadgets由左边stack处的地址实线指向。这个攻击的结果是将数0x32400加到地址0x4a304120所存储的值。
|
||||
|
||||
![ROP图示](figures/rop-case.png){图1: ROP图示}
|
||||
|
||||
由于这个攻击可以看到ROP发生的根本原因:就是 __call/jmp/ret__ 违反了原始代码控制流。基于这个因素所以有研究者提出了
|
||||
Control-flow integrity(CFI)[@Abadi05]。原理就是在编译器编译最开始的未经过破坏的源代码的时候就分析控制流,
|
||||
在 __call/jmp/ret__ 发生的地方插入检测代码,在代码运行的时候来判断报错是否有攻击行为发生。
|
||||
|
||||
关于ROP更详细的描述可以参考[@Krahmer05][@Shacham07][@Carlini14]。
|
||||
|
||||
|
||||
## 3 算法与实现
|
||||
|
||||
下面将描述PaX RAP的算法及其实现,分析这种方式带来的性能损耗,和Hardenedlinux社区所做的优化改进。
|
||||
|
||||
由上一节背景的描述可知,ROP发生的根源就是因为违反了原始代码的控制流。所以对于相应的检测防御也很简单:在原始控制流转移的
|
||||
地方由编译器插入检测代码。这其中就会有一个trade-off的考虑:怎么样在保证一定精度的情况下作出防御?
|
||||
|
||||
对于控制流的转移可以分为:
|
||||
|
||||
1) 直接调用的call/jmp
|
||||
2) 间接调用的call/jmp - RAP forward cfi
|
||||
3) 返回 - RAP backward cfi
|
||||
|
||||
对于情况1来说不需要考虑,因为直接调用都是位于 _.text_ 段,只读的section不会发生控制流ROP的攻击。所以ROP的防御就是针对情况2和3。
|
||||
|
||||
理论上来说最理想的防御当然是:对于每个会被间接调用的函数在进入该函数的时候作出检测,对于每个 __ret__ 作出检测。对于情况3的
|
||||
__ret__ 来说可以确定有 __ret__ 就意味着返回,也就是我们必须处理的检测点,也就是backward cfi的实现点,也就是对于所有 __ret__
|
||||
都需要处理。但是对于情况2来说复杂了许多,所有优化以及考虑都在于情况2里面。对于会被间接调用的函数这个问题是一个NP问题,是
|
||||
一个典型的pointer analysis的问题,也就是求解一个函数指针的指向范围是什么,相对地也就是求一个函数是不是会被间接调用也就是
|
||||
有没有被函数指针所指向,这个问题在编译器领域大概伴随着优化编译器的最开始研究(大约是1970年)一直进行到现在。
|
||||
|
||||
PaX RAP是使用gcc plugin[@gccinternals]来实现的,gcc plugin是gcc提供给第三方程序的一个钩子,可以回调第三方的代码,可以在
|
||||
gcc内部满足条件的时候输出信息,可以在gcc某个pass之后输出信息也可以调用第三方的代码作为某个pass,只要根据规范提供给gcc想
|
||||
插入的pass点就行了。其他的详细功能请参考gcc-internals[@gccinternals]或者gcc代码。
|
||||
|
||||
### RAP forward cfi
|
||||
|
||||
RAP的实现是做为几个gcc pass通过gcc plugin插入gcc来进行的。由上一段的分析知道求解精确的函数是否被间接调用以及函数指针的指
|
||||
向范围是一个NP问题,所以学术界和工程界有数不清的学术paper以及实现出现,在gcc内部的实现来说有一个flow-insensitive analysis
|
||||
和一个比较精确的flow-sensitive的算法,insensitive的算法非常简单,就是根据编译器的分析以及函数的声明来判断函数有没有可能
|
||||
被间接调用,代码如下:比如判断是不是static有没有取过函数的地址。
|
||||
|
||||
_flow-insensitive analysis :_
|
||||
|
||||
```
|
||||
static inline bool
|
||||
may_be_aliased (const_tree var) {
|
||||
return (TREE_CODE (var) != CONST_DECL
|
||||
&& !((TREE_STATIC (var) || TREE_PUBLIC (var) || DECL_EXTERNAL (var))
|
||||
&& TREE_READONLY (var)
|
||||
&& !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (var)))
|
||||
&& (TREE_PUBLIC (var) || DECL_EXTERNAL (var) || TREE_ADDRESSABLE (var)));
|
||||
}
|
||||
```
|
||||
|
||||
flow-sensitive analysis算法无数,gcc的实现基本上是描述于paper[@Hardekopf09]里的算法,在gcc summit也有开发者的
|
||||
paper[@Berlin05]描述。是基于Constraint set的一类算法,只不过是在gcc中间代码tree-ssa的基础上,针对ssa做了改进,这样基于
|
||||
ssa的一个稀疏算法。详细的实现参考[@Hardekopf09][@Berlin05]。这是一个流敏感的算法,也就是对于block内部的语句有分析,也会
|
||||
进入函数的内部。总是是一个比较精确的算法。
|
||||
|
||||
介绍完,RAP遇到的难点,接着介绍RAP对间接函数的处理,RAP做了一个更粗略的trade-off,当函数被间接调用的时候当前的调用点,
|
||||
除了函数指针没有任何信息,这里dereference函数指针会得到函数类型,函数类型和函数指针的指向是静态分析唯一能够知道的信息,
|
||||
RAP放弃了函数指针的指向,只抽取了函数的类型,对得到的函数类型做hash运算,然后得到一个hash值,这个hash值就是RAP间接检测
|
||||
的标准。hash值的计算算法是SipHash-2-4[@Aumasson12],函数类型则是按照标准规范包括返回值和参数[@C11-standard]。接着在间接
|
||||
调用的地方插入检测代码。RAP的检测代码插入在gcc tree-ssa[@Novillo03][@Novillo04]的表示层,在gcc内部表示来说tree-ssa之前是
|
||||
tree-ast[@Merrill03],而之后是rtl[@gccinternals]。tree-ssa是几乎整个gcc重要优化pass的实现点。
|
||||
|
||||
_PaX RAP forward cfi alogrithms:_
|
||||
|
||||
```
|
||||
for all gimple code of all function
|
||||
hashValue = computeHash(currentFunctionType);
|
||||
insertHashValueBeforeCurrentFunction(hashValue);
|
||||
if (isFunctionPointer(currentPointer))
|
||||
functionType = *currentPointer;
|
||||
hashValue = computeHash(functionType);
|
||||
insertHashValueCheckBeforeCurrentIndirectCall(currentPointer, hashValue);
|
||||
```
|
||||
|
||||
```
|
||||
insertHashValueBeforeCurrentFunction(hashValue)
|
||||
fprintf(asm_out_file, "\t.quad %#llx", hashValue);
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
insertHashValueCheckBeforeCurrentIndirectCall(currentPointer, hashValue);
|
||||
value = (long)*((long *)currentPointer - 8);
|
||||
if (value == hashValue)
|
||||
currentPointer();
|
||||
else
|
||||
catchAttack();
|
||||
```
|
||||
|
||||
上面给出的是RAP forward cfi实现的算法伪代码,在RAP的实现上有三个问题:
|
||||
|
||||
1) 因为RAP没有使用pointer analysis,所以会对全部函数都输出hash值。
|
||||
2) 上面的伪代码在RAP的实现上是在tree-ssa表示层,所以其实是几条gimple等效的伪代码,但是RAP的实现上这些gimple代码是作为一个整体插入gcc的,而且插入的位置是gcc的所有tree-ssa优化pass之后,也就是gcc根本不会感知到这些代码的存在,也就是说gcc不会去分析这些代码,也不会去优化这些代码。
|
||||
3) 安全上的考虑,RAP的实现是针对函数类型编码hash,所有函数类型都是同一个hash值,所以这是一个可能的漏洞。
|
||||
|
||||
基于以上的三个问题所以我们给出了Hardenedlinux hl-cfi的实现(hl的意思high level)。
|
||||
|
||||
_hl-cfi alogrithms:_
|
||||
|
||||
```
|
||||
for all gimple code of all function
|
||||
hashValue = computeHash(currentFunctionType);
|
||||
if (isCurrentFunctionMaybeAttacked(currentFunction))
|
||||
insertHashValueBeforeCurrentFunction(hashValue);
|
||||
if (isFunctionPointer(currentPointer))
|
||||
functionType = *currentPointer;
|
||||
hashValue = computeHash(functionType);
|
||||
insertHashValueCheckBeforeCurrentIndirectCall(currentPointer, hashValue);
|
||||
```
|
||||
|
||||
_解决RAP实现上的问题1_
|
||||
|
||||
```
|
||||
isCurrentFunctionMaybeAttacked(currentFunction)
|
||||
lookupPointerAnalysis(currentFunction)
|
||||
```
|
||||
|
||||
_解决RAP实现上的问题2_
|
||||
|
||||
|
||||
```
|
||||
insertHashValueCheckBeforeCurrentIndirectCall(currentPointer, hashValue)
|
||||
|
||||
+-------
|
||||
stmt1;
|
||||
call fptr;
|
||||
+-------
|
||||
|
||||
change to =>
|
||||
|
||||
// insertHashValueCheckBeforeCurrentIndirectCall(currentPointer, hashValue)
|
||||
+-------
|
||||
stmt1;
|
||||
lhs_1 = t_;
|
||||
ne_expr (lhs_1, s_); // hsahValueCheck()
|
||||
// FALLTHRU
|
||||
<bb ???> # true
|
||||
cfi_catch();
|
||||
<bb ???> # false
|
||||
call fptr;
|
||||
+--------
|
||||
```
|
||||
|
||||
insertHashValueCheckBeforeCurrentIndirectCall(currentPointer, hashValue)的插入实现为block级别的gimple code,而且hl-cfi
|
||||
的插入点是在tree-ssa pass的最开始处,在pass_build_ssa_passes之前,所以这里需要实现上的处理,需要模拟gcc已经跑过的所有代
|
||||
码对于一个假想的检测insertHashValueCheckBeforeCurrentIndirectCall()函数的表示在当前pass点是个什么样子,然后插入对应的代
|
||||
码。而且对于hl-cfi来说我们需要使用gcc pointer analysis,所以对于isCurrentFunctionMaybeAttacked()的调用又得保证在
|
||||
pass_ipa_pta(gcc flow-sensitive analysis)之后。cfi的检测代码的优化是一个复杂的问题,因为这是一个运行时才能知道的函数指针
|
||||
值,常规静态分析优化[@Gupta93]基本上没有用。所以hl-cfi的实现相对来说考虑的只能是尽可能利用gcc现有的优化,检测代码的hash
|
||||
常数可以被gcc做register promotion[@Makarov07],以及分析信息传播到整个fucntion里面[@Novillo05]进一步给其他pass提供机会。
|
||||
在hl-cfi构建block以及edge的时候给gcc提供profile信息[@Hubicka05][@Ramasamy08],使用profile的相关基础代码。给后续的优化
|
||||
pass比如code placement以及cache优化的pass提供信息。
|
||||
|
||||
_解决RAP实现问题3_
|
||||
|
||||
```
|
||||
// 这部分代码因为复杂度的原因,并没有在hl-cfi里面实现,下面只是提供算法。
|
||||
|
||||
for all gimple code of all function
|
||||
if (isCurrentFunctionMaybeAttacked(currentFunction))
|
||||
insertHashValueBeforeCurrentFunction(hashValue);
|
||||
if (isFunctionPointer(currentPointer))
|
||||
if (pointerAliasSetChanged(currentPointer, currentCodePlace))
|
||||
functionType = *currentPointer;
|
||||
// 根据当前的代码分析结果来给一个变化的seed来得到一个
|
||||
// 跟当前函数指针和函数类型相关的hash值。
|
||||
hashValue = computeHash(functionType, seed);
|
||||
insertCurrentHashValue(currentPointer, functionType, currentCodePlace);
|
||||
else
|
||||
hashValue = lookupHashValue(currentPointer, fucntionType, currentCodePlace);
|
||||
insertHashValueCheckBeforeCurrentIndirectCall(currentPointer, hashValue);
|
||||
```
|
||||
|
||||
为了解决问题3,计算一个动态的hash值,根据函数指针的变化而变化。
|
||||
|
||||
### RAP backward cfi
|
||||
|
||||
为了解决 __ret__ 的问题,PaX Team提出了世界上大概唯一一个backward cfi的软件实现方案。
|
||||
|
||||
```
|
||||
for all rtl code of all function
|
||||
if (isCurrentRTLIsRet(currentRTL))
|
||||
// 调用gcc内置函数,得到返回地址。
|
||||
retAddress = __builtin_return_address();
|
||||
// 在gcc里,这个函数类型通过分析可以知道的。
|
||||
hashValue = getHash(functionType);
|
||||
insertRetCheck(retAddress,hashValue);
|
||||
```
|
||||
|
||||
对于这个检测函数的描述跟RAP实现略有差异,RAP比较的是一个hashValue的取反的值。
|
||||
|
||||
```
|
||||
insertRetCheck(retAddress, hashValue)
|
||||
if (long*((long *)retAddress - 8) != hashValue)
|
||||
catchAttack();
|
||||
```
|
||||
|
||||
对于backward cfi来说这大概是业界唯一的实现,而且跟RAP forward cfi的一样,也是一串没有经过编译器优化的代码直接出现在输出
|
||||
的object里,不过这是唯一的算法,实在想不到优化的方案,只能期待硬件更新支持backward cfi,比如类似ARM PA[@zet17]。
|
||||
|
||||
## 4 结论
|
||||
|
||||
对于hl-cfi的实现和RAP的实现在spec CPU2017上做了一个对比测试,因为RAP本身是为了linux kernel防御,在优化RAP以及开发hl-cfi
|
||||
的时候,为了方便测试以及开发,我们抽取出了RAP作为一个独立的项目,hl-cfi也是如此,正因为这是两个针对kernel的项目,因为应
|
||||
用代码外部library依赖的问题,CPU2017的很多测试跑不过,跑过的数据如下:
|
||||
|
||||
RAP | hl-cfi | hl-cfi - RAP / RAP
|
||||
--- | --- | ---
|
||||
2.15| 2.35| 9.3%
|
||||
|
||||
大约有9.3%的性能提升。
|
||||
|
||||
由于hl-cfi的实现依赖于pointer analysis,如果使用lto[@Glek10]来编译linux kernel,相信hl-cfi应该会有一个更佳的表现。lto模
|
||||
式更好的一个特点是只需要修改linux kernel的编译构建脚本,对于hl-cfi本身不需要做改变。期待未来lto的编译能够普及。
|
||||
|
||||
## 引用
|
Binary file not shown.
|
@ -0,0 +1,168 @@
|
|||
@Article{Abadi05,
|
||||
Author="M. Abadi, M. Budiu, Ú. Erlingsson, and J. Ligatti",
|
||||
Title={"Control-flow integrity: Principles, implementations, and applications"},
|
||||
Journal="Proceedings of the 12th ACM conference on Computer and communications security",
|
||||
Year="2005",
|
||||
Pages="i340-i353",
|
||||
}
|
||||
|
||||
@Article{Aumasson12,
|
||||
Author="JP. Aumasson, D.J. Bernstein",
|
||||
Title="{SipHash: A Fast Short-Input PRF}",
|
||||
Journal="Progress in Cryptology - INDOCRYPT",
|
||||
Year="2012",
|
||||
Pages="i489-i508",
|
||||
}
|
||||
|
||||
@Article{Berlin05,
|
||||
Author="D. Berlin",
|
||||
Title="{Structure aliasing in GCC}",
|
||||
Journal="In Proceedings of the 2005 GCC Summit",
|
||||
Year="2005",
|
||||
Pages="i25-i36",
|
||||
}
|
||||
|
||||
@Article{C11-standard,
|
||||
Author="ISO/IEC",
|
||||
Title="{Information technology — Programming languages — C}",
|
||||
Journal="ISO/IEC 9899:2011",
|
||||
Year="2011",
|
||||
Pages="i42",
|
||||
}
|
||||
|
||||
@Article{Carlini14,
|
||||
Author="N. Carlini, D. Wagner",
|
||||
Title="{ROP is still dangerous: Breaking modern defenses.}",
|
||||
Journal="In USENIX Security Symposium",
|
||||
Year="2014",
|
||||
Pages="i385-i399",
|
||||
}
|
||||
|
||||
@Article{Gupta93,
|
||||
Author="R. Gupta",
|
||||
Title="{Optimizing array bound checks using flow analysis}",
|
||||
Journal="ACM Letters on Programming Languages and Systems",
|
||||
Year="1993",
|
||||
Pages="i135-i150",
|
||||
}
|
||||
|
||||
@Article{Glek10,
|
||||
Author="T. Glek, J. Hubicka",
|
||||
Title="{Optimizing real-world applications with GCC Link Time Optimization}",
|
||||
Journal="In Proceedings of the 2010 GCC Summit",
|
||||
Year="2010",
|
||||
}
|
||||
|
||||
@Article{gccinternals,
|
||||
Author="GCC-internals",
|
||||
Title="{Chapter rtl and plugins}",
|
||||
Journal="GNU Compiler Collection (GCC) Internals",
|
||||
Year="2017",
|
||||
}
|
||||
|
||||
@Article{Hubicka05,
|
||||
Author="J. Hubicka",
|
||||
Title="{Profile driven optimisations in GCC}",
|
||||
Journal="In Proceedings of the 2005 GCC Summit",
|
||||
Year="2005",
|
||||
Pages="i107-i124",
|
||||
}
|
||||
|
||||
@Article{Hardenedlinux18,
|
||||
Author="zet",
|
||||
Title="{hl-cfi project}",
|
||||
Journal="https://github.com/hardenedlinux/RAP-optimizations",
|
||||
Year="2018",
|
||||
}
|
||||
|
||||
@Article{Hardekopf09,
|
||||
Author="B. Hardekopf, C. Lin",
|
||||
Title="{Semi-sparse flow-sensitive pointer analysis}",
|
||||
Journal="Proceedings of the 36th annual ACM SIGPLAN-SIGACT symposium on Principles of programming languages",
|
||||
Year="2009",
|
||||
Pages="i226-i238",
|
||||
}
|
||||
|
||||
@Article{Krahmer05,
|
||||
Author="S. Krahmer",
|
||||
Title="{x86-64 buffer overflow exploits and the borrowed code chunks exploitation technique}",
|
||||
Year="2005",
|
||||
}
|
||||
|
||||
@Article{Merrill03,
|
||||
Author="J. Merrill",
|
||||
Title="{GENERIC and GIMPLE: A New Tree Representation for Entire Functions}",
|
||||
Journal="In Proceedings of the 2003 GCC Summit",
|
||||
Year="2003",
|
||||
Pages="i171-i180",
|
||||
}
|
||||
|
||||
@Article{Makarov07,
|
||||
Author="V N. Makarov",
|
||||
Title="{The integrated register allocator for GCC}",
|
||||
Journal="In Proceedings of the 2007 GCC Summit",
|
||||
Year="2007",
|
||||
Pages="i77-i90",
|
||||
}
|
||||
|
||||
@Article{Novillo03,
|
||||
Author="D. Novillo",
|
||||
Title="{Tree SSA – A New Optimization Infrastructure for GCC}",
|
||||
Journal="In Proceedings of the 2003 GCC Summit",
|
||||
Year="2003",
|
||||
Pages="i181-i194",
|
||||
}
|
||||
|
||||
@Article{Novillo04,
|
||||
Author="D. Novillo",
|
||||
Title="{Design and Implementation of Tree SSA}",
|
||||
Journal="In Proceedings of the 2004 GCC Summit",
|
||||
Year="2004",
|
||||
Pages="i119-i130",
|
||||
}
|
||||
|
||||
@Article{Novillo05,
|
||||
Author="D. Novillo",
|
||||
Title="{A Propagation Engine for GCC}",
|
||||
Journal="In Proceedings of the 2005 GCC Summit",
|
||||
Year="2005",
|
||||
Pages="i175-i184",
|
||||
}
|
||||
|
||||
@Article{PaX18,
|
||||
Author="PaX",
|
||||
Title="{Frequently Asked Questions About RAP}",
|
||||
Journal="https://www.grsecurity.net/rap_faq",
|
||||
Year="2018",
|
||||
}
|
||||
|
||||
@Article{Pincus04,
|
||||
Author="J. Pincus, B. Baker",
|
||||
Title="{Beyond stack smashing: Recent advances in exploiting buffer overruns}",
|
||||
Journal="Security & Privacy, IEEE.",
|
||||
Year="2004",
|
||||
Pages="i20-i27",
|
||||
}
|
||||
|
||||
@Article{Ramasamy08,
|
||||
Author="V. Ramasamy, P. Yuan, D. Chen, and R. Hundt",
|
||||
Title="{Feedback-Directed Optimizations in GCC with Estimated Edge Profiles from Hardware Event Sampling}",
|
||||
Journal="In Proceedings of the 2008 GCC Summit",
|
||||
Year="2008",
|
||||
Pages="i87-i101",
|
||||
}
|
||||
|
||||
@Aricle{Shacham07,
|
||||
Author="H. Shacham",
|
||||
Title="{structural variant discovery by integrated paired-end and split-read analysis}",
|
||||
Journal="Proceedings of the 14th ACM conference on Computer and communications security",
|
||||
Year="2007",
|
||||
Pages="i552-i561",
|
||||
}
|
||||
|
||||
@Aricle{zet17,
|
||||
Author="zet",
|
||||
Title="{ARMv8.3-A PA在GCC里的相关实现}",
|
||||
Journal="https://hardenedlinux.github.io/gnu/toolchains/security/2017/06/13/ARM_PA.html",
|
||||
Year="2017",
|
||||
}
|
|
@ -57,9 +57,10 @@ static bitmap sensi_funcs;
|
|||
#if BUILDING_GCC_VERSION < 7000
|
||||
/* Contains the type database which are pointer analysis can not sloved */
|
||||
static struct pointer_set_t *sensi_func_types;
|
||||
#else
|
||||
/* gcc has change the struct gimple base type.!!! */
|
||||
#define gimple gimple*
|
||||
#define gimple_t_ gimple
|
||||
#else
|
||||
#define gimple_t_ gimple*
|
||||
static hash_set<tree> *sensi_func_types;
|
||||
#endif
|
||||
|
||||
|
@ -543,7 +544,7 @@ create:
|
|||
//free_dominance_info (enum cdi_direction dir)
|
||||
|
||||
static tree
|
||||
build_cfi_hash_tree (gimple cs, int direct, tree *target_off_type_p)
|
||||
build_cfi_hash_tree (gimple_t_ cs, int direct, tree *target_off_type_p)
|
||||
{
|
||||
//tree hash_tree, var;
|
||||
rap_hash_value_type val;
|
||||
|
@ -617,10 +618,10 @@ build_cfi_hash_tree (gimple cs, int direct, tree *target_off_type_p)
|
|||
/* Help function called when the fe-cfi violate catched. */
|
||||
|
||||
static basic_block
|
||||
cfi_catch_and_trap_bb (gimple cs, basic_block after)
|
||||
cfi_catch_and_trap_bb (gimple_t_ cs, basic_block after)
|
||||
{
|
||||
tree trap;
|
||||
gimple g;
|
||||
gimple_t_ g;
|
||||
gimple_seq seq;
|
||||
basic_block bb;
|
||||
#if 0
|
||||
|
@ -707,12 +708,12 @@ insert_cond_and_build_ssa_cfg (gimple_stmt_iterator *const gp,
|
|||
tree t_,
|
||||
tree t_t)
|
||||
{
|
||||
const gimple cs = gsi_stmt (*gp);
|
||||
gimple g;
|
||||
const gimple_t_ cs = gsi_stmt (*gp);
|
||||
gimple_t_ g;
|
||||
gimple_stmt_iterator gsi;
|
||||
gimple assign; // used for dumps.
|
||||
gimple cond; // test gimple we insert.
|
||||
gimple call; // call label gimple we insert.
|
||||
gimple_t_ assign; // used for dumps.
|
||||
gimple_t_ cond; // test gimple we insert.
|
||||
gimple_t_ call; // call label gimple we insert.
|
||||
basic_block old_bb;
|
||||
basic_block catch_bb;
|
||||
edge edge_false;
|
||||
|
@ -840,7 +841,7 @@ insert_cond_and_build_ssa_cfg (gimple_stmt_iterator *const gp,
|
|||
static void
|
||||
build_cfi (gimple_stmt_iterator *labile_gsi_addr, basic_block* labile_bb_addr)
|
||||
{
|
||||
gimple cs;
|
||||
gimple_t_ cs;
|
||||
tree th; // hash get behind the function definitions.
|
||||
tree sh; // hash get before indirect calls.
|
||||
tree target_off_type = NULL;
|
||||
|
@ -964,7 +965,7 @@ hl_cfi_execute ()
|
|||
gsi_next (&labile_gsi))
|
||||
{
|
||||
//tree decl;
|
||||
gimple cs;
|
||||
gimple_t_ cs;
|
||||
//tree hash;
|
||||
cs = gsi_stmt (labile_gsi);
|
||||
/* We are in forward cfi only cares about function call */
|
||||
|
|
Loading…
Reference in New Issue