From 7c501359b3c6c5c09a60abc6f3831254e592afb1 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Mon, 1 Sep 2014 00:03:26 +0200 Subject: Windows vulnerability fix: correct some integer overflow issues using the IntSafe library. Detected by the Open Crypto Audit project --- src/Driver/EncryptedIoQueue.c | 31 +++++++++++++++++++++++++++---- src/Driver/Ntdriver.c | 15 +++++++++++++-- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/Driver/EncryptedIoQueue.c b/src/Driver/EncryptedIoQueue.c index bb76a0f5..7c9441ec 100644 --- a/src/Driver/EncryptedIoQueue.c +++ b/src/Driver/EncryptedIoQueue.c @@ -13,6 +13,7 @@ #include "EncryptedIoQueue.h" #include "EncryptionThreadPool.h" #include "Volumes.h" +#include static void AcquireBufferPoolMutex (EncryptedIoQueue *queue) @@ -492,6 +493,8 @@ static VOID MainThreadProc (PVOID threadArg) EncryptedIoRequest *request; uint64 intersectStart; uint32 intersectLength; + ULONGLONG addResult; + HRESULT hResult; if (IsEncryptionThreadPoolRunning()) KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY); @@ -561,8 +564,15 @@ static VOID MainThreadProc (PVOID threadArg) && (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) { byte *buffer; - ULONG alignedLength = item->OriginalLength + ENCRYPTION_DATA_UNIT_SIZE; + ULONG alignedLength; LARGE_INTEGER alignedOffset; + hResult = ULongAdd(item->OriginalLength, ENCRYPTION_DATA_UNIT_SIZE, &alignedLength); + if (hResult != S_OK) + { + CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); + continue; + } + alignedOffset.QuadPart = item->OriginalOffset.QuadPart & ~((LONGLONG) ENCRYPTION_DATA_UNIT_SIZE - 1); buffer = TCalloc (alignedLength); @@ -608,7 +618,12 @@ static VOID MainThreadProc (PVOID threadArg) if (item->OriginalLength == 0 || (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0 || (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0 - || (!queue->IsFilterDevice && item->OriginalOffset.QuadPart + item->OriginalLength > queue->VirtualDeviceLength)) + || ( !queue->IsFilterDevice && + ( (S_OK != ULongLongAdd(item->OriginalOffset.QuadPart, item->OriginalLength, &addResult)) + || (addResult > (ULONGLONG) queue->VirtualDeviceLength) + ) + ) + ) { CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); continue; @@ -622,9 +637,17 @@ static VOID MainThreadProc (PVOID threadArg) { // Adjust the offset for host file or device if (queue->CryptoInfo->hiddenVolume) - item->OriginalOffset.QuadPart += queue->CryptoInfo->hiddenVolumeOffset; + hResult = ULongLongAdd(item->OriginalOffset.QuadPart, queue->CryptoInfo->hiddenVolumeOffset, &addResult); + else + hResult = ULongLongAdd(item->OriginalOffset.QuadPart, queue->CryptoInfo->volDataAreaOffset, &addResult); + + if (hResult != S_OK) + { + CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); + continue; + } else - item->OriginalOffset.QuadPart += queue->CryptoInfo->volDataAreaOffset; + item->OriginalOffset.QuadPart = addResult; // Hidden volume protection if (item->Write && queue->CryptoInfo->bProtectHiddenVolume) diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c index 72f35c67..556badbf 100644 --- a/src/Driver/Ntdriver.c +++ b/src/Driver/Ntdriver.c @@ -34,6 +34,7 @@ #include #include +#include /* Init section, which is thrown away as soon as DriverEntry returns */ #pragma alloc_text(INIT,DriverEntry) @@ -704,10 +705,20 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION case IOCTL_DISK_VERIFY: if (ValidateIOBufferSize (Irp, sizeof (VERIFY_INFORMATION), ValidateInput)) { + HRESULT hResult; + ULONGLONG ullStartingOffset, ullNewOffset, ullEndOffset; PVERIFY_INFORMATION pVerifyInformation; pVerifyInformation = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer; - if (pVerifyInformation->StartingOffset.QuadPart + pVerifyInformation->Length > Extension->DiskLength) + ullStartingOffset = (ULONGLONG) pVerifyInformation->StartingOffset.QuadPart; + hResult = ULongLongAdd(ullStartingOffset, + (ULONGLONG) Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset, + &ullNewOffset); + if (hResult != S_OK) + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + else if (S_OK != ULongLongAdd(ullNewOffset, (ULONGLONG) pVerifyInformation->Length, &ullEndOffset)) + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + else if (ullEndOffset > (ULONGLONG) Extension->DiskLength) Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; else { @@ -721,7 +732,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION else { LARGE_INTEGER offset = pVerifyInformation->StartingOffset; - offset.QuadPart += Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset; + offset.QuadPart = ullNewOffset; Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, pVerifyInformation->Length, &offset, NULL); TCfree (buffer); -- cgit v1.2.3