每日一PATCH——CVE-2010-4169

漏洞链接

https://nvd.nist.gov/vuln/detail/CVE-2010-4169

bugzilla链接

https://bugzilla.redhat.com/show_bug.cgi?id=651671

patch链接

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=63bfd7384b119409685a17d5c58f0b56e5dc03da

其他分析

https://xorl.wordpress.com/2010/12/01/cve-2010-4169-linux-kernel-perf_event_mmap-use-after-free/

漏洞分析

漏洞成因

参考其他链接:
在kernel的mm/mprotect.c中存在use-after-free漏洞。

SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
                unsigned long, prot)
{
        unsigned long vm_flags, nstart, end, tmp, reqprot;
        struct vm_area_struct *vma, *prev;
        int error = -EINVAL;
     ...
        vma = find_vma_prev(current->mm, start, &prev);
     ...
        for (nstart = start ; ; ) {
     ...
                if (tmp > end)
                        tmp = end;
                error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
                if (error)
                        goto out;
                perf_event_mmap(vma);
                nstart = tmp;
     ...
out:
        up_write(&current->mm->mmap_sem);
        return error;
}

After obtaining a pointer to the VMA that will be processed, it will enter a loop that will execute the actual mprotect(2) code. Inside that loop you can see a call to mprotect_fixup() which is a routine located in the same source code file that could lead to the following code path.(在访问VMA之后,会进入一个循环,在这个循环中有函数mprotect_fixup(),下面是mprotect_fixup()的定义:)

int
mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
        unsigned long start, unsigned long end, unsigned long newflags)
{
        struct mm_struct *mm = vma->vm_mm;
        unsigned long oldflags = vma->vm_flags;
     ...
        /*
         * First try to merge with previous and/or next vma.
         */
        pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
        *pprev = vma_merge(mm, *pprev, start, end, newflags,
                        vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma));
        if (*pprev) {
                vma = *pprev;
                goto success;
        }
     ...
fail:
        vm_unacct_memory(charged);
        return error;
}

So, the call to vma_page() leads to vma_adjust() that could free the passed VMA in order to merge previous and possibly next VMAs. However, the following call of perf_event_mmap() will attempt to access the freed VMA pointer as we can find at kernel/perf_event.c file.(vma_adjust()会free VMA,但是perf_event_mmap()会试图去访问freed VMA pointer)

void perf_event_mmap(struct vm_area_struct *vma)
{
        struct perf_mmap_event mmap_event;
 
        if (!atomic_read(&nr_mmap_events))
                return;
 
        mmap_event = (struct perf_mmap_event){
                .vma    = vma,
                /* .file_name */
                /* .file_size */
                .event_id  = {
                        .header = {
                                .type = PERF_RECORD_MMAP,
                                .misc = PERF_RECORD_MISC_USER,
                                /* .size */
                        },
                        /* .pid */
                        /* .tid */
                        .start  = vma->vm_start,
                        .len    = vma->vm_end - vma->vm_start,
                        .pgoff  = (u64)vma->vm_pgoff << PAGE_SHIFT,
                },
        };
 
        perf_event_mmap_event(&mmap_event);
}

所以会发生use-after-free。

patch

To fix this, the perf_event_mmap() call was removed from mprotect(2) and placed in the ‘success’ code of mprotect_fixup().
将访问VMA的函数从SYSCALL_DEFINE3中移除,放在mprotect_fixup()的“success”里面。
所以是avoid use,使得use不再发生。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值