CVE-2024-41009 Linux内核的bpf ringbuf中存在一个缓冲区重叠漏洞分析与利用
字数 1517 2025-08-20 18:17:07

Linux内核BPF Ringbuf缓冲区重叠漏洞分析与利用 (CVE-2024-41009)

1. 漏洞概述

本漏洞存在于Linux内核的BPF环形缓冲区(bpf ringbuf)实现中,允许攻击者通过精心构造的内存操作,使第二个分配的内存块与第一个内存块重叠,从而修改第一个内存块的头部结构。这可能导致内核崩溃或权限提升。

2. 背景知识

2.1 BPF环形缓冲区结构

BPF环形缓冲区内部实现为一个大小为2的幂次方的循环缓冲区,使用两个逻辑计数器:

  • consumer_pos: 表示消费者消费数据的位置(用户空间可读写)
  • producer_pos: 表示生产者已保留的数据量(用户空间只读)

结构体定义如下:

struct bpf_ringbuf {
    wait_queue_head_t waitq;
    struct irq_work work;
    u64 mask;
    struct page **pages;
    int nr_pages;
    spinlock_t spinlock ____cacheline_aligned_in_smp;
    atomic_t busy ____cacheline_aligned_in_smp;
    unsigned long consumer_pos __aligned(PAGE_SIZE); // 用户空间可读写
    unsigned long producer_pos __aligned(PAGE_SIZE); // 用户空间只读
    unsigned long pending_pos;
    char data[] __aligned(PAGE_SIZE);
};

2.2 环形缓冲区记录头

BPF_FUNC_ringbuf_reserve函数用于从BPF_MAP_TYPE_RINGBUF中分配内存,预留8字节空间用于记录头部结构:

/* 8字节的环形缓冲区记录头结构 */
struct bpf_ringbuf_hdr {
    u32 len;
    u32 pg_off;
};

3. 漏洞分析

3.1 漏洞原理

正常情况下,eBPF程序无法修改bpf_ringbuf_hdr,因为它位于内存块外部。但通过以下步骤可以绕过这一限制:

  1. 用户空间修改&rb->consumer_pos
  2. 使得第二次分配的内存块与第一次分配的内存块重叠
  3. 通过重叠区域修改第一个内存块的头部

3.2 具体利用步骤

  1. 创建大小为0x4000的BPF_MAP_TYPE_RINGBUF
  2. 在调用BPF_FUNC_ringbuf_reserve前将consumer_pos修改为0x3000
  3. 分配块A(位于[0x0, 0x3008]),eBPF程序可编辑[0x8, 0x3008]
  4. 分配块B(大小为0x3000),由于consumer_pos已修改,检查会通过
  5. 块B位于[0x3008, 0x6010],eBPF程序可编辑[0x3010, 0x6010]

3.3 内核检查逻辑

static void *__bpf_ringbuf_reserve(struct bpf_ringbuf *rb, u64 size) {
    ...
    len = round_up(size + BPF_RINGBUF_HDR_SZ, 8);
    ...
    prod_pos = rb->producer_pos;
    new_prod_pos = prod_pos + len;
    
    /* 检查环形缓冲区是否溢出 */
    if (new_prod_pos - cons_pos > rb->mask) {
        // 失败路径
        spin_unlock_irqrestore(&rb->spinlock, flags);
        return NULL;
    }
    // 成功路径
}

由于cons_pos被修改为0x3000,new_prod_pos为0x6010,rb->mask为0x4000-1,条件满足,分配成功。

3.4 内存布局

环形缓冲区内存布局特点:

  • 每个数据页面被映射两次,实现"虚拟"连续读取
  • [0x0, 0x4000]和[0x4000, 0x8000]指向相同的数据页面
  • 可通过[0x4000, 0x4008]访问块B,这将指向块A的头部

4. 漏洞利用

4.1 控制流劫持

  1. 修改块A的pg_off为2,使bpf_ringbuf_restore_from_rec计算的元数据页面指向rb->consumer_pos
  2. 用户空间通过mmap控制rb->consumer_pos内容
  3. 构造bpf_ringbuf中的work字段
  4. 调用bpf_ringbuf_commit时传入BPF_RB_FORCE_WAKEUP,触发irq_work_queue(&rb->work)
  5. 内核执行构造的irq_work函数指针

4.2 KASLR绕过

参考现有技术绕过内核地址空间布局随机化(KASLR)。

4.3 ROP链构造

利用以下ROP小工具进行堆栈跳转:

0x00000000004b78b1 : push rbx ; or byte ptr [rbx + 0x41], bl ; pop rsp ; pop r13 ; pop rbp ; ret

特点:

  • RBX/RDI包含work字段地址
  • 可控制从RDI + 0x18开始的ROP数据
  • 通过ROP链覆盖core_pattern触发漏洞

5. 防御建议

  1. 加强对consumer_pos的修改权限控制
  2. 增加内存分配时的重叠检查
  3. 更新到已修复该漏洞的内核版本

6. 参考资源

Linux内核BPF Ringbuf缓冲区重叠漏洞分析与利用 (CVE-2024-41009) 1. 漏洞概述 本漏洞存在于Linux内核的BPF环形缓冲区(bpf ringbuf)实现中,允许攻击者通过精心构造的内存操作,使第二个分配的内存块与第一个内存块重叠,从而修改第一个内存块的头部结构。这可能导致内核崩溃或权限提升。 2. 背景知识 2.1 BPF环形缓冲区结构 BPF环形缓冲区内部实现为一个大小为2的幂次方的循环缓冲区,使用两个逻辑计数器: consumer_pos : 表示消费者消费数据的位置(用户空间可读写) producer_pos : 表示生产者已保留的数据量(用户空间只读) 结构体定义如下: 2.2 环形缓冲区记录头 BPF_FUNC_ringbuf_reserve 函数用于从 BPF_MAP_TYPE_RINGBUF 中分配内存,预留8字节空间用于记录头部结构: 3. 漏洞分析 3.1 漏洞原理 正常情况下,eBPF程序无法修改 bpf_ringbuf_hdr ,因为它位于内存块外部。但通过以下步骤可以绕过这一限制: 用户空间修改 &rb->consumer_pos 值 使得第二次分配的内存块与第一次分配的内存块重叠 通过重叠区域修改第一个内存块的头部 3.2 具体利用步骤 创建大小为0x4000的 BPF_MAP_TYPE_RINGBUF 在调用 BPF_FUNC_ringbuf_reserve 前将 consumer_pos 修改为0x3000 分配块A(位于[ 0x0, 0x3008]),eBPF程序可编辑[ 0x8, 0x3008 ] 分配块B(大小为0x3000),由于 consumer_pos 已修改,检查会通过 块B位于[ 0x3008, 0x6010],eBPF程序可编辑[ 0x3010, 0x6010 ] 3.3 内核检查逻辑 由于 cons_pos 被修改为0x3000, new_prod_pos 为0x6010, rb->mask 为0x4000-1,条件满足,分配成功。 3.4 内存布局 环形缓冲区内存布局特点: 每个数据页面被映射两次,实现"虚拟"连续读取 [ 0x0, 0x4000]和[ 0x4000, 0x8000 ]指向相同的数据页面 可通过[ 0x4000, 0x4008 ]访问块B,这将指向块A的头部 4. 漏洞利用 4.1 控制流劫持 修改块A的 pg_off 为2,使 bpf_ringbuf_restore_from_rec 计算的元数据页面指向 rb->consumer_pos 用户空间通过mmap控制 rb->consumer_pos 内容 构造 bpf_ringbuf 中的 work 字段 调用 bpf_ringbuf_commit 时传入 BPF_RB_FORCE_WAKEUP ,触发 irq_work_queue(&rb->work) 内核执行构造的 irq_work 函数指针 4.2 KASLR绕过 参考现有技术绕过内核地址空间布局随机化(KASLR)。 4.3 ROP链构造 利用以下ROP小工具进行堆栈跳转: 特点: RBX/RDI包含 work 字段地址 可控制从RDI + 0x18开始的ROP数据 通过ROP链覆盖 core_pattern 触发漏洞 5. 防御建议 加强对 consumer_pos 的修改权限控制 增加内存分配时的重叠检查 更新到已修复该漏洞的内核版本 6. 参考资源 Google Security Research漏洞文档 相关内核源码: kernel/bpf/ringbuf.c