首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IoBuildAsynchronousFsdRequest与IRP_MJ_WRITE

IoBuildAsynchronousFsdRequest与IRP_MJ_WRITE
EN

Stack Overflow用户
提问于 2016-09-22 09:38:53
回答 2查看 451关注 0票数 2

我在磁盘驱动器上开发了一个WDM过滤器驱动程序。我想发送一个在磁盘上写入数据的异步请求。当我删除writeBuffer函数中的WriteDataIRPCompletion内存时,窗口就会崩溃。

我的问题是:如何在不崩溃的情况下安全地释放writeBuffer内存?

这是我的发送请求代码:

代码语言:javascript
复制
#pragma PAGEDCODE
NTSTATUS WriteToDeviceRoutine() {
    PMYDRIVER_WRITE_CONTEXT context = (PMYDRIVER_WRITE_CONTEXT)ExAllocatePool(NonPagedPool,sizeof(PMYDRIVER_WRITE_CONTEXT));
    context->writeBuffer = new(NonPagedPool) unsigned char[4096];

    PIRP pNewIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE,
         pdx->LowerDeviceObject,
         context->writeBuffer,(wroteRecordNodeCount<<SHIFT_BIT),
         &startingOffset,NULL);
   IoSetCompletionRoutine(pNewIrp,WriteDataIRPCompletion,context,TRUE,TRUE,TRUE);
   IoCallDriver(pdx->LowerDeviceObject,pNewIrp);
}

这是我的完成例程代码:

代码语言:javascript
复制
#pragma LOCKEDCODE
NTSTATUS WriteDataIRPCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP driverIrp,IN PVOID Context) {
   PMDL mdl,nextMdl;
   KdPrint((" WriteDataIRPCompletion \n"));
   PMYDRIVER_WRITE_CONTEXT writeContext = (PMYDRIVER_WRITE_CONTEXT) Context;
   if(driverIrp->MdlAddress!=NULL){
      for(mdl=driverIrp->MdlAddress;mdl!=NULL;mdl = nextMdl) {
         nextMdl = mdl->Next;
         MmUnlockPages(mdl);
         IoFreeMdl(mdl);
         KdPrint(("mdl clear\n"));
     }
     driverIrp->MdlAddress = NULL;
   }
   delete [] writeContext->writeBuffer;
   if(Context)
      ExFreePool(Context);

    KdPrint(("leave WriteDataIRPCompletion \n"));
    return STATUS_CONTINUE_COMPLETION;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-17 23:42:15

下一行出错

代码语言:javascript
复制
context = ExAllocatePool(NonPagedPool,sizeof(PMYDRIVER_WRITE_CONTEXT));

一定是什么时候

代码语言:javascript
复制
context = ExAllocatePool(NonPagedPool,sizeof(MYDRIVER_WRITE_CONTEXT));

不是sizeof(PMYDRIVER_WRITE_CONTEXT),而是sizeof(MYDRIVER_WRITE_CONTEXT),您分配的不是结构,而是指向它的指针。

这仅在MYDRIVER_WRITE_CONTEXT包含单个字段writeBuffer而不包含更多数据时才会产生错误。否则,您将覆盖已分配的内存(仅为相当大的内存(PVOID)),并创建错误。

以及IoBuildAsynchronousFsdRequest的完成情况。不幸的是,文档不是很好。在这里满足了

在调用IoFreeIrp之前,如果以下所有内容都是正确的,则需要另外一步来释放由IoBuildAsynchronousFsdRequest生成的IRP缓冲区: 缓冲区是从系统内存池中分配的。

但之后所有的注意力

Irp->MdlAddress字段是非空的。

然而,我们必须检查和IRP_DEALLOCATE_BUFFER|IRP_BUFFERED_IO,没有这一点,我们可以泄漏Irp->AssociatedIrp.SystemBuffer。需要下一段代码

代码语言:javascript
复制
if (Irp->Flags & IRP_BUFFERED_IO)
{
    if (Irp->Flags & IRP_INPUT_OPERATION)
    {
        if (!NT_ERROR(Irp->IoStatus.Status) && Irp->IoStatus.Information)
        {
            memcpy( Irp->UserBuffer, Irp->AssociatedIrp.SystemBuffer, Irp->IoStatus.Information );
        }
    }

    if (Irp->Flags & IRP_DEALLOCATE_BUFFER)
    {
        ExFreePool(Irp->AssociatedIrp.SystemBuffer);
        Irp->AssociatedIrp.SystemBuffer = 0;
    }

    Irp->Flags &= ~(IRP_DEALLOCATE_BUFFER|IRP_BUFFERED_IO);
}

并检查if (writeContext) 使用writeContext->writeBuffer后已经失去意义和无意义。您真的需要在context != NULL中检查WriteToDeviceRoutine()

票数 0
EN

Stack Overflow用户

发布于 2016-09-22 09:58:11

我不太熟悉你在做什么的细节,下面是一些引起我注意的细节。

WriteDataIRPCompletion函数

PMYDRIVER_WRITE_CONTEXT writeContext = (PMYDRIVER_WRITE_CONTEXT)上下文;// .删除[]写上下文->写缓冲区;如果(上下文)ExFreePool(上下文);

注意,您的writeContext来自于Context参数。但是,您似乎要删除/释放分配的内存两次。

ExFreePool函数文档状态:

指定要释放的池内存块的地址。

看起来,delete [] writeContext->writeBuffer;行可能导致了问题,只需要删除它。

就像现在一样,函数应该是freed的部分内存在调用ExFreePool时已经是手动的deleted,但没有设置为,这反过来又导致ExFreePoolContext参数中接收到一个现在无效的指针(即指向非分配内存的非空指针),从而导致崩溃。

WriteToDeviceRoutine函数

ExFreePool的文档显式地声明它释放与其他函数(如ExAllocatePool和其他朋友)一起分配的内存。

但是,您的代码试图分别使用writeContext->writeBuffer /delete运算符直接分配/释放new。似乎您应该使用ExAllocatePool分配内存,然后使用ExFreePool进行释放,而不是像这样手动地执行操作。

这些函数可能是以一种特定的方式组织内存的,如果/当在ExFreePool中不满足这个预条件时,它可能会崩溃。

另外,似乎奇怪的是,在调用if(Context)之前检查ExFreePool是空的,但在尝试为本地writeContext变量键入强制转换并使用它之前就不是这样了。

也许你也应该在第一个使用点检查一下?如果Context总是非空的,那么在调用ExFreePool之前,检查可能也是不必要的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39635484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档