[PATCH v7 04/13] erofs-utils: lib: set OVL_XATTR_ORIGIN for directories with whiteouts

Gao Xiang hsiangkao at linux.alibaba.com
Sun Sep 10 02:32:31 AEST 2023


From: Jingbo Xu <jefflexu at linux.alibaba.com>

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 at linux.alibaba.com>
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 include/erofs/internal.h |  2 ++
 include/erofs/xattr.h    |  1 +
 lib/inode.c              |  3 +++
 lib/tar.c                |  7 +++++++
 lib/xattr.c              | 11 +++++++++++
 5 files changed, 24 insertions(+)

diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index ac82336..ba4d6c6 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -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;
diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h
index 59515d7..2ecb18e 100644
--- a/include/erofs/xattr.h
+++ b/include/erofs/xattr.h
@@ -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
 }
diff --git a/lib/inode.c b/lib/inode.c
index a3a643f..c976be3 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -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;
diff --git a/lib/tar.c b/lib/tar.c
index c5dbef0..b58bfd5 100644
--- 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))
diff --git a/lib/xattr.c b/lib/xattr.c
index bd03831..671ae05 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -57,12 +57,18 @@
 #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)
 {
-- 
2.24.4



More information about the Linux-erofs mailing list