[PATCH v6 10/11] erofs-utils: lib: set origin xattr on parent directory of whiteout
Jingbo Xu
jefflexu at linux.alibaba.com
Tue Sep 5 20:02:26 AEST 2023
Whiteouts will be exposed in the overlayfs mount if the whiteouts are
from non-merged directory without origin xattr set on the directory.
To fix this, set origin xattr (with empty value) on parent directory of
whiteouts, marking the parent directory as copied-up to avoid exposing
whiteouts in the overlayfs mount.
To avoid setting multiple origin xattrs on the same directory when
there are multiple whiteouts under the directory, enhance
erofs_setxattr() so that it could skip duplicate xattrs.
Signed-off-by: Jingbo Xu <jefflexu at linux.alibaba.com>
---
include/erofs/xattr.h | 3 ++-
lib/rebuild.c | 6 ++++++
lib/tar.c | 9 ++++++++-
lib/xattr.c | 27 ++++++++++++++++++++++++---
4 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h
index 9fa1ad1..62d0b8b 100644
--- a/include/erofs/xattr.h
+++ b/include/erofs/xattr.h
@@ -55,8 +55,9 @@ void erofs_xattr_prefixes_cleanup(struct erofs_sb_info *sbi);
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);
+ const void *value, size_t size, bool nodup);
int erofs_set_opaque_xattr(struct erofs_inode *inode);
+int erofs_set_origin_xattr(struct erofs_inode *inode);
int erofs_read_xattrs_from_disk(struct erofs_inode *inode);
#ifdef __cplusplus
diff --git a/lib/rebuild.c b/lib/rebuild.c
index 477d68d..b254dea 100644
--- a/lib/rebuild.c
+++ b/lib/rebuild.c
@@ -200,6 +200,12 @@ static int erofs_rebuild_fill_inode(struct erofs_inode *inode)
switch (inode->i_mode & S_IFMT) {
case S_IFCHR:
+ if (erofs_inode_is_whiteout(inode)) {
+ ret = erofs_set_origin_xattr(inode->i_parent);
+ if (ret)
+ break;
+ }
+ /* fallthrough */
case S_IFBLK:
case S_IFIFO:
case S_IFSOCK:
diff --git a/lib/tar.c b/lib/tar.c
index 8cb392c..b75b723 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -206,7 +206,7 @@ int tarerofs_apply_xattrs(struct erofs_inode *inode, struct list_head *xattrs)
item->kv[item->namelen] = '\0';
erofs_dbg("Recording xattr(%s)=\"%s\" (of %u bytes) to file %s",
item->kv, v, vsz, inode->i_srcpath);
- ret = erofs_setxattr(inode, item->kv, v, vsz);
+ ret = erofs_setxattr(inode, item->kv, v, vsz, false);
if (ret == -ENODATA)
erofs_err("Failed to set xattr(%s)=%s to file %s",
item->kv, v, inode->i_srcpath);
@@ -740,6 +740,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 parent directory as copied-up to avoid exposing
+ * whiteouts in the overlayfs mount.
+ */
+ ret = erofs_set_origin_xattr(inode->i_parent);
+ if (ret)
+ goto out;
} 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 cc6a393..feafe96 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
@@ -455,11 +461,12 @@ err:
}
int erofs_setxattr(struct erofs_inode *inode, char *key,
- const void *value, size_t size)
+ const void *value, size_t size, bool nodup)
{
char *kvbuf;
unsigned int len[2];
struct xattr_item *item;
+ struct inode_xattr_node *node;
u8 prefix;
u16 prefixlen;
@@ -481,12 +488,26 @@ int erofs_setxattr(struct erofs_inode *inode, char *key,
if (IS_ERR(item))
return PTR_ERR(item);
+ if (nodup) {
+ list_for_each_entry(node, &inode->i_xattrs, list) {
+ if (node->item == item) {
+ put_xattritem(item);
+ return 0;
+ }
+ }
+ }
+
return erofs_xattr_add(&inode->i_xattrs, item);
}
int erofs_set_opaque_xattr(struct erofs_inode *inode)
{
- return erofs_setxattr(inode, OVL_XATTR_OPAQUE, "y", 1);
+ return erofs_setxattr(inode, OVL_XATTR_OPAQUE, "y", 1, false);
+}
+
+int erofs_set_origin_xattr(struct erofs_inode *inode)
+{
+ return erofs_setxattr(inode, OVL_XATTR_ORIGIN, NULL, 0, true);
}
#ifdef WITH_ANDROID
@@ -599,7 +620,7 @@ int erofs_read_xattrs_from_disk(struct erofs_inode *inode)
DBG_BUGON(ret != size);
}
- ret = erofs_setxattr(inode, key, value, size);
+ ret = erofs_setxattr(inode, key, value, size, false);
free(value);
if (ret)
break;
--
2.19.1.6.gb485710b
More information about the Linux-erofs
mailing list