aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-12-12 18:19:44 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2018-12-12 18:19:44 -0800
commite6333d72cb373239400969f5d10204c094a9712a (patch)
treeffa840eab4f81b319e606eeba3f47bbd7de56b54
parent70f4828201e3bc9a5ac52d1f7ede06e56194268a (diff)
parentec7ba118b9407c9b4d998b8065167afae5ed04be (diff)
downloadlinux-e6333d72cb373239400969f5d10204c094a9712a.tar.gz
Merge tag 'ovl-fixes-4.20-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs fixes from Miklos Szeredi: "Needed to revert a patch, because it possibly introduces a security hole. Since the patch is basically a conceptual cleanup, not a bug fix, it's safe to revert. I'm not giving up on this, and discussions seemed to have reached an agreement over how to move forward, but that can wait 'till the next release. The other two patches are fixes for bugs introduced in recent releases" * tag 'ovl-fixes-4.20-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: Revert "ovl: relax permission checking on underlying layers" ovl: fix decode of dir file handle with multi lower layers ovl: fix missing override creds in link of a metacopy upper
-rw-r--r--fs/overlayfs/dir.c14
-rw-r--r--fs/overlayfs/export.c6
-rw-r--r--fs/overlayfs/inode.c17
3 files changed, 20 insertions, 17 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index c6289147c7871f..82c129bfe58d9e 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -651,6 +651,18 @@ static int ovl_symlink(struct inode *dir, struct dentry *dentry,
return ovl_create_object(dentry, S_IFLNK, 0, link);
}
+static int ovl_set_link_redirect(struct dentry *dentry)
+{
+ const struct cred *old_cred;
+ int err;
+
+ old_cred = ovl_override_creds(dentry->d_sb);
+ err = ovl_set_redirect(dentry, false);
+ revert_creds(old_cred);
+
+ return err;
+}
+
static int ovl_link(struct dentry *old, struct inode *newdir,
struct dentry *new)
{
@@ -670,7 +682,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
goto out_drop_write;
if (ovl_is_metacopy_dentry(old)) {
- err = ovl_set_redirect(old, false);
+ err = ovl_set_link_redirect(old);
if (err)
goto out_drop_write;
}
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
index 8fa37cd7818adf..54e5d17d7f3e5c 100644
--- a/fs/overlayfs/export.c
+++ b/fs/overlayfs/export.c
@@ -754,9 +754,8 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
goto out;
}
- /* Otherwise, get a connected non-upper dir or disconnected non-dir */
- if (d_is_dir(origin.dentry) &&
- (origin.dentry->d_flags & DCACHE_DISCONNECTED)) {
+ /* Find origin.dentry again with ovl_acceptable() layer check */
+ if (d_is_dir(origin.dentry)) {
dput(origin.dentry);
origin.dentry = NULL;
err = ovl_check_origin_fh(ofs, fh, true, NULL, &stack);
@@ -769,6 +768,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
goto out_err;
}
+ /* Get a connected non-upper dir or disconnected non-dir */
dentry = ovl_get_dentry(sb, NULL, &origin, index);
out:
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 6bcc9dedc342cc..3b7ed5d2279c6a 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -286,22 +286,13 @@ int ovl_permission(struct inode *inode, int mask)
if (err)
return err;
- /* No need to do any access on underlying for special files */
- if (special_file(realinode->i_mode))
- return 0;
-
- /* No need to access underlying for execute */
- mask &= ~MAY_EXEC;
- if ((mask & (MAY_READ | MAY_WRITE)) == 0)
- return 0;
-
- /* Lower files get copied up, so turn write access into read */
- if (!upperinode && mask & MAY_WRITE) {
+ old_cred = ovl_override_creds(inode->i_sb);
+ if (!upperinode &&
+ !special_file(realinode->i_mode) && mask & MAY_WRITE) {
mask &= ~(MAY_WRITE | MAY_APPEND);
+ /* Make sure mounter can read file for copy up later */
mask |= MAY_READ;
}
-
- old_cred = ovl_override_creds(inode->i_sb);
err = inode_permission(realinode, mask);
revert_creds(old_cred);