mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-22 00:42:03 +08:00
GP-6712 fix some ext4 bounds checking
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;
|
||||
|
||||
private static final int MAX_SANE_INODE_COUNT = 30_000_000; // should handle 500gb disk images
|
||||
|
||||
private int blockSize;
|
||||
private ByteProvider provider;
|
||||
private String volumeName;
|
||||
@@ -58,24 +60,17 @@ public class Ext4FileSystem extends AbstractFileSystem<Ext4File> {
|
||||
this.volumeName = superBlock.getVolumeName();
|
||||
this.uuid = NumericUtilities.convertBytesToString(superBlock.getS_uuid());
|
||||
|
||||
long blockCount = superBlock.getS_blocks_count();
|
||||
int s_log_block_size = superBlock.getS_log_block_size();
|
||||
this.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) (blockCount / superBlock.getS_blocks_per_group());
|
||||
if (blockCount % superBlock.getS_blocks_per_group() != 0) {
|
||||
numGroups++;
|
||||
this.blockSize = superBlock.getBlockSize();
|
||||
long numGroups = superBlock.getNumGroups();
|
||||
if (numGroups > Integer.MAX_VALUE - 1000 /*ensure we can alloc jvm array */) {
|
||||
throw new IOException("Bad numgroups: " + numGroups);
|
||||
}
|
||||
|
||||
int groupDescriptorOffset = blockSize + (superBlock.getS_first_data_block() * blockSize);
|
||||
reader.setPointerIndex(groupDescriptorOffset);
|
||||
monitor.initialize(numGroups);
|
||||
monitor.setMessage("Reading inode tables");
|
||||
Ext4GroupDescriptor[] groupDescriptors = new Ext4GroupDescriptor[numGroups];
|
||||
Ext4GroupDescriptor[] groupDescriptors = new Ext4GroupDescriptor[(int) numGroups];
|
||||
for (int i = 0; i < numGroups; i++) {
|
||||
groupDescriptors[i] = new Ext4GroupDescriptor(reader, superBlock.is64Bit());
|
||||
monitor.increment();
|
||||
@@ -297,6 +292,10 @@ public class Ext4FileSystem extends AbstractFileSystem<Ext4File> {
|
||||
private Ext4Inode[] getInodes(BinaryReader reader, Ext4GroupDescriptor[] groupDescriptors,
|
||||
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 inodesPerGroup = superBlock.getS_inodes_per_group();
|
||||
Ext4Inode[] inodes = new Ext4Inode[inodeCount + 1];
|
||||
|
||||
+12
-7
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* 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.ByteProvider;
|
||||
import ghidra.formats.gfilesystem.FSRLRoot;
|
||||
import ghidra.formats.gfilesystem.FileSystemService;
|
||||
import ghidra.formats.gfilesystem.*;
|
||||
import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
||||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeByteProvider;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
@@ -34,10 +33,16 @@ public class Ext4FileSystemFactory
|
||||
FileSystemService fsService, TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
|
||||
Ext4FileSystem fs = new Ext4FileSystem(targetFSRL, byteProvider);
|
||||
fs.mountFS(monitor);
|
||||
try {
|
||||
Ext4FileSystem fs = new Ext4FileSystem(targetFSRL, byteProvider);
|
||||
fs.mountFS(monitor);
|
||||
|
||||
return fs;
|
||||
return fs;
|
||||
}
|
||||
catch (IOException e) {
|
||||
FSUtilities.uncheckedClose(byteProvider, null);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+26
-3
@@ -125,15 +125,15 @@ public class Ext4SuperBlock implements StructConverter {
|
||||
}
|
||||
|
||||
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_r_blocks_count_lo = reader.readNextInt();
|
||||
s_free_blocks_count_lo = reader.readNextInt();
|
||||
s_free_inodes_count = 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_blocks_per_group = reader.readNextInt();
|
||||
s_blocks_per_group = reader.readNextUnsignedIntExact();
|
||||
s_clusters_per_group = reader.readNextInt();
|
||||
s_inodes_per_group = reader.readNextInt();
|
||||
s_mtime = reader.readNextInt();
|
||||
@@ -254,6 +254,14 @@ public class Ext4SuperBlock implements StructConverter {
|
||||
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() {
|
||||
return s_log_cluster_size;
|
||||
}
|
||||
@@ -262,6 +270,21 @@ public class Ext4SuperBlock implements StructConverter {
|
||||
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() {
|
||||
return s_clusters_per_group;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user