Blame SOURCES/0221-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch

8e15ce
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
8e15ce
From: Erwan Velu <erwanaliasr1@gmail.com>
8e15ce
Date: Wed, 25 Aug 2021 15:31:52 +0200
8e15ce
Subject: [PATCH] fs/xfs: Fix unreadable filesystem with v4 superblock
8e15ce
8e15ce
The commit 8b1e5d193 (fs/xfs: Add bigtime incompat feature support)
8e15ce
introduced the bigtime support by adding some features in v3 inodes.
8e15ce
This change extended grub_xfs_inode struct by 76 bytes but also changed
8e15ce
the computation of XFS_V2_INODE_SIZE and XFS_V3_INODE_SIZE. Prior this
8e15ce
commit, XFS_V2_INODE_SIZE was 100 bytes. After the commit it's 84 bytes
8e15ce
XFS_V2_INODE_SIZE becomes 16 bytes too small.
8e15ce
8e15ce
As a result, the data structures aren't properly aligned and the GRUB
8e15ce
generates "attempt to read or write outside of partition" errors when
8e15ce
trying to read the XFS filesystem:
8e15ce
8e15ce
                             GNU GRUB  version 2.11
8e15ce
	....
8e15ce
	grub> set debug=efi,gpt,xfs
8e15ce
	grub> insmod part_gpt
8e15ce
	grub> ls (hd0,gpt1)/
8e15ce
	partmap/gpt.c:93: Read a valid GPT header
8e15ce
	partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125
8e15ce
	fs/xfs.c:931: Reading sb
8e15ce
	fs/xfs.c:270: Validating superblock
8e15ce
	fs/xfs.c:295: XFS v4 superblock detected
8e15ce
	fs/xfs.c:962: Reading root ino 128
8e15ce
	fs/xfs.c:515: Reading inode (128) - 64, 0
8e15ce
	fs/xfs.c:515: Reading inode (739521961424144223) - 344365866970255880, 3840
8e15ce
	error: attempt to read or write outside of partition.
8e15ce
8e15ce
This commit change the XFS_V2_INODE_SIZE computation by subtracting 76
8e15ce
bytes instead of 92 bytes from the actual size of grub_xfs_inode struct.
8e15ce
This 76 bytes value comes from added members:
8e15ce
	20 grub_uint8_t   unused5
8e15ce
	 1 grub_uint64_t  flags2
8e15ce
        48 grub_uint8_t   unused6
8e15ce
8e15ce
This patch explicitly splits the v2 and v3 parts of the structure.
8e15ce
The unused4 is still ending of the v2 structures and the v3 starts
8e15ce
at unused5. Thanks to this we will avoid future corruptions of v2
8e15ce
or v3 inodes.
8e15ce
8e15ce
The XFS_V2_INODE_SIZE is returning to its expected size and the
8e15ce
filesystem is back to a readable state:
8e15ce
8e15ce
                      GNU GRUB  version 2.11
8e15ce
	....
8e15ce
	grub> set debug=efi,gpt,xfs
8e15ce
	grub> insmod part_gpt
8e15ce
	grub> ls (hd0,gpt1)/
8e15ce
	partmap/gpt.c:93: Read a valid GPT header
8e15ce
	partmap/gpt.c:115: GPT entry 0: start=4096, length=1953125
8e15ce
	fs/xfs.c:931: Reading sb
8e15ce
	fs/xfs.c:270: Validating superblock
8e15ce
	fs/xfs.c:295: XFS v4 superblock detected
8e15ce
	fs/xfs.c:962: Reading root ino 128
8e15ce
	fs/xfs.c:515: Reading inode (128) - 64, 0
8e15ce
	fs/xfs.c:515: Reading inode (128) - 64, 0
8e15ce
	fs/xfs.c:931: Reading sb
8e15ce
	fs/xfs.c:270: Validating superblock
8e15ce
	fs/xfs.c:295: XFS v4 superblock detected
8e15ce
	fs/xfs.c:962: Reading root ino 128
8e15ce
	fs/xfs.c:515: Reading inode (128) - 64, 0
8e15ce
	fs/xfs.c:515: Reading inode (128) - 64, 0
8e15ce
	fs/xfs.c:515: Reading inode (128) - 64, 0
8e15ce
	fs/xfs.c:515: Reading inode (131) - 64, 768
8e15ce
	efi/ fs/xfs.c:515: Reading inode (3145856) - 1464904, 0
8e15ce
	grub2/ fs/xfs.c:515: Reading inode (132) - 64, 1024
8e15ce
	grub/ fs/xfs.c:515: Reading inode (139) - 64, 2816
8e15ce
	grub>
8e15ce
8e15ce
Fixes: 8b1e5d193 (fs/xfs: Add bigtime incompat feature support)
8e15ce
8e15ce
Signed-off-by: Erwan Velu <e.velu@criteo.com>
8e15ce
Tested-by: Carlos Maiolino <cmaiolino@redhat.com>
8e15ce
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
8e15ce
(cherry picked from commit a4b495520e4dc41a896a8b916a64eda9970c50ea)
8e15ce
---
8e15ce
 grub-core/fs/xfs.c | 14 ++++++++++----
8e15ce
 1 file changed, 10 insertions(+), 4 deletions(-)
8e15ce
8e15ce
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
8e15ce
index 0f524c3a8a6..e3816d1ec4a 100644
8e15ce
--- a/grub-core/fs/xfs.c
8e15ce
+++ b/grub-core/fs/xfs.c
8e15ce
@@ -192,6 +192,11 @@ struct grub_xfs_time_legacy
8e15ce
   grub_uint32_t nanosec;
8e15ce
 } GRUB_PACKED;
8e15ce
 
8e15ce
+/*
8e15ce
+ * The struct grub_xfs_inode layout was taken from the
8e15ce
+ * struct xfs_dinode_core which is described here:
8e15ce
+ * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf
8e15ce
+ */
8e15ce
 struct grub_xfs_inode
8e15ce
 {
8e15ce
   grub_uint8_t magic[2];
8e15ce
@@ -208,14 +213,15 @@ struct grub_xfs_inode
8e15ce
   grub_uint32_t nextents;
8e15ce
   grub_uint16_t unused3;
8e15ce
   grub_uint8_t fork_offset;
8e15ce
-  grub_uint8_t unused4[37];
8e15ce
+  grub_uint8_t unused4[17]; /* Last member of inode v2. */
8e15ce
+  grub_uint8_t unused5[20]; /* First member of inode v3. */
8e15ce
   grub_uint64_t flags2;
8e15ce
-  grub_uint8_t unused5[48];
8e15ce
+  grub_uint8_t unused6[48]; /* Last member of inode v3. */
8e15ce
 } GRUB_PACKED;
8e15ce
 
8e15ce
 #define XFS_V3_INODE_SIZE	sizeof(struct grub_xfs_inode)
8e15ce
-/* Size of struct grub_xfs_inode until fork_offset (included). */
8e15ce
-#define XFS_V2_INODE_SIZE	(XFS_V3_INODE_SIZE - 92)
8e15ce
+/* Size of struct grub_xfs_inode v2, up to unused4 member included. */
8e15ce
+#define XFS_V2_INODE_SIZE	(XFS_V3_INODE_SIZE - 76)
8e15ce
 
8e15ce
 struct grub_xfs_dirblock_tail
8e15ce
 {