eCryptfs: fix permission denied with ecryptfs_xattr mount option when create readonly...
authorRobbie Ko <robbieko@synology.com>
Tue, 21 Aug 2018 08:17:40 +0000 (16:17 +0800)
committerTyler Hicks <tyhicks@canonical.com>
Sat, 16 Feb 2019 23:18:57 +0000 (23:18 +0000)
When the ecryptfs_xattr mount option is turned on, the ecryptfs
metadata will be written to xattr via vfs_setxattr, which will
check the WRITE permissions.

However, this will cause denial of permission when creating a
file withoug write permission.

So fix this by calling __vfs_setxattr directly to skip permission
check.

Signed-off-by: Robbie Ko <robbieko@synology.com>
[tyhicks: Copy up lower inode attributes when successful]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
fs/ecryptfs/crypto.c

index 708f931c36f14adace91af82229a6043386c9baf..bc2376726090b403ed3fa8d043efa07c6b45c23a 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 #include <linux/kernel.h>
+#include <linux/xattr.h>
 #include "ecryptfs_kernel.h"
 
 #define DECRYPT                0
@@ -1131,9 +1132,21 @@ ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
                                 char *page_virt, size_t size)
 {
        int rc;
+       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+       struct inode *lower_inode = d_inode(lower_dentry);
 
-       rc = ecryptfs_setxattr(ecryptfs_dentry, ecryptfs_inode,
-                              ECRYPTFS_XATTR_NAME, page_virt, size, 0);
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
+       inode_lock(lower_inode);
+       rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
+                           page_virt, size, 0);
+       if (!rc && ecryptfs_inode)
+               fsstack_copy_attr_all(ecryptfs_inode, lower_inode);
+       inode_unlock(lower_inode);
+out:
        return rc;
 }