From e5664e23f5459c09bfb12bb40506d8e2baf54306 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 17 Jun 2019 19:29:35 +0100 Subject: [PATCH] mm/mincore.c: make mincore() more conservative (CVE-2019-5489) --- debian/changelog | 1 + ...ore.c-make-mincore-more-conservative.patch | 95 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 97 insertions(+) create mode 100644 debian/patches/bugfix/all/mm-mincore.c-make-mincore-more-conservative.patch diff --git a/debian/changelog b/debian/changelog index 3153cbb3c..5c2d06a14 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,6 +12,7 @@ linux (4.19.37-4) UNRELEASED; urgency=medium (CVE-2019-3846) * mwifiex: Abort at too short BSS descriptor element * mwifiex: Don't abort on small, spec-compliant vendor IEs + * mm/mincore.c: make mincore() more conservative (CVE-2019-5489) [ Romain Perier ] * [rt] Update to 4.19.37-rt20 diff --git a/debian/patches/bugfix/all/mm-mincore.c-make-mincore-more-conservative.patch b/debian/patches/bugfix/all/mm-mincore.c-make-mincore-more-conservative.patch new file mode 100644 index 000000000..d502d26f6 --- /dev/null +++ b/debian/patches/bugfix/all/mm-mincore.c-make-mincore-more-conservative.patch @@ -0,0 +1,95 @@ +From: Jiri Kosina +Date: Tue, 14 May 2019 15:41:38 -0700 +Subject: mm/mincore.c: make mincore() more conservative +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit?id=f580a54bbd522f2518fd642f7d4d73ad728e5d58 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-5489 + +commit 134fca9063ad4851de767d1768180e5dede9a881 upstream. + +The semantics of what mincore() considers to be resident is not +completely clear, but Linux has always (since 2.3.52, which is when +mincore() was initially done) treated it as "page is available in page +cache". + +That's potentially a problem, as that [in]directly exposes +meta-information about pagecache / memory mapping state even about +memory not strictly belonging to the process executing the syscall, +opening possibilities for sidechannel attacks. + +Change the semantics of mincore() so that it only reveals pagecache +information for non-anonymous mappings that belog to files that the +calling process could (if it tried to) successfully open for writing; +otherwise we'd be including shared non-exclusive mappings, which + + - is the sidechannel + + - is not the usecase for mincore(), as that's primarily used for data, + not (shared) text + +[jkosina@suse.cz: v2] + Link: http://lkml.kernel.org/r/20190312141708.6652-2-vbabka@suse.cz +[mhocko@suse.com: restructure can_do_mincore() conditions] +Link: http://lkml.kernel.org/r/nycvar.YFH.7.76.1903062342020.19912@cbobk.fhfr.pm +Signed-off-by: Jiri Kosina +Signed-off-by: Vlastimil Babka +Acked-by: Josh Snyder +Acked-by: Michal Hocko +Originally-by: Linus Torvalds +Originally-by: Dominique Martinet +Cc: Andy Lutomirski +Cc: Dave Chinner +Cc: Kevin Easton +Cc: Matthew Wilcox +Cc: Cyril Hrubis +Cc: Tejun Heo +Cc: Kirill A. Shutemov +Cc: Daniel Gruss +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + mm/mincore.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/mm/mincore.c b/mm/mincore.c +index fc37afe226e6..2732c8c0764c 100644 +--- a/mm/mincore.c ++++ b/mm/mincore.c +@@ -169,6 +169,22 @@ static int mincore_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + return 0; + } + ++static inline bool can_do_mincore(struct vm_area_struct *vma) ++{ ++ if (vma_is_anonymous(vma)) ++ return true; ++ if (!vma->vm_file) ++ return false; ++ /* ++ * Reveal pagecache information only for non-anonymous mappings that ++ * correspond to the files the calling process could (if tried) open ++ * for writing; otherwise we'd be including shared non-exclusive ++ * mappings, which opens a side channel. ++ */ ++ return inode_owner_or_capable(file_inode(vma->vm_file)) || ++ inode_permission(file_inode(vma->vm_file), MAY_WRITE) == 0; ++} ++ + /* + * Do a chunk of "sys_mincore()". We've already checked + * all the arguments, we hold the mmap semaphore: we should +@@ -189,8 +205,13 @@ static long do_mincore(unsigned long addr, unsigned long pages, unsigned char *v + vma = find_vma(current->mm, addr); + if (!vma || addr < vma->vm_start) + return -ENOMEM; +- mincore_walk.mm = vma->vm_mm; + end = min(vma->vm_end, addr + (pages << PAGE_SHIFT)); ++ if (!can_do_mincore(vma)) { ++ unsigned long pages = DIV_ROUND_UP(end - addr, PAGE_SIZE); ++ memset(vec, 1, pages); ++ return pages; ++ } ++ mincore_walk.mm = vma->vm_mm; + err = walk_page_range(addr, end, &mincore_walk); + if (err < 0) + return err; diff --git a/debian/patches/series b/debian/patches/series index 19011f4fc..df2100c53 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -220,6 +220,7 @@ bugfix/all/Bluetooth-hidp-fix-buffer-overflow.patch bugfix/all/mwifiex-fix-possible-buffer-overflows-at-parsing-bss.patch bugfix/all/mwifiex-abort-at-too-short-bss-descriptor-element.patch bugfix/all/mwifiex-don-t-abort-on-small-spec-compliant-vendor-ies.patch +bugfix/all/mm-mincore.c-make-mincore-more-conservative.patch # Fix exported symbol versions bugfix/all/module-disable-matching-missing-version-crc.patch