aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-03 14:57:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-03 14:57:09 -0400
commit236bfd8ed868edfc42a656682487683ade3fede4 (patch)
treee1311ab7ca76f663f837c7adf9aacd27492939bb
parent4f302921c1458d790ae21147f7043f4e6b6a1085 (diff)
parente7c0b5991dd1be7b6f6dc2b54a15a0f47b64b007 (diff)
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs fixes from Miklos Szeredi: "This contains fixes for a dentry leak, a regression in 4.6 noticed by Docker users and missing write access checking in truncate" * 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: warn instead of error if d_type is not supported ovl: get_write_access() in truncate ovl: fix dentry leak for default_permissions
-rw-r--r--fs/overlayfs/inode.c29
-rw-r--r--fs/overlayfs/super.c12
2 files changed, 33 insertions, 8 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 1dbeab6cf96e..c831c2e5f803 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -59,16 +59,37 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
59 if (err) 59 if (err)
60 goto out; 60 goto out;
61 61
62 if (attr->ia_valid & ATTR_SIZE) {
63 struct inode *realinode = d_inode(ovl_dentry_real(dentry));
64
65 err = -ETXTBSY;
66 if (atomic_read(&realinode->i_writecount) < 0)
67 goto out_drop_write;
68 }
69
62 err = ovl_copy_up(dentry); 70 err = ovl_copy_up(dentry);
63 if (!err) { 71 if (!err) {
72 struct inode *winode = NULL;
73
64 upperdentry = ovl_dentry_upper(dentry); 74 upperdentry = ovl_dentry_upper(dentry);
65 75
76 if (attr->ia_valid & ATTR_SIZE) {
77 winode = d_inode(upperdentry);
78 err = get_write_access(winode);
79 if (err)
80 goto out_drop_write;
81 }
82
66 inode_lock(upperdentry->d_inode); 83 inode_lock(upperdentry->d_inode);
67 err = notify_change(upperdentry, attr, NULL); 84 err = notify_change(upperdentry, attr, NULL);
68 if (!err) 85 if (!err)
69 ovl_copyattr(upperdentry->d_inode, dentry->d_inode); 86 ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
70 inode_unlock(upperdentry->d_inode); 87 inode_unlock(upperdentry->d_inode);
88
89 if (winode)
90 put_write_access(winode);
71 } 91 }
92out_drop_write:
72 ovl_drop_write(dentry); 93 ovl_drop_write(dentry);
73out: 94out:
74 return err; 95 return err;
@@ -121,16 +142,18 @@ int ovl_permission(struct inode *inode, int mask)
121 142
122 err = vfs_getattr(&realpath, &stat); 143 err = vfs_getattr(&realpath, &stat);
123 if (err) 144 if (err)
124 return err; 145 goto out_dput;
125 146
147 err = -ESTALE;
126 if ((stat.mode ^ inode->i_mode) & S_IFMT) 148 if ((stat.mode ^ inode->i_mode) & S_IFMT)
127 return -ESTALE; 149 goto out_dput;
128 150
129 inode->i_mode = stat.mode; 151 inode->i_mode = stat.mode;
130 inode->i_uid = stat.uid; 152 inode->i_uid = stat.uid;
131 inode->i_gid = stat.gid; 153 inode->i_gid = stat.gid;
132 154
133 return generic_permission(inode, mask); 155 err = generic_permission(inode, mask);
156 goto out_dput;
134 } 157 }
135 158
136 /* Careful in RCU walk mode */ 159 /* Careful in RCU walk mode */
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index ce02f46029da..9a7693d5f8ff 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1082,11 +1082,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1082 if (err < 0) 1082 if (err < 0)
1083 goto out_put_workdir; 1083 goto out_put_workdir;
1084 1084
1085 if (!err) { 1085 /*
1086 pr_err("overlayfs: upper fs needs to support d_type.\n"); 1086 * We allowed this configuration and don't want to
1087 err = -EINVAL; 1087 * break users over kernel upgrade. So warn instead
1088 goto out_put_workdir; 1088 * of erroring out.
1089 } 1089 */
1090 if (!err)
1091 pr_warn("overlayfs: upper fs needs to support d_type.\n");
1090 } 1092 }
1091 } 1093 }
1092 1094