CVE: 2020-14356 & 2020-25220
作者:pi3
一个Linux内核Cgroup BPF释放后使用漏洞与两个CVE的简短故事
名称: Linux内核Cgroup BPF释放后使用漏洞 作者: Adam Zabrocki (pi3@pi3.com.pl) 日期: 2020年5月27日
背景概述
2019年,Tejun Heo发现了一个与cgroup_bpf生命周期相关的竞争条件问题,可能导致双重释放和其他内存损坏。该漏洞在5.3内核中修复。关于该问题和补丁的更多信息可在此找到: https://lore.kernel.org/patchwork/patch/1094080/
Roman Gushchin在新修复的代码中发现了另一个可能导致释放后使用漏洞的问题。他的报告和修复可在此找到: https://lore.kernel.org/bpf/20191227215034.3169624-1-guro@fb.com/
在修复讨论中,Alexei Starovoitov指出在不持有cgroup_mutex的情况下遍历cgroup层次结构可能很危险: https://lore.kernel.org/bpf/20200104003523.rfte5rw6hbnncjes@ast-mbp/
然而,Roman和Alexei得出结论认为这不应该是个问题: https://lore.kernel.org/bpf/20200106220746.fm3hp3zynaiaqgly@ast-mbp/
不幸的是,还存在另一个与Cgroup BPF释放逻辑相关的释放后使用漏洞。
“新"漏洞 - 技术细节
在LKRG开发和测试期间,我的一个虚拟机在关机过程中生成了内核崩溃。该特定机器当时运行最新的内核(5.7.x),我编译时包含了所有调试信息以及SLAB DEBUG功能。分析崩溃后发现与LKRG无关。后来我确认没有LKRG的内核也会遇到此问题:
|
|
崩溃发生在函数”__cgroup_bpf_run_filter_skb"中,具体是在这段代码:
|
|
其中RAX: 0000000000000000。但在SLAB_DEBUG下进行复现测试时,我经常得到RAX: 6b6b6b6b6b6b6b6b。
这表明存在某种释放后使用漏洞。该漏洞可从用户模式触发。
漏洞根本原因
损坏的指针(struct cgroup *)来自这行代码:
|
|
此代码与CONFIG_SOCK_CGROUP_DATA相关。Linux源码在"cgroup-defs.h"文件中有相关注释说明:
|
|
在崩溃中我们可以看到:
|
|
描述的socket保持"sk_cgrp_data"指针,指示其"附加"到cgroup2。然而,cgroup2已被销毁。
漏洞触发场景
- 进程创建socket,两者都在某个cgroup v2(非root)中
- cgroup BPF仅适用于cgroup2
- 在某些时候net_prio或net_cls被使用:
- 此操作禁用cgroup2 socket匹配
- 现在,所有相关socket应转换为使用net_prio,sk_cgrp_data应更新
- socket被克隆,但对cgroup的引用未被克隆
- 这实质上将socket移动到新的cgroup
- 旧cgroup中的所有任务必须死亡,当这种情况发生时,该cgroup也会死亡
- 当原始进程开始"使用"socket时,它可能尝试访问已经"死亡"的cgroup,这实质上生成释放后使用条件
修复与CVE分配
CVE-2020-14356
我决定在2020年7月中旬向Linux内核安全邮件列表报告此问题。Roman Gushchin回复了我的报告,并建议验证当提交ad0f75e5f57c(“cgroup: fix cgroup_sk_alloc() for sk_clone_lock()")应用时是否仍能复现此问题。该提交在我报告前几天合并到Linux内核git源码树。我仔细验证了它确实修复了问题。
之后,Greg KH决定将Roman的补丁反向移植到LTS内核。同时,我决定申请CVE编号(通过RedHat)来跟踪此问题:
- CVE-2020-14356被分配来跟踪此问题
- 由于某些未知原因,此漏洞被分类为NULL指针解引用
RedHat正确地将此问题确认为释放后使用漏洞,但在CVE MITRE门户中我们可以看到非常不准确的描述。
CVE-2020-25220
在分析此漏洞期间,我联系了Brad Spengler。当此问题的补丁被反向移植到LTS内核时,Brad注意到它与预先存在的反向移植冲突,并且上游反向移植看起来不正确。
反向移植的补丁缺少检查:
|
|
这可能导致引用计数器错误,并最终再次出现释放后使用。看起来稳定内核的反向移植补丁仍然有错误。
我再次联系RedHat,他们开始为自己的内核提供正确的补丁。然而,LTS内核仍然有错误。我还要求为此问题分配单独的CVE,但RedHat建议我自己完成。
总结
- 原始问题(由CVE-2020-14356跟踪)影响从4.5+到5.7.10的内核
- RedHat正确修复了所有他们的内核,并有正确的错误描述
- CVE MITRE仍然有无效和误导性的描述
错误反向移植的补丁(由CVE-2020-25220跟踪)影响内核:
- 4.19直到版本4.19.140(不包括)
- 4.14直到版本4.14.194(不包括)
- 4.9直到版本4.9.233(不包括)
*grsecurity内核从未受CVE-2020-25220影响
此致, Adam ‘pi3’ Zabrocki