summaryrefslogtreecommitdiffstats
path: root/FatPkg
diff options
context:
space:
mode:
authorRobinson, Herbie <Herbie.Robinson@stratus.com>2018-09-07 08:07:09 +0800
committerRuiyu Ni <ruiyu.ni@intel.com>2018-10-24 13:30:43 +0800
commitadd1310df55eede2f52f44a021802831c683577d (patch)
treee0b6d8a7caf5a6d37e546b84cdbd2dcd659e7520 /FatPkg
parent8a2794f6f3a42bcc878a30565e1db9ac96fdc7cd (diff)
downloadedk2-add1310df55eede2f52f44a021802831c683577d.tar.gz
edk2-add1310df55eede2f52f44a021802831c683577d.tar.bz2
edk2-add1310df55eede2f52f44a021802831c683577d.zip
FatPkg/EnhancedFatDxe Fix Double Cluster Allocation
This is a fix for a double cluster allocation when the disk is full. The double allocation happens because FatGrowEof calls FatAllocateCluster without immediately marking the each returned cluster as allocated. The fix is to move the FatSetFatEntry call inside the loop. I've also include some improvements to the sanity checks that I added while tracking this down. They are optional. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Herbie Robinson <Herbie.Robinson@stratus.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Diffstat (limited to 'FatPkg')
-rw-r--r--FatPkg/EnhancedFatDxe/FileSpace.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/FatPkg/EnhancedFatDxe/FileSpace.c b/FatPkg/EnhancedFatDxe/FileSpace.c
index 1254cd68b5..50391b75b8 100644
--- a/FatPkg/EnhancedFatDxe/FileSpace.c
+++ b/FatPkg/EnhancedFatDxe/FileSpace.c
@@ -467,7 +467,7 @@ FatGrowEof (
ClusterCount = 0;
while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
- if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
+ if (Cluster < FAT_MIN_CLUSTER || Cluster > Volume->MaxCluster + 1) {
DEBUG (
(EFI_D_INIT | EFI_D_ERROR,
@@ -509,6 +509,11 @@ FatGrowEof (
goto Done;
}
+ if (NewCluster < FAT_MIN_CLUSTER || NewCluster > Volume->MaxCluster + 1) {
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Done;
+ }
+
if (LastCluster != 0) {
FatSetFatEntry (Volume, LastCluster, NewCluster);
} else {
@@ -518,12 +523,21 @@ FatGrowEof (
LastCluster = NewCluster;
CurSize += 1;
+
+ //
+ // Terminate the cluster list
+ //
+ // Note that we must do this EVERY time we allocate a cluster, because
+ // FatAllocateCluster scans the FAT looking for a free cluster and
+ // "LastCluster" is no longer free! Usually, FatAllocateCluster will
+ // start looking with the cluster after "LastCluster"; however, when
+ // there is only one free cluster left, it will find "LastCluster"
+ // a second time. There are other, less predictable scenarios
+ // where this could happen, as well.
+ //
+ FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
+ OFile->FileLastCluster = LastCluster;
}
- //
- // Terminate the cluster list
- //
- FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
- OFile->FileLastCluster = LastCluster;
}
OFile->FileSize = (UINTN) NewSizeInBytes;
@@ -603,7 +617,7 @@ FatOFilePosition (
Cluster = FatGetFatEntry (Volume, Cluster);
}
- if (Cluster < FAT_MIN_CLUSTER) {
+ if (Cluster < FAT_MIN_CLUSTER || Cluster > Volume->MaxCluster + 1) {
return EFI_VOLUME_CORRUPTED;
}