|
@@ -169,6 +169,22 @@ out:
|
|
|
return 0;
|
|
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
|
|
* Do a chunk of "sys_mincore()". We've already checked
|
|
|
* all the arguments, we hold the mmap semaphore: we should
|
|
* 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);
|
|
vma = find_vma(current->mm, addr);
|
|
|
if (!vma || addr < vma->vm_start)
|
|
if (!vma || addr < vma->vm_start)
|
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
- mincore_walk.mm = vma->vm_mm;
|
|
|
|
|
end = min(vma->vm_end, addr + (pages << PAGE_SHIFT));
|
|
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);
|
|
err = walk_page_range(addr, end, &mincore_walk);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|