summaryrefslogtreecommitdiff
path: root/mm/mincore.c
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2019-06-30 03:26:38 -0700
committerLinux Build Service Account <lnxbuild@localhost>2019-06-30 03:26:38 -0700
commitf6f18bf58a688e45e149708a00659bd1010ef94c (patch)
treeaea1549c4c8f28ad359a92b7702481b2cb369d20 /mm/mincore.c
parentc9d92a953ba0dffba643376ec463754a88db107a (diff)
parent17c66e9e49a181498ae3c75809c98fdbe630de28 (diff)
Merge 17c66e9e49a181498ae3c75809c98fdbe630de28 on remote branch
Change-Id: I49238aefe09bba152a8000c046959157c328f183
Diffstat (limited to 'mm/mincore.c')
-rw-r--r--mm/mincore.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/mm/mincore.c b/mm/mincore.c
index 14bb9fb37f0c..9700c2303941 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -165,6 +165,22 @@ out:
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
@@ -185,8 +201,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;