G.O.S.S.I.P 阅读推荐 2022-07-01 KCFI

admin 2022年7月2日01:26:14G.O.S.S.I.P 阅读推荐 2022-07-01 KCFI已关闭评论90 views字数 1336阅读4分27秒阅读模式

正式进入到2022年的下半年!虽然上半年犹如一场梦,但是我们还记得昨天的论文推荐,今天就接着关注CFI的一些技术动向(今天更像是一个随笔,乱七八糟地给大家推荐一系列相关的文章)。


从Linux Kernel 5.13开始,LLVM编译器提供的CFI支持已经可以比较成熟地应用起来了。具体地,在编译过程中,编译器为内核中所有的合法的函数地址建立了一个巨大的跳转表("jump tables"),然后会在执行indirect call的时候根据这个跳转表来决定是否合法。关于这个实现的具体细节,在lwn.net上有一篇文章Control-flow integrity in 5.13(https://lwn.net/Articles/856514/)进行了详细的讨论。


目前的LLVM CFI in Linux主要检查的是callee的函数类型,不允许一个特定类型的指针去访问和它类型不匹配的函数(地址),然而在Kernel中,有一些(奇奇怪怪的)代码用法往往会导致传统的CFI失效,例如下面的代码声明:


图片



其中的参数`cmp`是一个函数指针,注意到在`list_sort`的内部实现中,有这么一个对`cmp`的使用:


图片


这里产生了一个会导致CFI violation的问题——由于代码执行了对`cmp`的转型(转成了`cmp_func`类型),而导致了问题。修复这类问题需要对很多代码进行重构(例如重新调整函数的声明,涉及到很多人工开销)。此外,在这个版本的CFI中,需要配合开启link-time optimization(LTO,https://lwn.net/Articles/744507/)才能保证CFI策略的部署,而LTO本身在编译过程中会花掉很多时间。当前只有ARM64版本的Kernel上开启了LLVM CFI,包括x86的其它一些架构尚未完全支持。

考虑到上述的一些问题,最近lwn.net又介绍了一个新的CFI实现工作(https://lwn.net/Articles/898040/),在这个名为KCFI的工作中(目前还没有合并到LLVM主线代码),抛弃了对jump table的使用和对LTO的依赖,并希望能更好支持x86_64结构。

简单地说,KCFI为每个被可能被间接调用的函数生成了一个特定的32-bit hash值,把它记录在被int 3指令包围的代码段中(防止被reuse),并在函数的entry point(prologue)上执行对这个hash值的检查(注意到这个时候有个问题,就是代码段必须是可读可执行,如果是execute-only属性就会出问题)。关于这个实现特性的具体细节可关注:https://lwn.net/ml/linux-kernel/[email protected]/


可以看到,工业界在对一些安全特性的引入上显得不是那么fancy,毕竟生产环境中存在太多需要考虑的因素,关于CFI的更多讨论,近年来也有很多很多论文,在2016年有一篇论文从CFI的精确性、安全性和性能三方面进行了一个横向测试,大家有兴趣可以读一下。

图片

图片

论文PDF:

https://dl.acm.org/doi/10.1145/3054924

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月2日01:26:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   G.O.S.S.I.P 阅读推荐 2022-07-01 KCFIhttps://cn-sec.com/archives/1150878.html