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,因为它位于内存块外部。但通过以下步骤可以绕过这一限制:
- 用户空间修改
&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 内核检查逻辑
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 控制流劫持
- 修改块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小工具进行堆栈跳转:
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. 防御建议
- 加强对
consumer_pos的修改权限控制 - 增加内存分配时的重叠检查
- 更新到已修复该漏洞的内核版本
6. 参考资源
- Google Security Research漏洞文档
- 相关内核源码:
kernel/bpf/ringbuf.c