diff --git a/debian/changelog b/debian/changelog index b8eb0c391..b5bb74db0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -23,6 +23,10 @@ linux (4.14.2-1~exp1) UNRELEASED; urgency=medium * [rt] Add new signing subkey for Steven Rostedt * [rt] Update to 4.14.1-rt3 + [ Salvatore Bonaccorso ] + * mm, thp: Do not make page table dirty unconditionally in touch_p[mu]d() + (CVE-2017-1000405) + -- Ben Hutchings Mon, 20 Nov 2017 14:16:28 +0000 linux (4.14-1~exp1) experimental; urgency=medium diff --git a/debian/patches/bugfix/all/mm-thp-Do-not-make-page-table-dirty-unconditionally-.patch b/debian/patches/bugfix/all/mm-thp-Do-not-make-page-table-dirty-unconditionally-.patch new file mode 100644 index 000000000..6647fde6a --- /dev/null +++ b/debian/patches/bugfix/all/mm-thp-Do-not-make-page-table-dirty-unconditionally-.patch @@ -0,0 +1,109 @@ +From: "Kirill A. Shutemov" +Date: Mon, 27 Nov 2017 06:21:25 +0300 +Subject: mm, thp: Do not make page table dirty unconditionally in + touch_p[mu]d() +Origin: https://git.kernel.org/linus/a8f97366452ed491d13cf1e44241bc0b5740b1f0 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-1000405 + +Currently, we unconditionally make page table dirty in touch_pmd(). +It may result in false-positive can_follow_write_pmd(). + +We may avoid the situation, if we would only make the page table entry +dirty if caller asks for write access -- FOLL_WRITE. + +The patch also changes touch_pud() in the same way. + +Signed-off-by: Kirill A. Shutemov +Cc: Michal Hocko +Cc: Hugh Dickins +Signed-off-by: Linus Torvalds +--- + mm/huge_memory.c | 36 +++++++++++++----------------------- + 1 file changed, 13 insertions(+), 23 deletions(-) + +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 86fe697e8bfb..0e7ded98d114 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -842,20 +842,15 @@ EXPORT_SYMBOL_GPL(vmf_insert_pfn_pud); + #endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ + + static void touch_pmd(struct vm_area_struct *vma, unsigned long addr, +- pmd_t *pmd) ++ pmd_t *pmd, int flags) + { + pmd_t _pmd; + +- /* +- * We should set the dirty bit only for FOLL_WRITE but for now +- * the dirty bit in the pmd is meaningless. And if the dirty +- * bit will become meaningful and we'll only set it with +- * FOLL_WRITE, an atomic set_bit will be required on the pmd to +- * set the young bit, instead of the current set_pmd_at. +- */ +- _pmd = pmd_mkyoung(pmd_mkdirty(*pmd)); ++ _pmd = pmd_mkyoung(*pmd); ++ if (flags & FOLL_WRITE) ++ _pmd = pmd_mkdirty(_pmd); + if (pmdp_set_access_flags(vma, addr & HPAGE_PMD_MASK, +- pmd, _pmd, 1)) ++ pmd, _pmd, flags & FOLL_WRITE)) + update_mmu_cache_pmd(vma, addr, pmd); + } + +@@ -884,7 +879,7 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr, + return NULL; + + if (flags & FOLL_TOUCH) +- touch_pmd(vma, addr, pmd); ++ touch_pmd(vma, addr, pmd, flags); + + /* + * device mapped pages can only be returned if the +@@ -995,20 +990,15 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, + + #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD + static void touch_pud(struct vm_area_struct *vma, unsigned long addr, +- pud_t *pud) ++ pud_t *pud, int flags) + { + pud_t _pud; + +- /* +- * We should set the dirty bit only for FOLL_WRITE but for now +- * the dirty bit in the pud is meaningless. And if the dirty +- * bit will become meaningful and we'll only set it with +- * FOLL_WRITE, an atomic set_bit will be required on the pud to +- * set the young bit, instead of the current set_pud_at. +- */ +- _pud = pud_mkyoung(pud_mkdirty(*pud)); ++ _pud = pud_mkyoung(*pud); ++ if (flags & FOLL_WRITE) ++ _pud = pud_mkdirty(_pud); + if (pudp_set_access_flags(vma, addr & HPAGE_PUD_MASK, +- pud, _pud, 1)) ++ pud, _pud, flags & FOLL_WRITE)) + update_mmu_cache_pud(vma, addr, pud); + } + +@@ -1031,7 +1021,7 @@ struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr, + return NULL; + + if (flags & FOLL_TOUCH) +- touch_pud(vma, addr, pud); ++ touch_pud(vma, addr, pud, flags); + + /* + * device mapped pages can only be returned if the +@@ -1424,7 +1414,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, + page = pmd_page(*pmd); + VM_BUG_ON_PAGE(!PageHead(page) && !is_zone_device_page(page), page); + if (flags & FOLL_TOUCH) +- touch_pmd(vma, addr, pmd); ++ touch_pmd(vma, addr, pmd, flags); + if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { + /* + * We don't mlock() pte-mapped THPs. This way we can avoid +-- +2.15.0 + diff --git a/debian/patches/series b/debian/patches/series index aa96b58b5..2e5269208 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -117,6 +117,7 @@ debian/i386-686-pae-pci-set-pci-nobios-by-default.patch bugfix/all/media-cx231xx-cards-fix-null-deref-on-missing-associ.patch bugfix/all/media-dvb-core-always-call-invoke_release-in-fe_free.patch bugfix/all/dvb_frontend-don-t-use-after-free-the-frontend-struc.patch +bugfix/all/mm-thp-Do-not-make-page-table-dirty-unconditionally-.patch # Fix exported symbol versions bugfix/all/module-disable-matching-missing-version-crc.patch