From: Miklos Szeredi mszeredi@redhat.com
mainline inclusion from mainline-v5.8-rc1 commit 05acefb4872dae89e772729efb194af754c877e8 category: bugfix bugzilla: NA CVE: CVE-2020-16120
--------------------------------
Call inode_permission() on real inode before opening regular file on one of the underlying layers.
In some cases ovl_permission() already checks access to an underlying file, but it misses the metacopy case, and possibly other ones as well.
Removing the redundant permission check from ovl_permission() should be considered later.
Signed-off-by: Miklos Szeredi mszeredi@redhat.com Conflicts: fs/overlayfs/file.c [yyl: adjust context] Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/overlayfs/file.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index b4ab06c3f3c67..f8e733c29cc47 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -35,10 +35,22 @@ static struct file *ovl_open_realfile(const struct file *file, struct file *realfile; const struct cred *old_cred; int flags = file->f_flags | OVL_OPEN_FLAGS; + int acc_mode = ACC_MODE(flags); + int err; + + if (flags & O_APPEND) + acc_mode |= MAY_APPEND;
old_cred = ovl_override_creds(inode->i_sb); - realfile = open_with_fake_path(&file->f_path, flags, realinode, - current_cred()); + err = inode_permission(realinode, MAY_OPEN | acc_mode); + if (err) { + realfile = ERR_PTR(err); + } else if (!inode_owner_or_capable(realinode)) { + realfile = ERR_PTR(-EPERM); + } else { + realfile = open_with_fake_path(&file->f_path, flags, realinode, + current_cred()); + } revert_creds(old_cred);
pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",