ovl: do not get metacopy for userxattr
[linux-2.6-microblaze.git] / fs / overlayfs / util.c
index 23f4756..6569031 100644 (file)
@@ -50,6 +50,9 @@ const struct cred *ovl_override_creds(struct super_block *sb)
  */
 int ovl_can_decode_fh(struct super_block *sb)
 {
+       if (!capable(CAP_DAC_READ_SEARCH))
+               return 0;
+
        if (!sb->s_export_op || !sb->s_export_op->fh_to_dentry)
                return 0;
 
@@ -582,9 +585,10 @@ bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry,
 #define OVL_XATTR_METACOPY_POSTFIX     "metacopy"
 
 #define OVL_XATTR_TAB_ENTRY(x) \
-       [x] = OVL_XATTR_PREFIX x ## _POSTFIX
+       [x] = { [false] = OVL_XATTR_TRUSTED_PREFIX x ## _POSTFIX, \
+               [true] = OVL_XATTR_USER_PREFIX x ## _POSTFIX }
 
-const char *ovl_xattr_table[] = {
+const char *const ovl_xattr_table[][2] = {
        OVL_XATTR_TAB_ENTRY(OVL_XATTR_OPAQUE),
        OVL_XATTR_TAB_ENTRY(OVL_XATTR_REDIRECT),
        OVL_XATTR_TAB_ENTRY(OVL_XATTR_ORIGIN),
@@ -716,6 +720,7 @@ bool ovl_need_index(struct dentry *dentry)
 /* Caller must hold OVL_I(inode)->lock */
 static void ovl_cleanup_index(struct dentry *dentry)
 {
+       struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
        struct dentry *indexdir = ovl_indexdir(dentry->d_sb);
        struct inode *dir = indexdir->d_inode;
        struct dentry *lowerdentry = ovl_dentry_lower(dentry);
@@ -725,7 +730,7 @@ static void ovl_cleanup_index(struct dentry *dentry)
        struct qstr name = { };
        int err;
 
-       err = ovl_get_index_name(lowerdentry, &name);
+       err = ovl_get_index_name(ofs, lowerdentry, &name);
        if (err)
                goto fail;
 
@@ -879,6 +884,13 @@ int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry)
        if (res < 0) {
                if (res == -ENODATA || res == -EOPNOTSUPP)
                        return 0;
+               /*
+                * getxattr on user.* may fail with EACCES in case there's no
+                * read permission on the inode.  Not much we can do, other than
+                * tell the caller that this is not a metacopy inode.
+                */
+               if (ofs->config.userxattr && res == -EACCES)
+                       return 0;
                goto out;
        }