]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
ext4: Improve feature checking
authorRichard Weinberger <richard@nod.at>
Mon, 29 Jul 2024 21:37:31 +0000 (23:37 +0200)
committerTom Rini <trini@konsulko.com>
Thu, 15 Aug 2024 20:35:15 +0000 (14:35 -0600)
Evaluate the filesystem incompat and ro_compat bit fields to judge
whether the filesystem can be read or written.
For the read side only a scary warning is shown so far.
I'd love to abort mounting too, but I fear this will break some setups
where the driver works by chance.

Signed-off-by: Richard Weinberger <richard@nod.at>
fs/ext4/ext4_common.c
fs/ext4/ext4_write.c
include/ext4fs.h

index 52152a2295a10540ffadda7411062f2f514a2901..7cf0160c408d5882550b625245dd5d2f93cf78e5 100644 (file)
@@ -2383,6 +2383,20 @@ int ext4fs_mount(void)
                fs->inodesz = 128;
                fs->gdsize = 32;
        } else {
+               int missing = __le32_to_cpu(data->sblock.feature_incompat) &
+                             ~(EXT4_FEATURE_INCOMPAT_SUPP |
+                               EXT4_FEATURE_INCOMPAT_SUPP_LAZY_RO);
+
+               if (missing) {
+                       /*
+                        * This code used to be relaxed about feature flags.
+                        * We don't stop the mount to avoid breaking existing setups.
+                        * But, incompatible features can cause serious read errors.
+                        */
+                       log_err("fs uses incompatible features: %08x, ignoring\n",
+                               missing);
+               }
+
                debug("EXT4 features COMPAT: %08x INCOMPAT: %08x RO_COMPAT: %08x\n",
                      __le32_to_cpu(data->sblock.feature_compatibility),
                      __le32_to_cpu(data->sblock.feature_incompat),
index a2dfff8197928a1e885fb1151938ef6e2b7165df..d109ed6e90db07ff127644abe7648248caf06068 100644 (file)
@@ -866,6 +866,7 @@ int ext4fs_write(const char *fname, const char *buffer,
        ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256);
        bool store_link_in_inode = false;
        memset(filename, 0x00, 256);
+       int missing_feat;
 
        if (type != FILETYPE_REG && type != FILETYPE_SYMLINK)
                return -1;
@@ -879,8 +880,15 @@ int ext4fs_write(const char *fname, const char *buffer,
                return -1;
        }
 
-       if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
-               printf("Unsupported feature metadata_csum found, not writing.\n");
+       missing_feat = le32_to_cpu(fs->sb->feature_incompat) & ~EXT4_FEATURE_INCOMPAT_SUPP;
+       if (missing_feat) {
+               log_err("Unsupported features found %08x, not writing.\n", missing_feat);
+               return -1;
+       }
+
+       missing_feat = le32_to_cpu(fs->sb->feature_ro_compat) & ~EXT4_FEATURE_RO_COMPAT_SUPP;
+       if (missing_feat) {
+               log_err("Unsupported RO compat features found %08x, not writing.\n", missing_feat);
                return -1;
        }
 
index d96edfd0576cefaacbd7900d7287caf420f1ce78..41f9eb8bd336747a54e3b5a3eb971fd8b3640ed6 100644 (file)
@@ -34,12 +34,63 @@ struct disk_partition;
 #define EXT4_TOPDIR_FL         0x00020000 /* Top of directory hierarchies*/
 #define EXT4_EXTENTS_FL                0x00080000 /* Inode uses extents */
 #define EXT4_EXT_MAGIC                 0xf30a
-#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM        0x0010
+
+#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER  0x0001
+#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE    0x0002
+#define EXT4_FEATURE_RO_COMPAT_BTREE_DIR     0x0004
+#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE     0x0008
+#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM      0x0010
+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK     0x0020
+#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE   0x0040
+#define EXT4_FEATURE_RO_COMPAT_QUOTA         0x0100
+#define EXT4_FEATURE_RO_COMPAT_BIGALLOC      0x0200
 #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400
+
+#define EXT4_FEATURE_INCOMPAT_FILETYPE  0x0002
+#define EXT4_FEATURE_INCOMPAT_RECOVER   0x0004
 #define EXT4_FEATURE_INCOMPAT_EXTENTS  0x0040
 #define EXT4_FEATURE_INCOMPAT_64BIT    0x0080
+#define EXT4_FEATURE_INCOMPAT_MMP       0x0100
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG   0x0200
+#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000
+#define EXT4_FEATURE_INCOMPAT_ENCRYPT   0x10000
+
 #define EXT4_INDIRECT_BLOCKS           12
 
+/*
+ * Incompat features supported by this implementation.
+ */
+#define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE | \
+                                  EXT4_FEATURE_INCOMPAT_RECOVER | \
+                                  EXT4_FEATURE_INCOMPAT_EXTENTS | \
+                                  EXT4_FEATURE_INCOMPAT_64BIT | \
+                                  EXT4_FEATURE_INCOMPAT_FLEX_BG)
+
+/*
+ * Incompat features supported by this implementation only in a lazy
+ * way, good enough for reading files.
+ *
+ * - Multi mount protection (mmp) is not supported, but for read-only
+ *   we get away with it.
+ * - Same for metadata_csum_seed and metadata_csum.
+ * - The implementation has also no clue about fscrypt, but it can read
+ *   unencrypted files. Reading encrypted files will read garbage.
+ */
+#define EXT4_FEATURE_INCOMPAT_SUPP_LAZY_RO (EXT4_FEATURE_INCOMPAT_MMP | \
+                                          EXT4_FEATURE_INCOMPAT_CSUM_SEED | \
+                                          EXT4_FEATURE_INCOMPAT_ENCRYPT)
+
+/*
+ * Read-only compat features we support.
+ * If unknown ro compat features are detected, writing to the fs is denied.
+ */
+#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | \
+                                   EXT4_FEATURE_RO_COMPAT_LARGE_FILE | \
+                                   EXT4_FEATURE_RO_COMPAT_HUGE_FILE | \
+                                   EXT4_FEATURE_RO_COMPAT_GDT_CSUM | \
+                                   EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
+                                   EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)
+
 #define EXT4_BG_INODE_UNINIT           0x0001
 #define EXT4_BG_BLOCK_UNINIT           0x0002
 #define EXT4_BG_INODE_ZEROED           0x0004