From 0fa24fd72d32468ce796d8d560bca6b07c3476ca Mon Sep 17 00:00:00 2001 From: dev747368 <48332326+dev747368@users.noreply.github.com> Date: Tue, 22 Jun 2021 18:57:40 -0400 Subject: [PATCH] GP-1067 fix Ext4 mounting fs in an oversized volume The fs mounting code was using the physical volume size instead of values from the superblock. --- .../file/formats/ext4/Ext4FileSystem.java | 22 +++++++------------ .../formats/ext4/Ext4GroupDescriptor.java | 8 +++++++ .../file/formats/ext4/Ext4SuperBlock.java | 8 +++++++ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4FileSystem.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4FileSystem.java index 2bc33985d7..5d6f9f0a0b 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4FileSystem.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4FileSystem.java @@ -57,15 +57,13 @@ public class Ext4FileSystem implements GFileSystem { this.uuid = NumericUtilities.convertBytesToString(superBlock.getS_uuid()); + long blockCount = superBlock.getS_blocks_count(); + int s_log_block_size = superBlock.getS_log_block_size(); blockSize = (int) Math.pow(2, (10 + s_log_block_size)); - int groupSize = blockSize * superBlock.getS_blocks_per_group(); - if (groupSize <= 0) { - throw new IOException("Invalid groupSize: " + groupSize); - } - int numGroups = (int) (provider.length() / groupSize); - if (provider.length() % groupSize != 0) { + int numGroups = (int) (blockCount / superBlock.getS_blocks_per_group()); + if (blockCount % superBlock.getS_blocks_per_group() != 0) { numGroups++; } @@ -81,7 +79,7 @@ public class Ext4FileSystem implements GFileSystem { monitor.incrementProgress(1); } - Ext4Inode[] inodes = getInodes(reader, superBlock, groupDescriptors, is64Bit, monitor); + Ext4Inode[] inodes = getInodes(reader, superBlock, groupDescriptors, monitor); int s_inodes_count = superBlock.getS_inodes_count(); for (int i = 0; i < s_inodes_count; i++) { @@ -400,23 +398,19 @@ public class Ext4FileSystem implements GFileSystem { } private Ext4Inode[] getInodes(BinaryReader reader, Ext4SuperBlock superBlock, - Ext4GroupDescriptor[] groupDescriptors, boolean is64Bit, TaskMonitor monitor) + Ext4GroupDescriptor[] groupDescriptors, TaskMonitor monitor) throws IOException, CancelledException { int inodeCount = superBlock.getS_inodes_count(); + int inodesPerGroup = superBlock.getS_inodes_per_group(); Ext4Inode[] inodes = new Ext4Inode[inodeCount + 1]; int inodeIndex = 1; for (int i = 0; i < groupDescriptors.length; i++) { monitor.checkCanceled(); - long inodeTableBlockOffset = groupDescriptors[i].getBg_inode_table_lo() & 0xffffffffL; - if (is64Bit) { - inodeTableBlockOffset = - (groupDescriptors[i].getBg_inode_table_hi() << 32) | inodeTableBlockOffset; - } + long inodeTableBlockOffset = groupDescriptors[i].getBg_inode_table(); long offset = inodeTableBlockOffset * blockSize; reader.setPointerIndex(offset); - int inodesPerGroup = superBlock.getS_inodes_per_group(); monitor.setMessage( "Reading inode table " + i + " of " + (groupDescriptors.length - 1) + "..."); monitor.setMaximum(inodesPerGroup); diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4GroupDescriptor.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4GroupDescriptor.java index 53a2090a43..df69b75bfe 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4GroupDescriptor.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4GroupDescriptor.java @@ -149,6 +149,14 @@ public class Ext4GroupDescriptor implements StructConverter { return bg_inode_table_hi; } + /** + * Return the calculated inode table value by combining bg_inode_table_lo and bg_inode_table_hi + * @return the calculated inode table value by combining bg_inode_table_lo and bg_inode_table_hi + */ + public long getBg_inode_table() { + return ((long) bg_inode_table_hi << 32) | Integer.toUnsignedLong(bg_inode_table_lo); + } + public short getBg_free_blocks_count_hi() { return bg_free_blocks_count_hi; } diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4SuperBlock.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4SuperBlock.java index d2a7e4b7d6..cb20ba2544 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4SuperBlock.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ext4/Ext4SuperBlock.java @@ -226,6 +226,14 @@ public class Ext4SuperBlock implements StructConverter { return s_blocks_count_lo; } + /** + * Return the calculated block count by combining the s_blocks_count_lo and s_blocks_count_hi + * @return the calculated block count by combining the s_blocks_count_lo and s_blocks_count_hi + */ + public long getS_blocks_count() { + return ((long) s_blocks_count_hi << 32) | Integer.toUnsignedLong(s_blocks_count_lo); + } + public int getS_r_blocks_count_lo() { return s_r_blocks_count_lo; }