diff --git a/mm/filemap.c b/mm/filemap.c index 6a3d62de1cca..056422e6a0be 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -4270,6 +4270,20 @@ resched: rcu_read_unlock(); } +/* + * See mincore: reveal pagecache information only for files + * that the calling process has write access to, or could (if + * tried) open for writing. + */ +static inline bool can_do_cachestat(struct file *f) +{ + if (f->f_mode & FMODE_WRITE) + return true; + if (inode_owner_or_capable(file_mnt_idmap(f), file_inode(f))) + return true; + return file_permission(f, MAY_WRITE) == 0; +} + /* * The cachestat(2) system call. * @@ -4329,6 +4343,11 @@ SYSCALL_DEFINE4(cachestat, unsigned int, fd, return -EOPNOTSUPP; } + if (!can_do_cachestat(f.file)) { + fdput(f); + return -EPERM; + } + if (flags != 0) { fdput(f); return -EINVAL;