[PATCH 3/3] ovl: Use real disk UUID for origin file handles

From: André Almeida

Date: Tue Jan 13 2026 - 23:32:46 EST


Some filesystem, like btrfs, supports mounting cloned images, but assign
random UUIDs for them to avoid conflicts. This breaks overlayfs "index"
check, given that every time the same image is mounted, it get's
assigned a new UUID.

Fix this assigning the disk UUID for filesystem that implements the
export operation get_disk_uuid(), so overlayfs check is also against the
same value.

Signed-off-by: André Almeida <andrealmeid@xxxxxxxxxx>
---
fs/overlayfs/copy_up.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 758611ee4475..8551681fffd3 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -421,8 +421,26 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode,
struct ovl_fh *fh;
int fh_type, dwords;
int buflen = MAX_HANDLE_SZ;
- uuid_t *uuid = &realinode->i_sb->s_uuid;
- int err;
+ struct super_block *real_sb = realinode->i_sb;
+ uuid_t *uuid = &real_sb->s_uuid, real_uuid;
+ u32 len = sizeof(uuid_t);
+ int err, ret;
+ u64 offset;
+
+ /*
+ * Some filesystems that support cloned devices may expose random UUIDs
+ * for userspace, which will cause the upper root origin check to fail
+ * during a remount. To avoid this, store the real disk UUID.
+ *
+ * ENODATA means that the filesystem implements get_disk_uuid(), but
+ * this instance is using the real UUID so we can skip the operation.
+ */
+ if (real_sb->s_export_op && real_sb->s_export_op->get_disk_uuid) {
+ ret = real_sb->s_export_op->get_disk_uuid(real_sb, real_uuid.b, &len, &offset);
+
+ if (!ret || ret != ENODATA)
+ uuid = &real_uuid;
+ }

/* Make sure the real fid stays 32bit aligned */
BUILD_BUG_ON(OVL_FH_FID_OFFSET % 4);

--
2.52.0