From 255101471918ed8840f2be347916b90eef0e9c08 Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Sat, 14 Apr 2018 11:06:13 +0800 Subject: [PATCH] FatPkg/EnhancedFatDxe: Ensure traverse of subtasks is delete-safe Within function FatQueueTask(), the traverse of FAT subtasks for executing the disk read/write is not delete-safe. For the below case: FatDiskIo(): When non-blocking access, creates subtasks and creates event (FatOnAccessComplete, NOTIFY level) when subtasks finish. FatQueueTask(): Traverses the subtasks and submits them one by one at Tpl lower than NOTIFY. Disk R/W completes really quick. FatOnAccessComplete(): Removes the finished subtask, causing the traverse in FatQueueTask() broken. This commits will refine the subtask traverse in FatQueueTask() to be delete-safe. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Hao Wu Reviewed-by: Ruiyu Ni --- FatPkg/EnhancedFatDxe/Misc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/FatPkg/EnhancedFatDxe/Misc.c b/FatPkg/EnhancedFatDxe/Misc.c index c035670bf7..af66b1d0e3 100644 --- a/FatPkg/EnhancedFatDxe/Misc.c +++ b/FatPkg/EnhancedFatDxe/Misc.c @@ -132,6 +132,7 @@ FatQueueTask ( { EFI_STATUS Status; LIST_ENTRY *Link; + LIST_ENTRY *NextLink; FAT_SUBTASK *Subtask; // @@ -149,9 +150,17 @@ FatQueueTask ( EfiReleaseLock (&FatTaskLock); Status = EFI_SUCCESS; - for ( Link = GetFirstNode (&Task->Subtasks) - ; !IsNull (&Task->Subtasks, Link) - ; Link = GetNextNode (&Task->Subtasks, Link) + // + // Use NextLink to store the next link of the list, because Link might be remove from the + // doubly-linked list and get freed in the end of current loop. + // + // Also, list operation APIs like IsNull() and GetNextNode() are avoided during the loop, since + // they may check the validity of doubly-linked lists by traversing them. These APIs cannot + // handle list elements being removed during the traverse. + // + for ( Link = GetFirstNode (&Task->Subtasks), NextLink = GetNextNode (&Task->Subtasks, Link) + ; Link != &Task->Subtasks + ; Link = NextLink, NextLink = Link->ForwardLink ) { Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE); if (Subtask->Write) { -- 2.39.2