Hi, all
I'm writting a driver which works as a DiskDrive upper filter ( ClassGUID: {4D36E967-E325-11CE-BFC1-08002BE10318}).
The code of IRP_MJ_READ Dispatch is very very simple :
NTSTATUS DiskReadDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PDISK_DEVICE_EXTENSION deviceExtension;
NTSTATUS status = STATUS_INVALID_DEVICE_STATE;
deviceExtension = (PDISK_DEVICE_EXTENSION )DeviceObject->DeviceExtension;
if(deviceExtension == NULL)
{
KdBreakPoint(); // had never execute in here
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
return status;
}
PIO_STACK_LOCATION irpStack = NULL;
irpStack = IoGetCurrentIrpStackLocation(Irp);
do
{
if( irpStack->MajorFunction != IRP_MJ_READ )
{
KdBreakPoint(); // had never execute in here
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
return status;
}
ULONG ulRequestReadLen = irpStack->Parameters.Read.Length;
if (Irp->MdlAddress == NULL || ulRequestReadLen == 0)
{
break;
}
if (MmGetMdlByteCount(Irp->MdlAddress) < ulRequestReadLen)
{
break;
}
PVOID pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,NormalPagePriority);
if (!pOutputBuffer)
{
break;
}
PVOID pJustTest = ExAllocatePoolWithTag(NonPagedPool,ulRequestReadLen,'tseT');
if (pJustTest)
{
memset(pJustTest,0x18,ulRequestReadLen);
if(irpStack->Parameters.Read.ByteOffset.QuadPart == 0xF8CE0000)
{
KdBreakPoint(); // just for debug
}
memcpy(pOutputBuffer, pJustTest, ulRequestReadLen);
if ( memcmp( pOutputBuffer, pJustTest, ulRequestReadLen) != 0 )
{
KdPrint(("data diff!\r\n")); // !!!!!!!!!! Problems here: I don't understand why the code can excute to here
KdBreakPoint();
}
ExFreePool(pJustTest);
}
} while (FALSE);
// send to lower and return
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(deviceExtension->LowerDeviceObject,Irp);
}
As we can see, the code basically did nothing, just malloc a buffer , set every byte to 0x18 , copy to OutputBuffer of current IRP , then compare the data in pOutputBuffer with pJustTest immediately , and skip current irp stack , then pass irp to lower device.
But the code execute result was strange :
sometimes , after copy data to pOutputBuffer, the data in pOutputbuffer is diffrent from pJustTest. some range in the pOutputBuffer becames random values (not 0x18).
It doesn’t happen most of the time, only sometimes, and every times it happened, the readOffset in the irpStack->Parameters.Read.ByteOffset is same: 0xF8CE0000.
When it happened , I checked data in pJustTest , every byte in the buffer is correct. Just data in pOutputBuffer has been OVERWRITE.
In order to know the buffer was OVERWRITE by who, I had add some code to check whether the read offset is 0xF8CE0000, if is , then break to windbg, and set a memory write breakpoint with ba command in windbg : ba w1 poi(pOutputBuffer) . (and also tried ba w2 , ba w3, ba w4, ba w8)
But when the memcmp return a non-zero value , the break point only hit one times ( this time is caused by my own code, because I set break point before my memcpy)…
At first , I think maybe this is a hardware problem, caused by memory or disk error? So I had install the driver on my notebook, the issue still exists.
This is really unbeliveable, I had debug it for a week, I had no idea now.
Any one can help? Thanks very much!
More infomation:
- test on : vmware win7 64 sp1, with full patch. physical memory : 2GB. ( also test on 4GB 8GB and 16GB, always same )
- The DiskDrive health status is good, and I also test on my notebook(not virtual machine), result is almost same. (just read offset is not 0xF8CE0000)
- The flag of every deviceObjcect in the device stack has DO_DIRECT_IO set.
- I do nothing with the irp , just skip and send to lower device.
- I didn’t modify Irp->MDLAddress, just use MmGetSystemAddressForMdlSafe to get ouput buffer address.
- I tried install the driver as a Volume Filter ( ClassGUID: {71A27CDD-812A-11D0-BEC7-08002BE2092F}) , all code is totally same, the issue never appeared.
- When the available physical memory of the OS is insufficient, it happens more frequently. Maybe a same physical page been mapped to more than one virtual address? Or MmGetSystemAddressForMdlSafe returned wrong value?
- except IRP_MJ_READ, All other type of irp had send to lower device, I didn’t touch them.
- the code list here is meaningless, I just use the code to reproduce the issue. (My purpose is to write a disk cache driver)
- had test on other PC, result is same. (these PC has diffrent chipset, intel… amd…)
- ha test driver with microsoft driver verifier and run on checked build win7 , verifier detect nothing, no help.
If you need more infomation , please tell me, thanks !