Dirty COW(CVE-2015-5195):应用修复程序重新编译Linux Kernel 4.2

时间:2020-03-21 11:42:20  来源:igfitidea点击:

Dirty COW(CVE-2015-5195)是Linux内核中的特权升级漏洞。

问题

我的笔记本电脑运行带有自定义4.2内核的Debian Jessie,而Debian并未维护该内核。

内核容易受到公开可用的攻击:

$./dirtyc0w foo m00000000000000000
mmap 7f83599c6000
madvise 0
procselfmem 1800000000
$cat foo 
m00000000000000000

怎么修复?

我们可以使用已应用的修复程序重新编译内核。

将修补程序应用于内核源

该修复程序在这里可用:

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619

导航到内核源目录'/usr/src/linux-4.2.6/'。

将以下修复程序(必须在绿色的行中添加)应用于文件“ include/linux/mm.h”:

#define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */
#define FOLL_COW 0x4000 /* internal GUP flag */

检查确认:

$grep -n FOLL_COW include/linux/mm.h
2095:#define FOLL_COW 0x4000 /* internal GUP flag */

将以下修复程序应用于文件'mm/gup.c'。
需要添加所有绿色的行,必须删除所有红色的行或者将其注释掉。

}
//around line #35 in mm/gup.c
static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
{

return pte_write(pte) ||

((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
}
static struct page *follow_page_pte(struct vm_area_struct *vma,

unsigned long address, pmd_t *pmd, unsigned int flags)
//around line #75 in mm/gup.c
}
if ((flags & FOLL_NUMA) && pte_protnone(pte))
	goto no_page;
//if ((flags & FOLL_WRITE) && !pte_write(pte)) {
if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) {
	pte_unmap_unlock(ptep, ptl);
	return NULL;
}
//around line #324 in mm/gup.c
if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE))
//	*flags &= ~FOLL_WRITE;

*flags |= FOLL_COW;
return 0;

检查确认:

$grep -n can_follow_write_pte mm/gup.c
35:static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
75: if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) {
$grep -n "= FOLL_COW" mm/gup.c
324: *flags |= FOLL_COW;

重新编译内核

不用说,在安装新内核之前,请确保已备份了正在运行的内核。

# make -j3
# make modules_install install

重启。

$uname -rv
4.2.6-dev #4 SMP Sat Oct 29 10:52:26 BST 2015

内核不再是易受攻击的:

$./dirtyc0w foo m00000000000000000
mmap 7f23f122f000
madvise 0
procselfmem 1800000000
$cat foo 
this is not a test