Linux v4.20 中的安全特性
Linux内核v4.20已于今日发布!通过梳理变更内容,以下是我发现的一些有趣的安全相关特性:
stackleak插件
Alexander Popov将grsecurity的STACKLEAK插件移植到上游内核的工作取得了成果。虽然它已获得x86(和arm64)维护者的认可,但曾多次被Linus拒绝。现在一切符合Linus的期望,该插件及其x86粘合代码已合并。(Laura Abbott为arm64提供的架构特定部分实际上已在v4.19中合并。)该插件跟踪函数调用(具有足够大的堆栈使用量),以标记系统调用期间使用的堆栈最大深度。利用这些信息,在系统调用结束时,可以有效地毒化堆栈(即,不是清除整个堆栈,而是仅写入系统调用期间实际使用的部分)。每次系统调用后清除堆栈有两个主要好处。首先,不再有“未初始化”的值留在堆栈上,攻击者可能在下一个系统调用中使用这些值。其次,堆栈上任何敏感数据的生命周期缩短到仅在系统调用本身期间活动。这主要有趣,因为来自其他内核线程的任何信息泄露或侧信道攻击需要更精确地计时,以在堆栈数据被清除之前捕获它。
启用CONFIG_GCC_PLUGIN_STACKLEAK=y
意味着几乎所有未初始化变量缺陷都会消失,性能影响非常小(对于大多数工作负载似乎低于1%)。仍然可能的是,在单个系统调用内,后续有缺陷的函数调用可能使用堆栈上早期函数的“未初始化”字节。修复此问题需要编译器支持预初始化(例如,Clang已在开发中),但这可能会带来更大的性能影响。
在copy_*_user()中为内核地址引发故障
Jann Horn重新设计了x86内存异常处理,以大声通知当copy_{to,from}_user()
尝试访问未映射的内核内存时。在此之前,这些访问会导致静默错误(通常对调用者显示为EFAULT),使其与“常规”用户空间内存异常无法区分。这样做的目的是捕获例如未检查的__copy_to_user()
针对内核地址调用的情况。像syzcaller这样的模糊测试器无法注意到非常严重的错误,因为写入内核地址要么会破坏内存(可能在稍后检测到或未检测到),要么返回一个看起来操作正常的EFAULT。通过此更改,现在可以更容易地注意到缺少的access_ok()
检查。这甚至在v4.20期间已经在HID和Xen中捕获了另外两个角落案例。
Spectre v2用户空间缓解措施
对单线程间接分支预测器(STIBP)的支持已合并。这使得支持STIBP的CPU能够有效禁用超线程,以避免间接分支预测侧信道在同一物理CPU上的用户空间线程之间暴露信息。由于这是一个非常昂贵的解决方案,此保护被设为选择加入(通过显式prctl()或在seccomp()下隐式)。LWN有一篇关于细节的好文章。
初始化后跳转标签只读
Ard Biesheuvel注意到跳转标签在初始化后不需要可写,因此它们的数据结构被设为只读。由于它们指向内核代码,攻击者可能使用它们来操纵跳转目标,作为更改不应更改的内核代码的一种方式。最好将所有内容移动到只读内存区域,以将其从攻击者可能的内核目标中移除。
VLA移除完成
如v4.17、v4.18和v4.19中详细所述,许多人响应了我的呼吁,从内核中移除可变长度数组(VLA)。我统计自v4.16以来至少有153个提交被添加到内核以移除VLA,非常感谢Gustavo A. R. Silva、Laura Abbott、Salvatore Mesoraca、Kyle Spiers、Tobin C. Harding、Stephen Kitt、Geert Uytterhoeven、Arnd Bergmann、Takashi Iwai、Suraj Jitindar Singh、Tycho Andersen、Thomas Gleixner、Stefan Wahren、Prashant Bhole、Nikolay Borisov、Nicolas Pitre、Martin Schwidefsky、Martin KaFai Lau、Lorenzo Bianconi、Himanshu Jha、Chris Wilson、Christian Lamparter、Boris Brezillon、Ard Biesheuvel和Antoine Tenart。完成所有这些后,“-Wvla”已被添加到顶级Makefile中,因此我们将来不会再有任何VLA被添加回来。
每任务堆栈金丝雀,powerpc
长期以来,只有x86具有每任务内核堆栈金丝雀。其他架构会为启动生命周期生成单个金丝雀,并在每个任务中使用它。这意味着从一个任务暴露金丝雀会给攻击者提供他们在不同任务中单独攻击中欺骗金丝雀所需的一切。Christophe Leroy现在已在powerpc上解决了这个问题,集成了GCC对-mstack-protector-guard-reg
和-mstack-protector-guard-offset
选项的新支持。
由于假期,Linus在v4.20发布之前打开了合并窗口,让每个人在发布前一周发送拉取请求。v4.21正在制作中。:) 大家新年快乐!
编辑:澄清了stackleak细节,感谢Alexander Popov。还添加了每任务金丝雀说明。
© 2018 – 2019, Kees Cook。本作品根据知识共享署名-相同方式共享4.0许可协议授权。
评论 (1)
1条评论
你好Kees,感谢文章! 让我补充两点简要说明:
- STACKLEAK插件为具有大堆栈帧(>=CONFIG_STACKLEAK_TRACK_MIN_SIZE)的函数添加堆栈跟踪,而不是叶函数。
- 在单个系统调用内,后续有缺陷的函数使用未初始化内存可以利用早期函数留在堆栈上的数据。 最好的问候! 评论由Alexander Popov — 2018年12月24日 @ 10:24 pm