Skip to content
3 changes: 3 additions & 0 deletions drivers/filesystems/udfs/protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -1380,6 +1380,9 @@ UDFAcquireResource(
#define UDFAcquirePagingIoExclusive(IC,F) \
UDFAcquireResource((IC), (F)->Header.PagingIoResource, FALSE, AcquireExclusive)

#define UDFAcquirePagingIoShared(IC,F) \
UDFAcquireResource((IC), (F)->Header.PagingIoResource, FALSE, AcquireShared)

#define UDFReleasePagingIo(IC,F) \
ExReleaseResourceLite((F)->Header.PagingIoResource)

Expand Down
9 changes: 9 additions & 0 deletions drivers/filesystems/udfs/read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ UDFCommonRead(
PVCB Vcb = NULL;
BOOLEAN VcbAcquired = FALSE;
BOOLEAN FcbAcquired = FALSE;
BOOLEAN PagingIoResourceAcquired = FALSE;
PVOID SystemBuffer = NULL;

BOOLEAN Wait;
Expand Down Expand Up @@ -157,6 +158,11 @@ UDFCommonRead(

UDFAcquireFcbSharedStarveExclusive(IrpContext, Fcb, FALSE);
FcbAcquired = TRUE;
// Acquire PagingIo resource shared to serialize with writes that hold
// it exclusively while modifying the extent mapping (UDFResizeExtent).
// This prevents a use-after-free when iterating DataLoc.Mapping.
UDFAcquirePagingIoShared(IrpContext, Fcb);
PagingIoResourceAcquired = TRUE;

} else {

Expand Down Expand Up @@ -406,6 +412,9 @@ try_exit: NOTHING;

} _SEH2_FINALLY {

if (PagingIoResourceAcquired) {
UDFReleasePagingIo(IrpContext, Fcb);
}
if (FcbAcquired) {

UDFReleaseFcb(IrpContext, Fcb);
Expand Down
11 changes: 9 additions & 2 deletions drivers/filesystems/udfs/write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,15 @@ UDFCommonWrite(
}
}

UDFReleasePagingIo(IrpContext, Fcb);
PagingIoResourceAcquired = FALSE;
// For cached I/O, release now so that CcCopyWrite-triggered
// paging reads (which acquire PagingIoResource shared) do
// not deadlock against our exclusive hold.
// For non-cached I/O, keep it held through UDFWriteFile__ to
// protect against concurrent paging reads seeing a freed mapping.
if (!NonCachedIo) {
UDFReleasePagingIo(IrpContext, Fcb);
PagingIoResourceAcquired = FALSE;
}

if (CcIsFileCached(FileObject)) {
if (ExtendFS) {
Expand Down