Browse Source

Ext4Pkg: Fix shift out of bounds in Ext4OpenSuperblock

Missing check for wrong s_log_block_size exponent leads to shift out of
bounds. Limit block size to 2 MiB

Cc: Marvin Häuser <mhaeuser@posteo.de>
Cc: Pedro Falcato <pedro.falcato@gmail.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Fixes: d9ceedca6c8f ("Ext4Pkg: Add Ext4Dxe driver.")
Signed-off-by: Savva Mitrofanov <savvamtr@gmail.com>
Reviewed-by: Pedro Falcato <pedro.falcato@gmail.com>
Reviewed-by: Marvin Häuser <mhaeuser@posteo.de>
Savva Mitrofanov 1 year ago
parent
commit
127af29959
2 changed files with 19 additions and 0 deletions
  1. 14 0
      Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h
  2. 5 0
      Features/Ext4Pkg/Ext4Dxe/Superblock.c

+ 14 - 0
Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h

@@ -40,6 +40,20 @@
 #define EXT4_EFI_PATH_MAX    4096
 #define EXT4_DRIVER_VERSION  0x0000
 
+//
+// The EXT4 Specification doesn't strictly limit block size and this value could be up to 2^31,
+// but in practice it is limited by PAGE_SIZE due to performance significant impact.
+// Many EXT4 implementations have size of block limited to PAGE_SIZE. In many cases it's limited
+// to 4096, which is a commonly supported page size on most MMU-capable hardware, and up to 65536.
+// So, to take a balance between compatibility and security measures, it is decided to use the
+// value of 2MiB as the limit, which is equal to large page size on new hardware.
+// As for supporting big block sizes, EXT4 has a RO_COMPAT_FEATURE called BIGALLOC, which changes
+// EXT4 to use clustered allocation, so that each bit in the ext4 block allocation bitmap addresses
+// a power of two number of blocks. So it would be wiser to implement and use this feature
+// if there is such a need instead of big block size.
+//
+#define EXT4_LOG_BLOCK_SIZE_MAX  11
+
 /**
    Opens an ext4 partition and installs the Simple File System protocol.
 

+ 5 - 0
Features/Ext4Pkg/Ext4Dxe/Superblock.c

@@ -248,6 +248,11 @@ Ext4OpenSuperblock (
     return EFI_VOLUME_CORRUPTED;
   }
 
+  if (Sb->s_log_block_size > EXT4_LOG_BLOCK_SIZE_MAX) {
+    DEBUG ((DEBUG_ERROR, "[ext4] SuperBlock s_log_block_size %lu is too big\n", Sb->s_log_block_size));
+    return EFI_UNSUPPORTED;
+  }
+
   Partition->BlockSize = (UINT32)LShiftU64 (1024, Sb->s_log_block_size);
 
   // The size of a block group can also be calculated as 8 * Partition->BlockSize