diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2016-07-29 06:05:23 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-07-29 06:05:23 -0400 |
commit | 9c630ebefeeee4363ffd29f2f9b18eddafc6479c (patch) | |
tree | 377086556cf88b99ffba8b935c6a72d1f365ba9c /fs/overlayfs | |
parent | 754f8cb72b42a3a6100d2bbb1cb885361a7310dd (diff) |
ovl: simplify permission checking
The fact that we always do permission checking on the overlay inode and
clear MAY_WRITE for checking access to the lower inode allows cruft to be
removed from ovl_permission().
1) "default_permissions" option effectively did generic_permission() on the
overlay inode with i_mode, i_uid and i_gid updated from underlying
filesystem. This is what we do by default now. It did the update using
vfs_getattr() but that's only needed if the underlying filesystem can
change (which is not allowed). We may later introduce a "paranoia_mode"
that verifies that mode/uid/gid are not changed.
2) splitting out the IS_RDONLY() check from inode_permission() also becomes
unnecessary once we remove the MAY_WRITE from the lower inode check.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r-- | fs/overlayfs/inode.c | 46 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 1 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 7 |
3 files changed, 1 insertions, 53 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 8f7dd547cfb3..66f42f5cf705 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -124,29 +124,6 @@ int ovl_permission(struct inode *inode, int mask) | |||
124 | const struct cred *old_cred; | 124 | const struct cred *old_cred; |
125 | int err; | 125 | int err; |
126 | 126 | ||
127 | if (ovl_is_default_permissions(inode)) { | ||
128 | struct kstat stat; | ||
129 | struct path realpath = { .dentry = realdentry }; | ||
130 | |||
131 | if (mask & MAY_NOT_BLOCK) | ||
132 | return -ECHILD; | ||
133 | |||
134 | realpath.mnt = ovl_entry_mnt_real(oe, inode, is_upper); | ||
135 | |||
136 | err = vfs_getattr(&realpath, &stat); | ||
137 | if (err) | ||
138 | return err; | ||
139 | |||
140 | if ((stat.mode ^ inode->i_mode) & S_IFMT) | ||
141 | return -ESTALE; | ||
142 | |||
143 | inode->i_mode = stat.mode; | ||
144 | inode->i_uid = stat.uid; | ||
145 | inode->i_gid = stat.gid; | ||
146 | |||
147 | return generic_permission(inode, mask); | ||
148 | } | ||
149 | |||
150 | /* Careful in RCU walk mode */ | 127 | /* Careful in RCU walk mode */ |
151 | realinode = d_inode_rcu(realdentry); | 128 | realinode = d_inode_rcu(realdentry); |
152 | if (!realinode) { | 129 | if (!realinode) { |
@@ -154,27 +131,6 @@ int ovl_permission(struct inode *inode, int mask) | |||
154 | return -ENOENT; | 131 | return -ENOENT; |
155 | } | 132 | } |
156 | 133 | ||
157 | if (mask & MAY_WRITE) { | ||
158 | umode_t mode = realinode->i_mode; | ||
159 | |||
160 | /* | ||
161 | * Writes will always be redirected to upper layer, so | ||
162 | * ignore lower layer being read-only. | ||
163 | * | ||
164 | * If the overlay itself is read-only then proceed | ||
165 | * with the permission check, don't return EROFS. | ||
166 | * This will only happen if this is the lower layer of | ||
167 | * another overlayfs. | ||
168 | * | ||
169 | * If upper fs becomes read-only after the overlay was | ||
170 | * constructed return EROFS to prevent modification of | ||
171 | * upper layer. | ||
172 | */ | ||
173 | if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) && | ||
174 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | ||
175 | return -EROFS; | ||
176 | } | ||
177 | |||
178 | /* | 134 | /* |
179 | * Check overlay inode with the creds of task and underlying inode | 135 | * Check overlay inode with the creds of task and underlying inode |
180 | * with creds of mounter | 136 | * with creds of mounter |
@@ -186,7 +142,7 @@ int ovl_permission(struct inode *inode, int mask) | |||
186 | old_cred = ovl_override_creds(inode->i_sb); | 142 | old_cred = ovl_override_creds(inode->i_sb); |
187 | if (!is_upper) | 143 | if (!is_upper) |
188 | mask &= ~(MAY_WRITE | MAY_APPEND); | 144 | mask &= ~(MAY_WRITE | MAY_APPEND); |
189 | err = __inode_permission(realinode, mask); | 145 | err = inode_permission(realinode, mask); |
190 | revert_creds(old_cred); | 146 | revert_creds(old_cred); |
191 | 147 | ||
192 | return err; | 148 | return err; |
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 75128c70aa6a..e8d50da384d5 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
@@ -146,7 +146,6 @@ struct inode *ovl_inode_real(struct inode *inode); | |||
146 | struct vfsmount *ovl_entry_mnt_real(struct ovl_entry *oe, struct inode *inode, | 146 | struct vfsmount *ovl_entry_mnt_real(struct ovl_entry *oe, struct inode *inode, |
147 | bool is_upper); | 147 | bool is_upper); |
148 | struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry); | 148 | struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry); |
149 | bool ovl_is_default_permissions(struct inode *inode); | ||
150 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache); | 149 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache); |
151 | struct dentry *ovl_workdir(struct dentry *dentry); | 150 | struct dentry *ovl_workdir(struct dentry *dentry); |
152 | int ovl_want_write(struct dentry *dentry); | 151 | int ovl_want_write(struct dentry *dentry); |
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 893d6e0ea1c5..80598912a5d9 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -185,13 +185,6 @@ struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry) | |||
185 | return oe->cache; | 185 | return oe->cache; |
186 | } | 186 | } |
187 | 187 | ||
188 | bool ovl_is_default_permissions(struct inode *inode) | ||
189 | { | ||
190 | struct ovl_fs *ofs = inode->i_sb->s_fs_info; | ||
191 | |||
192 | return ofs->config.default_permissions; | ||
193 | } | ||
194 | |||
195 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache) | 188 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache) |
196 | { | 189 | { |
197 | struct ovl_entry *oe = dentry->d_fsdata; | 190 | struct ovl_entry *oe = dentry->d_fsdata; |