erofs-utils: lib: set OVL_XATTR_ORIGIN for directories with whiteouts
authorJingbo Xu <jefflexu@linux.alibaba.com>
Sat, 9 Sep 2023 16:32:31 +0000 (00:32 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Mon, 11 Sep 2023 03:22:05 +0000 (11:22 +0800)
Whiteouts are exposed in the overlayfs mount if these are from some
non-merged directory without OVL_XATTR_ORIGIN set on the directory.

To fix this, tag OVL_XATTR_ORIGIN (with empty value) on the parent
directory of whiteouts.

Fixes: 95d315fd7958 ("erofs-utils: introduce tarerofs")
Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20230909163240.42057-5-hsiangkao@linux.alibaba.com
include/erofs/internal.h
include/erofs/xattr.h
lib/inode.c
lib/tar.c
lib/xattr.c

index ac82336a3257ba45f4435c8d493e1d7c639c84d9..ba4d6c6efdc3a17eaefde05f6a2efc9b6682cbcb 100644 (file)
@@ -192,6 +192,8 @@ struct erofs_inode {
        bool compressed_idata;
        bool lazy_tailblock;
        bool with_tmpfile;
+       /* OVL: non-merge dir that may contain whiteout entries */
+       bool whiteouts;
 
        unsigned int xattr_isize;
        unsigned int extent_isize;
index 59515d7605b5023dbd66a5d558102c664720a9d7..2ecb18ef4135ef439644eafb8c06f96bd5a4708e 100644 (file)
@@ -57,6 +57,7 @@ int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi);
 int erofs_setxattr(struct erofs_inode *inode, char *key,
                   const void *value, size_t size);
 int erofs_set_opaque_xattr(struct erofs_inode *inode);
+int erofs_set_origin_xattr(struct erofs_inode *inode);
 
 #ifdef __cplusplus
 }
index a3a643fad8f057f036dee058b35493229db34bcc..c976be3b9b4c9a140bd14d890bfe65442e96211f 100644 (file)
@@ -1337,6 +1337,9 @@ int tarerofs_dump_tree(struct erofs_inode *dir)
                dir->inode_isize = sizeof(struct erofs_inode_compact);
        }
 
+       if (dir->whiteouts)
+               erofs_set_origin_xattr(dir);
+
        ret = erofs_prepare_xattr_ibody(dir);
        if (ret < 0)
                return ret;
index c5dbef0dd1c38b67ddd789aba6170302802fb0f2..b58bfd5e55fa9a21295de0d0acc38c9124e97b24 100644 (file)
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -843,6 +843,13 @@ new_inode:
                inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFCHR;
                inode->u.i_rdev = EROFS_WHITEOUT_DEV;
                d->type = EROFS_FT_CHRDEV;
+
+               /*
+                * Mark the parent directory as copied-up to avoid exposing
+                * whiteouts if mounted.  See kernel commit b79e05aaa166
+                * ("ovl: no direct iteration for dir with origin xattr")
+                */
+               inode->i_parent->whiteouts = true;
        } else {
                inode->i_mode = st.st_mode;
                if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
index bd0383162c927a6268b376dc161567b4916f7398..671ae05164c37169733f1d0e8d548d48934546f1 100644 (file)
 #ifndef OVL_XATTR_OPAQUE_POSTFIX
 #define OVL_XATTR_OPAQUE_POSTFIX "opaque"
 #endif
+#ifndef OVL_XATTR_ORIGIN_POSTFIX
+#define OVL_XATTR_ORIGIN_POSTFIX "origin"
+#endif
 #ifndef OVL_XATTR_TRUSTED_PREFIX
 #define OVL_XATTR_TRUSTED_PREFIX XATTR_TRUSTED_PREFIX OVL_XATTR_NAMESPACE
 #endif
 #ifndef OVL_XATTR_OPAQUE
 #define OVL_XATTR_OPAQUE OVL_XATTR_TRUSTED_PREFIX OVL_XATTR_OPAQUE_POSTFIX
 #endif
+#ifndef OVL_XATTR_ORIGIN
+#define OVL_XATTR_ORIGIN OVL_XATTR_TRUSTED_PREFIX OVL_XATTR_ORIGIN_POSTFIX
+#endif
 
 #define EA_HASHTABLE_BITS 16
 
@@ -490,6 +496,11 @@ int erofs_set_opaque_xattr(struct erofs_inode *inode)
        return erofs_setxattr(inode, OVL_XATTR_OPAQUE, "y", 1);
 }
 
+int erofs_set_origin_xattr(struct erofs_inode *inode)
+{
+       return erofs_setxattr(inode, OVL_XATTR_ORIGIN, NULL, 0);
+}
+
 #ifdef WITH_ANDROID
 static int erofs_droid_xattr_set_caps(struct erofs_inode *inode)
 {