Change the getxattr inode operation to only use its inode argument, and ignore the dentry. This is possible because on overlayfs, each dentry has a separate inode and inodes are not shared among dentries. Allows SELinux to work on top of overlayfs. Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx> --- fs/overlayfs/inode.c | 26 +++++++++++++++----------- fs/overlayfs/overlayfs.h | 1 + fs/overlayfs/super.c | 10 +++++++--- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 8c3f985..7acc145 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -238,29 +238,32 @@ out: return err; } -static bool ovl_need_xattr_filter(struct dentry *dentry, +static bool ovl_need_xattr_filter(struct inode *inode, enum ovl_path_type type) { if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER) - return S_ISDIR(dentry->d_inode->i_mode); + return S_ISDIR(inode->i_mode); else return false; } -ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, +ssize_t ovl_getxattr(struct dentry *unused, struct inode *inode, const char *name, void *value, size_t size) { - struct path realpath; + struct ovl_entry *oe = inode->i_private; enum ovl_path_type type; + struct dentry *realdentry; + bool is_upper; - if (!dentry) - return -ECHILD; + realdentry = ovl_entry_real(oe, &is_upper); + if (!realdentry->d_inode) + return -ENOENT; - type = ovl_path_real(dentry, &realpath); - if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) + type = __ovl_path_type(oe, inode->i_mode); + if (ovl_need_xattr_filter(inode, type) && ovl_is_private_xattr(name)) return -ENODATA; - return vfs_getxattr(realpath.dentry, name, value, size); + return vfs_getxattr(realdentry, name, value, size); } ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) @@ -274,7 +277,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) if (res <= 0 || size == 0) return res; - if (!ovl_need_xattr_filter(dentry, type)) + if (!ovl_need_xattr_filter(dentry->d_inode, type)) return res; /* filter out private xattrs */ @@ -306,7 +309,8 @@ int ovl_removexattr(struct dentry *dentry, const char *name) goto out; err = -ENODATA; - if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) + if (ovl_need_xattr_filter(dentry->d_inode, type) && + ovl_is_private_xattr(name)) goto out_drop_write; if (!OVL_TYPE_UPPER(type)) { diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 4bd9b5b..0d1430f 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -131,6 +131,7 @@ static inline int ovl_do_whiteout(struct inode *dir, struct dentry *dentry) return err; } +enum ovl_path_type __ovl_path_type(struct ovl_entry *oe, umode_t mode); enum ovl_path_type ovl_path_type(struct dentry *dentry); u64 ovl_dentry_version_get(struct dentry *dentry); void ovl_dentry_version_inc(struct dentry *dentry); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index ce02f46..d04546e 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -70,9 +70,8 @@ static struct dentry *__ovl_dentry_lower(struct ovl_entry *oe) return oe->numlower ? oe->lowerstack[0].dentry : NULL; } -enum ovl_path_type ovl_path_type(struct dentry *dentry) +enum ovl_path_type __ovl_path_type(struct ovl_entry *oe, umode_t mode) { - struct ovl_entry *oe = dentry->d_fsdata; enum ovl_path_type type = 0; if (oe->__upperdentry) { @@ -82,7 +81,7 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry) * Non-dir dentry can hold lower dentry from previous * location. Its purity depends only on opaque flag. */ - if (oe->numlower && S_ISDIR(dentry->d_inode->i_mode)) + if (oe->numlower && S_ISDIR(mode)) type |= __OVL_PATH_MERGE; else if (!oe->opaque) type |= __OVL_PATH_PURE; @@ -93,6 +92,11 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry) return type; } +enum ovl_path_type ovl_path_type(struct dentry *dentry) +{ + return __ovl_path_type(dentry->d_fsdata, dentry->d_inode->i_mode); +} + static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) { return lockless_dereference(oe->__upperdentry); -- 2.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html