diff options
| author | Miklos Szeredi <mszeredi@redhat.com> | 2016-06-06 10:21:37 -0400 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-06-06 10:21:37 -0400 |
| commit | b581755b1c565391c72d03b157ba2dd0b18e9d15 (patch) | |
| tree | 9db3109b50d47faad07d457feb671eb0e90fcbe1 | |
| parent | af8c34ce6ae32addda3788d54a7e340cad22516b (diff) | |
ovl: xattr filter fix
a) ovl_need_xattr_filter() is wrong, we can have multiple lower layers
overlaid, all of which (except the lowest one) honouring the
"trusted.overlay.opaque" xattr. So need to filter everything except the
bottom and the pure-upper layer.
b) we no longer can assume that inode is attached to dentry in
get/setxattr.
This patch unconditionally filters private xattrs to fix both of the above.
Performance impact for get/removexattrs is likely in the noise.
For listxattrs it might be measurable in pathological cases, but I very
much hope nobody cares. If they do, we'll fix it then.
Reported-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Fixes: b96809173e94 ("security_d_instantiate(): move to the point prior to attaching dentry to inode")
| -rw-r--r-- | fs/overlayfs/inode.c | 26 |
1 files changed, 6 insertions, 20 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 0ed7c4012437..1dbeab6cf96e 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
| @@ -238,41 +238,27 @@ out: | |||
| 238 | return err; | 238 | return err; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | static bool ovl_need_xattr_filter(struct dentry *dentry, | ||
| 242 | enum ovl_path_type type) | ||
| 243 | { | ||
| 244 | if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER) | ||
| 245 | return S_ISDIR(dentry->d_inode->i_mode); | ||
| 246 | else | ||
| 247 | return false; | ||
| 248 | } | ||
| 249 | |||
| 250 | ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, | 241 | ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, |
| 251 | const char *name, void *value, size_t size) | 242 | const char *name, void *value, size_t size) |
| 252 | { | 243 | { |
| 253 | struct path realpath; | 244 | struct dentry *realdentry = ovl_dentry_real(dentry); |
| 254 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); | ||
| 255 | 245 | ||
| 256 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | 246 | if (ovl_is_private_xattr(name)) |
| 257 | return -ENODATA; | 247 | return -ENODATA; |
| 258 | 248 | ||
| 259 | return vfs_getxattr(realpath.dentry, name, value, size); | 249 | return vfs_getxattr(realdentry, name, value, size); |
| 260 | } | 250 | } |
| 261 | 251 | ||
| 262 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) | 252 | ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) |
| 263 | { | 253 | { |
| 264 | struct path realpath; | 254 | struct dentry *realdentry = ovl_dentry_real(dentry); |
| 265 | enum ovl_path_type type = ovl_path_real(dentry, &realpath); | ||
| 266 | ssize_t res; | 255 | ssize_t res; |
| 267 | int off; | 256 | int off; |
| 268 | 257 | ||
| 269 | res = vfs_listxattr(realpath.dentry, list, size); | 258 | res = vfs_listxattr(realdentry, list, size); |
| 270 | if (res <= 0 || size == 0) | 259 | if (res <= 0 || size == 0) |
| 271 | return res; | 260 | return res; |
| 272 | 261 | ||
| 273 | if (!ovl_need_xattr_filter(dentry, type)) | ||
| 274 | return res; | ||
| 275 | |||
| 276 | /* filter out private xattrs */ | 262 | /* filter out private xattrs */ |
| 277 | for (off = 0; off < res;) { | 263 | for (off = 0; off < res;) { |
| 278 | char *s = list + off; | 264 | char *s = list + off; |
| @@ -302,7 +288,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name) | |||
| 302 | goto out; | 288 | goto out; |
| 303 | 289 | ||
| 304 | err = -ENODATA; | 290 | err = -ENODATA; |
| 305 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | 291 | if (ovl_is_private_xattr(name)) |
| 306 | goto out_drop_write; | 292 | goto out_drop_write; |
| 307 | 293 | ||
| 308 | if (!OVL_TYPE_UPPER(type)) { | 294 | if (!OVL_TYPE_UPPER(type)) { |
