aboutsummaryrefslogtreecommitdiff
path: root/mm/mincore.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/mincore.c')
-rw-r--r--mm/mincore.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/mm/mincore.c b/mm/mincore.c
index 51d46e5d5..b1add60db 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -209,6 +209,22 @@ static void mincore_page_range(struct vm_area_struct *vma,
} while (pgd++, addr = next, addr != end);
}
+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
@@ -224,6 +240,11 @@ static long do_mincore(unsigned long addr, unsigned long pages, unsigned char *v
return -ENOMEM;
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;
+ }
if (is_vm_hugetlb_page(vma)) {
mincore_hugetlb_page_range(vma, addr, end, vec);