mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 09:34:56 +08:00
Merge remote-tracking branch 'origin/GP-6712_dev747368_ext4_fixes'
This commit is contained in:
+11
-12
@@ -40,6 +40,8 @@ public class Ext4FileSystem extends AbstractFileSystem<Ext4File> {
|
|||||||
|
|
||||||
public static final Charset EXT4_DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
public static final Charset EXT4_DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
private static final int MAX_SANE_INODE_COUNT = 30_000_000; // should handle 500gb disk images
|
||||||
|
|
||||||
private int blockSize;
|
private int blockSize;
|
||||||
private ByteProvider provider;
|
private ByteProvider provider;
|
||||||
private String volumeName;
|
private String volumeName;
|
||||||
@@ -58,24 +60,17 @@ public class Ext4FileSystem extends AbstractFileSystem<Ext4File> {
|
|||||||
this.volumeName = superBlock.getVolumeName();
|
this.volumeName = superBlock.getVolumeName();
|
||||||
this.uuid = NumericUtilities.convertBytesToString(superBlock.getS_uuid());
|
this.uuid = NumericUtilities.convertBytesToString(superBlock.getS_uuid());
|
||||||
|
|
||||||
long blockCount = superBlock.getS_blocks_count();
|
this.blockSize = superBlock.getBlockSize();
|
||||||
int s_log_block_size = superBlock.getS_log_block_size();
|
long numGroups = superBlock.getNumGroups();
|
||||||
this.blockSize = (int) Math.pow(2, (10 + s_log_block_size));
|
if (numGroups > Integer.MAX_VALUE - 1000 /*ensure we can alloc jvm array */) {
|
||||||
|
throw new IOException("Bad numgroups: " + numGroups);
|
||||||
int groupSize = blockSize * superBlock.getS_blocks_per_group();
|
|
||||||
if (groupSize <= 0) {
|
|
||||||
throw new IOException("Invalid groupSize: " + groupSize);
|
|
||||||
}
|
|
||||||
int numGroups = (int) (blockCount / superBlock.getS_blocks_per_group());
|
|
||||||
if (blockCount % superBlock.getS_blocks_per_group() != 0) {
|
|
||||||
numGroups++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int groupDescriptorOffset = blockSize + (superBlock.getS_first_data_block() * blockSize);
|
int groupDescriptorOffset = blockSize + (superBlock.getS_first_data_block() * blockSize);
|
||||||
reader.setPointerIndex(groupDescriptorOffset);
|
reader.setPointerIndex(groupDescriptorOffset);
|
||||||
monitor.initialize(numGroups);
|
monitor.initialize(numGroups);
|
||||||
monitor.setMessage("Reading inode tables");
|
monitor.setMessage("Reading inode tables");
|
||||||
Ext4GroupDescriptor[] groupDescriptors = new Ext4GroupDescriptor[numGroups];
|
Ext4GroupDescriptor[] groupDescriptors = new Ext4GroupDescriptor[(int) numGroups];
|
||||||
for (int i = 0; i < numGroups; i++) {
|
for (int i = 0; i < numGroups; i++) {
|
||||||
groupDescriptors[i] = new Ext4GroupDescriptor(reader, superBlock.is64Bit());
|
groupDescriptors[i] = new Ext4GroupDescriptor(reader, superBlock.is64Bit());
|
||||||
monitor.increment();
|
monitor.increment();
|
||||||
@@ -297,6 +292,10 @@ public class Ext4FileSystem extends AbstractFileSystem<Ext4File> {
|
|||||||
private Ext4Inode[] getInodes(BinaryReader reader, Ext4GroupDescriptor[] groupDescriptors,
|
private Ext4Inode[] getInodes(BinaryReader reader, Ext4GroupDescriptor[] groupDescriptors,
|
||||||
TaskMonitor monitor) throws IOException, CancelledException {
|
TaskMonitor monitor) throws IOException, CancelledException {
|
||||||
|
|
||||||
|
if (superBlock.getS_inodes_count() > MAX_SANE_INODE_COUNT) {
|
||||||
|
throw new IOException("Inode number too big: " + superBlock.getS_inodes_count());
|
||||||
|
}
|
||||||
|
|
||||||
int inodeCount = superBlock.getS_inodes_count();
|
int inodeCount = superBlock.getS_inodes_count();
|
||||||
int inodesPerGroup = superBlock.getS_inodes_per_group();
|
int inodesPerGroup = superBlock.getS_inodes_per_group();
|
||||||
Ext4Inode[] inodes = new Ext4Inode[inodeCount + 1];
|
Ext4Inode[] inodes = new Ext4Inode[inodeCount + 1];
|
||||||
|
|||||||
+12
-7
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -19,8 +19,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
import ghidra.formats.gfilesystem.FSRLRoot;
|
import ghidra.formats.gfilesystem.*;
|
||||||
import ghidra.formats.gfilesystem.FileSystemService;
|
|
||||||
import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
||||||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeByteProvider;
|
import ghidra.formats.gfilesystem.factory.GFileSystemProbeByteProvider;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
@@ -34,10 +33,16 @@ public class Ext4FileSystemFactory
|
|||||||
FileSystemService fsService, TaskMonitor monitor)
|
FileSystemService fsService, TaskMonitor monitor)
|
||||||
throws IOException, CancelledException {
|
throws IOException, CancelledException {
|
||||||
|
|
||||||
Ext4FileSystem fs = new Ext4FileSystem(targetFSRL, byteProvider);
|
try {
|
||||||
fs.mountFS(monitor);
|
Ext4FileSystem fs = new Ext4FileSystem(targetFSRL, byteProvider);
|
||||||
|
fs.mountFS(monitor);
|
||||||
|
|
||||||
return fs;
|
return fs;
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
FSUtilities.uncheckedClose(byteProvider, null);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+26
-3
@@ -125,15 +125,15 @@ public class Ext4SuperBlock implements StructConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Ext4SuperBlock( BinaryReader reader ) throws IOException {
|
public Ext4SuperBlock( BinaryReader reader ) throws IOException {
|
||||||
s_inodes_count = reader.readNextInt();
|
s_inodes_count = reader.readNextUnsignedIntExact(); // error if more than 2.1billion
|
||||||
s_blocks_count_lo = reader.readNextInt();
|
s_blocks_count_lo = reader.readNextInt();
|
||||||
s_r_blocks_count_lo = reader.readNextInt();
|
s_r_blocks_count_lo = reader.readNextInt();
|
||||||
s_free_blocks_count_lo = reader.readNextInt();
|
s_free_blocks_count_lo = reader.readNextInt();
|
||||||
s_free_inodes_count = reader.readNextInt();
|
s_free_inodes_count = reader.readNextInt();
|
||||||
s_first_data_block = reader.readNextInt();
|
s_first_data_block = reader.readNextInt();
|
||||||
s_log_block_size = reader.readNextInt();
|
s_log_block_size = reader.readNextUnsignedIntExact();
|
||||||
s_log_cluster_size = reader.readNextInt();
|
s_log_cluster_size = reader.readNextInt();
|
||||||
s_blocks_per_group = reader.readNextInt();
|
s_blocks_per_group = reader.readNextUnsignedIntExact();
|
||||||
s_clusters_per_group = reader.readNextInt();
|
s_clusters_per_group = reader.readNextInt();
|
||||||
s_inodes_per_group = reader.readNextInt();
|
s_inodes_per_group = reader.readNextInt();
|
||||||
s_mtime = reader.readNextInt();
|
s_mtime = reader.readNextInt();
|
||||||
@@ -254,6 +254,14 @@ public class Ext4SuperBlock implements StructConverter {
|
|||||||
return s_log_block_size;
|
return s_log_block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getBlockSize() throws IOException {
|
||||||
|
if (s_log_block_size > 6) {
|
||||||
|
throw new IOException("Blocksize out of range: " + s_log_block_size);
|
||||||
|
}
|
||||||
|
int result = 1 << (10 + s_log_block_size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public int getS_log_cluster_size() {
|
public int getS_log_cluster_size() {
|
||||||
return s_log_cluster_size;
|
return s_log_cluster_size;
|
||||||
}
|
}
|
||||||
@@ -262,6 +270,21 @@ public class Ext4SuperBlock implements StructConverter {
|
|||||||
return s_blocks_per_group;
|
return s_blocks_per_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final int MAX_BLOCKS_PER_GROUP = 1 << 19;
|
||||||
|
|
||||||
|
public long getNumGroups() throws IOException {
|
||||||
|
int bs = getBlockSize();
|
||||||
|
if (s_blocks_per_group < bs || s_blocks_per_group > MAX_BLOCKS_PER_GROUP) {
|
||||||
|
throw new IOException("Bad blocks per group: " + s_blocks_per_group);
|
||||||
|
}
|
||||||
|
long blockCount = getS_blocks_count();
|
||||||
|
long numGroups = blockCount / s_blocks_per_group;
|
||||||
|
if (blockCount % s_blocks_per_group != 0) {
|
||||||
|
numGroups++;
|
||||||
|
}
|
||||||
|
return numGroups;
|
||||||
|
}
|
||||||
|
|
||||||
public int getS_clusters_per_group() {
|
public int getS_clusters_per_group() {
|
||||||
return s_clusters_per_group;
|
return s_clusters_per_group;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user