Linux内核Cgroup BPF Use-After-Free漏洞分析:CVE-2020-14356与CVE-2020-25220

本文深入分析了Linux内核中Cgroup BPF子系统的Use-After-Free漏洞(CVE-2020-14356),揭示了在cgroup销毁后仍被引用的危险场景,同时披露了错误补丁引发的二次漏洞(CVE-2020-25220),影响范围涵盖4.5至5.7.10内核版本。

漏洞背景

2019年Tejun Heo发现cgroup_bpf生命周期存在的竞态条件问题(可能导致双重释放)。该漏洞在5.3内核中被修复。随后Roman Gushchin发现修复代码存在新的Use-After-Free问题。

漏洞细节

在LKRG开发测试期间发现内核崩溃,回溯显示问题出现在__cgroup_bpf_run_filter_skb函数中:

1
0xffffffff9423e801 <__cgroup_bpf_run_filter_skb+401>: mov 0x10(%rax),%rdi

此时RAX寄存器可能为NULL或已释放内存(0x6b6b6b6b6b6b6b6b)。崩溃触发路径为:

1
2
3
do_exit -> sock_close -> __sock_release -> inet_release -> tcp_close 
-> __tcp_push_pending_frames -> tcp_write_xmit -> __tcp_transmit_skb 
-> __ip_queue_xmit -> ip_finish_output -> __cgroup_bpf_run_filter_skb

关键问题在于:当net_prio/net_cls被激活时,cgroup2 socket匹配会被禁用,但已存在的socket仍保留对已销毁cgroup的引用。

漏洞验证

通过内核日志可观察到以下关键事件序列:

  1. cgroup: disabling cgroup2 socket matching due to net_prio or net_cls activation
  2. percpu ref (cgroup_bpf_release_fn) <= 0 after switching to atomic
  3. 最终触发UAF崩溃

CVE-2020-14356

原始漏洞修复补丁ad0f75e5f57c(需配合14b032b8f8fc)主要修改了:

1
2
3
4
5
6
7
8
9
void cgroup_sk_clone(struct sock_cgroup_data *skcd)
{
    if (skcd->val) {
        if (skcd->no_refcnt)  // 新增检查
            return;
        cgroup_get(sock_cgroup_ptr(skcd));
        cgroup_bpf_get(sock_cgroup_ptr(skcd));
    }
}

CVE-2020-25220

在LTS内核(4.14/4.19/4.9)的补丁中遗漏了关键检查:

1
2
if (skcd->no_refcnt)
    return;

导致引用计数错误,可能再次引发UAF。该问题后续由华为工程师提交正确修复。

影响范围

  • CVE-2020-14356:影响Linux内核4.5+至5.7.10
  • CVE-2020-25220:影响特定LTS版本:
    • 4.19 < 4.19.140
    • 4.14 < 4.14.194
    • 4.9 < 4.9.233
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计