esfs: prevent allocating blocks past end of file system

This commit is contained in:
nakst 2022-03-21 14:53:08 +00:00
parent a0fe4d31e9
commit 4f9b5194cd
2 changed files with 25 additions and 6 deletions

View File

@ -42,6 +42,8 @@ struct FSNode {
static bool AccessBlock(Volume *volume, uint64_t index, uint64_t count, void *buffer, uint64_t flags, int driveAccess) {
// TODO Return EsError.
Superblock *superblock = &volume->superblock;
if (!count) return true;
ESFS_CHECK(index < superblock->blockCount && count <= superblock->blockCount - index, "AccessBlock - Access past the end of the file system.");
EsError error = volume->Access(index * superblock->blockSize, count * superblock->blockSize, driveAccess, buffer, flags, nullptr);
ESFS_CHECK_ERROR(error, "AccessBlock - Could not access blocks.");
return error == ES_SUCCESS;

View File

@ -1139,7 +1139,8 @@ bool Format(uint64_t driveSize, const char *volumeName, EsUniqueIdentifier osIns
uint64_t blockGDT = ESFS_BOOT_SUPER_BLOCK_SIZE * 2 / superblock.blockSize + 1;
uint64_t blockGroup0Bitmap = blockGDT + (superblock.groupCount * sizeof(GroupDescriptor) + superblock.blockSize - 1) / superblock.blockSize;
uint64_t blockCoreNodes = blockGroup0Bitmap + superblock.blocksPerGroupBlockBitmap;
uint64_t blockGroupLastBitmap = blockGroup0Bitmap + (superblock.groupCount * sizeof(GroupDescriptor) + superblock.blockSize - 1) / superblock.blockSize;
uint64_t blockCoreNodes = blockGroupLastBitmap + superblock.blocksPerGroupBlockBitmap;
uint64_t end = blockCoreNodes + ((ESFS_CORE_NODE_COUNT + superblock.directoryEntriesPerBlock - 1) / superblock.directoryEntriesPerBlock);
superblock.blocksUsed = end;
@ -1191,17 +1192,33 @@ bool Format(uint64_t driveSize, const char *volumeName, EsUniqueIdentifier osIns
for (uintptr_t i = 0; i < superblock.groupCount; i++) {
memcpy(buffer[i].signature, ESFS_GROUP_DESCRIPTOR_SIGNATURE, 4);
buffer[i].largestExtent = superblock.blocksPerGroup - superblock.blocksPerGroupBlockBitmap;
uint8_t bitmap[superblock.blocksPerGroupBlockBitmap * superblock.blockSize];
if (i == 0) {
uint8_t firstGroupBitmap[superblock.blocksPerGroupBlockBitmap * superblock.blockSize];
memset(firstGroupBitmap, 0, superblock.blocksPerGroupBlockBitmap * superblock.blockSize);
for (uint64_t i = 0; i < superblock.blocksUsed; i++) firstGroupBitmap[i / 8] |= 1 << (i % 8);
memset(bitmap, 0, superblock.blocksPerGroupBlockBitmap * superblock.blockSize);
for (uint64_t i = 0; i < superblock.blocksUsed; i++) bitmap[i / 8] |= 1 << (i % 8);
buffer[i].blocksUsed = superblock.blocksUsed;
buffer[i].blockBitmap = blockGroup0Bitmap;
buffer[i].bitmapChecksum = CalculateCRC32(firstGroupBitmap, sizeof(firstGroupBitmap), 0);
buffer[i].bitmapChecksum = CalculateCRC32(bitmap, sizeof(bitmap), 0);
buffer[i].largestExtent = superblock.blocksPerGroup - superblock.blocksUsed;
if (!WriteBytes(blockGroup0Bitmap * superblock.blockSize, sizeof(firstGroupBitmap), &firstGroupBitmap)) {
if (!WriteBytes(blockGroup0Bitmap * superblock.blockSize, sizeof(bitmap), &bitmap)) {
return false;
}
} else if (i == superblock.groupCount - 1) {
// Mark the blocks that go past the end of the file system in the last block group as allocated.
// TODO Make sure these blocks aren't deallocated by any future file system checker tools!
uint64_t overflow = superblock.blocksPerGroup * superblock.groupCount - superblock.blockCount;
assert(overflow < superblock.blocksPerGroup);
memset(bitmap, 0, superblock.blocksPerGroupBlockBitmap * superblock.blockSize);
for (uint64_t i = superblock.blocksPerGroup - overflow; i < superblock.blocksPerGroup; i++) bitmap[i / 8] |= 1 << (i % 8);
buffer[i].blocksUsed = overflow;
buffer[i].blockBitmap = blockGroupLastBitmap;
buffer[i].bitmapChecksum = CalculateCRC32(bitmap, sizeof(bitmap), 0);
buffer[i].largestExtent = superblock.blocksPerGroup - overflow;
if (!WriteBytes(blockGroupLastBitmap * superblock.blockSize, sizeof(bitmap), &bitmap)) {
return false;
}
}