From 4f9b5194cd31a41e71665014c3829366849a97ea Mon Sep 17 00:00:00 2001 From: nakst <> Date: Mon, 21 Mar 2022 14:53:08 +0000 Subject: [PATCH] esfs: prevent allocating blocks past end of file system --- drivers/esfs2.cpp | 2 ++ shared/esfs2.h | 29 +++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/esfs2.cpp b/drivers/esfs2.cpp index c40283c..4b3a7f6 100644 --- a/drivers/esfs2.cpp +++ b/drivers/esfs2.cpp @@ -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; diff --git a/shared/esfs2.h b/shared/esfs2.h index 56c3005..1bb8373 100644 --- a/shared/esfs2.h +++ b/shared/esfs2.h @@ -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; } }