阅读:3980回复:12
如何在MjCreate中安全地关闭打开的fileobject?
osr上是这样说的:
IoCancelFileOpen is unsafe under any circumstances (the FAQ item should be changed) - there\'s a front page www.osronline.com article about this now. The alternative is to have your filter open its own reference to the file (either a handle with the Zw* APIs through shadow DO\'s or a file object created with IoCreateStreamFileObject* sent down on the original IRP_MJ_CREATE IRP), post-process, then close the reference and send down the original IRP with the original file object. 我下面的代码有没有问题,请大虾指点: KeInitializeEvent(); IoCopyCurrentIrpStackLocationToNext(); IoSetCompletionRoutine(); IoCallDriver(); KeWaitForSingleObject(); PFILE_OBJECT streamFileObject = NULL; try { streamFileObject = IoCreateStreamFileObject(IrpSp->FileObject, NULL); } except (STATUS_INSUFFICIENT_RESOURCES) { Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Irp->IoStatus.Status; } if (streamFileObject) { ObDereferenceObject(streamFileObject); } Irp->IoStatus.Status = STATUS_ACCESS_DENIED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Irp->IoStatus.Status; |
|
最新喜欢:ljmmar... |
沙发#
发布于:2004-01-15 06:52
http://www.osronline.com/article.cfm?id=219
|
|
板凳#
发布于:2004-01-15 13:47
http://www.osronline.com/article.cfm?id=219 打不开,:( |
|
地板#
发布于:2004-01-15 17:12
Everything Windows Driver Development there@citiz.net Thu, 15 Jan 2004 9764 members About This Site Hector\'s Memos The NT Insider The Basics File Systems The Online DDK Downloads ListServer Driver Jobs Store This Site NTDEV NTFSD WINDBG THE NT INSIDER Emerging Issues in IoCancelFileOpen The NT Insider, Vol 10, Issue 4, July-August 2003 | Published: 06-May-03| Modified: 27-Aug-03 At the April 2003 Microsoft IFS Plugfest an issue was identified that could arise when two file system filter drivers interact in an unexpected fashion during the processing of IRP_MJ_CREATE. This situation arises when the lower filter performs an IRP_MJ_READ or IRP_MJ_WRITE operation after the IRP_MJ_CREATE has been satisfied by the underlying file system and then the higher filter calls IoCancelFileOpen because it has decided to disallow the file open. What actually happens is that the lower filter\'s call will cause the virtual memory system (cache manager and memory manager) to increment the reference count of the file object passed in the IRP_MJ_READ. If this is the IRP_MJ_READ from the original IRP_MJ_CREATE, the reference count on that file object is incremented. When the higher filter calls IoCancelFileOpen the I/O Manager issues an IRP_MJ_CLEANUP and IRP_MJ_CLOSE down to the lower filter and then to the file system - as if the reference count had in fact dropped to zero. The higher filter then returns an error to the I/O Manager (or other OS component) and that component then discards the file object, even though there is a dangling reference from the virtual memory system. Thus, later when the virtual memory system releases its reference to the \"file object\" it is now acting on a potentially arbitrary location in memory. This can trigger random failures. In the initial analysis, Microsoft developers indicated that this appears to be a bug in IoCancelFileOpen and the way it is used within Windows. On further investigation, there does not appear to be a fix that can be made that would only affect IoCancelFileOpen to address 100% of the issues that can arise, but Microsoft developers are exploring this issue in search of a good solution. OSR developers have suggested that in fact this is a bug in the lower filter because it is never safe to perform a non-cached I/O call IRP_MJ_READ or IRP_MJ_WRITE with the file object from the IRP_MJ_CREATE. This is because some paths within the file system create fake (stack based) file objects in order to improve performance for operations that would not invoke the virtual memory system. Note: with NTFS, a non-cached I/O request is not honored in the case of compressed files. Other (third party) file systems may similarly ignore a request for non-cached I/O. At the present time our suggested work-around is for the filter to use IoCreateStreamFile, IoCreateStreamFileLite, or IoCreateStreamFileEx to create its own stream file object. This new stream file object may then be used when setting up the next I/O stack location in the IRP. The filter should then forward the IRP to the next driver synchoronously (this is normally done by blocking and waiting on a notification event that is set in the completion routine). The stream file object may then be used for IRP_MJ_READ and IRP_MJ_WRITE operations safely. When the filter is done using the stream file object, it may be dereferenced (potentially causing an IRP_MJ_CLEANUP and IRP_MJ_CLOSE) and Windows will delete it when appropriate. If the original create is to be allowed to proceed, the IRP can then be sent (with the original file object) to the underlying driver for further processing. Initial reports from developers are promising regarding this work around. Regardless, we know this is an emerging issue. Stay tuned for further information. Additional Information (May 9, 2003) Microsoft has indicated that the following calls may use stack-based file objects: NtDeleteFile NtQueryAttributesFile NtQueryFullAttributesFile IoFastQueryNetworkAttributes And that these fake file objects may appear for the following operations: IRP_MJ_CREATE IRP_MJ_CLEANUP IRP_MJ_CLOSE IRP_MJ_QUERY_INFORMATION FastIoQueryOpen FastIoQueryBasicInfo FastIoQueryStandardInfo FastIoQueryNetworkOpenInfo Further, the information from the Microsoft team indicates that this situation is unlikely to change in the forseeable future. The previously described solution remains OSR\'s suggested solution. Additional Information (July 10, 2003) The Microsoft filter driver team has provided an alternative solution as well: To work around this issue, the filter doing cached I/O to the file during IRP_MJ_CREATE processing should do the following: Check to see if the file object address is within the current stack limits (IoGetStackLimits) If the file object address is within the current stack limits, the filter should allocate its own file object (IoCreateStreamFileObject, or IoCreateStreamFileObjectLite), pass this stream file object down to the file system to be opened, then do the cached I/O against this file object. This is a well-formed file object which will be cleaned up safely if this is the file object referenced by either the cache manager or the memory manager. Here is the pseudo code for a filter that cancels create operations. In your IRP_MJ_CREATE dispatch routine, before the operation has been passed down to the file system, if this is a create that you may wish to cancel, do the following: // // Pseudo code assumptions: // // Variables: // NameToOpen |
|
|
地下室#
发布于:2004-01-16 09:28
感谢 wowocock !正在消化中...
|
|
5楼#
发布于:2004-01-16 09:40
继续请教: :D
DDK 中说: File system filter driver writers should note that IoCreateStreamFileObject causes an IRP_MJ_CLEANUP request to be sent to the file system driver stack for the volume. 请问IRP_MJ_CLEANUP是何时发出的,在IoCreateStreamFileObject中发出,还是后面调用ObDereferenceObject时发出?? |
|
6楼#
发布于:2004-03-25 16:02
osr上是这样说的: 重大bug,会bugcheck的 |
|
7楼#
发布于:2008-05-06 16:51
不错,正解之急
|
|
|
8楼#
发布于:2009-09-20 20:37
描述
在打开文件后根据条件决定是否关闭文件打开。 但是使用了IoCreateStreamFileObjectLite怎么去操作呢? SfCreate() { streamFileObject = IoCreateStreamFileObject(IrpSp->FileObject, NULL); IoCallDriver(streamFileObject ); if(可以打开文件) status = IoCallDriver(FileObject ); else status = STATUS_ACCESS_DENIED; ObDereferenceObject(streamFileObject); Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } 可是这样处理是错误的,一旦调用了status = IoCallDriver(FileObject ); 就发生: (368)SfRead : \Device\HarddiskVolume4 (\temp\temp1.txt) Access violation - code c0000005 (!!! second chance !!!) Fastfat!FatFsdRead+0x3e: f7c4c640 66813b0205 cmp word ptr [ebx],502h 错误 上面的SfCreate流程应该怎么处理? |
|
|
9楼#
发布于:2009-09-21 12:05
问题解决
|
|
|
驱动小牛
|
10楼#
发布于:2009-09-21 12:36
我贴一部分代码给你参考:
tempFileObject = IoCreateStreamFileObjectLite(NULL, VolumeDeviceObject); if (!tempFileObject) { ObDereferenceObject(tempFileObject); } ASSERT(tempFileObject); RtlZeroMemory(tempFileObject, sizeof(FILE_OBJECT)); tempFileObject->Type = IO_TYPE_FILE; tempFileObject->Size = sizeof(FILE_OBJECT); tempFileObject->DeviceObject = pStorage->VolumeDeviceObject; tempFileObject->Flags = FO_SYNCHRONOUS_IO; foBuffer = AllocatePool(NonPagedPool, MAX_PATH, __LINE__); RtlCopyMemory(foBuffer, usFullPath.Buffer + 2, usFullPath.Length - 2 * sizeof(WCHAR)); RtlInitUnicodeString(&tempFileObject->FileName, (PWCHAR)foBuffer); KeInitializeEvent(&tempFileObject->Lock, SynchronizationEvent, FALSE); KeInitializeEvent(&tempFileObject->Event, NotificationEvent, FALSE); //初始化irp irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (irp == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; __leave; } irp->MdlAddress = NULL; irp->Flags |= IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API; irp->RequestorMode = KernelMode; irp->UserIosb = &pWorkItem->IoStatus; irp->UserEvent = &pWorkItem->evUserEvent; irp->PendingReturned = FALSE; irp->Cancel = FALSE; irp->CancelRoutine = NULL; irp->Tail.Overlay.AuxiliaryBuffer = NULL; irp->Tail.Overlay.OriginalFileObject = tempFileObject; // 初始化安全属性 status = SeCreateAccessState( &pWorkItem->u.CREATE.accessState, &pWorkItem->u.CREATE.auxData, pWorkItem->u.CREATE.DesiredAccess, IoGetFileObjectGenericMapping()); if (!NT_SUCCESS(status)) { IoFreeIrp(irp); ObDereferenceObject(tempFileObject); __leave; } pWorkItem->u.CREATE.SecurityContext.SecurityQos = NULL; pWorkItem->u.CREATE.SecurityContext.AccessState = &pWorkItem->u.CREATE.accessState; pWorkItem->u.CREATE.SecurityContext.DesiredAccess = pWorkItem->u.CREATE.DesiredAccess; pWorkItem->u.CREATE.SecurityContext.FullCreateOptions = 0; //初始化IrpStack irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_CREATE; irpSp->Parameters.Create.SecurityContext = &pWorkItem->u.CREATE.SecurityContext; irpSp->Parameters.Create.Options = pIrpStack->Parameters.Create.Options; irpSp->Parameters.Create.FileAttributes = pIrpStack->Parameters.Create.FileAttributes; irpSp->Parameters.Create.ShareAccess = pIrpStack->Parameters.Create.ShareAccess; irpSp->Parameters.Create.EaLength = 0; pWorkItem->FileObject = tempFileObject; irpSp->FileObject = tempFileObject; irpSp->DeviceObject = pStorage->DeviceObject; IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE); pWorkItem->u.CREATE.pIrp = irp; status = IoCallDriver(pStorage->DeviceObject, pWorkItem->u.CREATE.pIrp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&pWorkItem->evUserEvent, Executive, KernelMode, TRUE, NULL); status = pWorkItem->IoStatus.Status; } ObReferenceObject(pWorkItem->FileObject); |
|
11楼#
发布于:2009-09-21 13:37
非常感谢yandong_8212 ,但我解本还是按照我上面提到流程去写了,但是不知道是否正确。
znsoft说osr上的说得方法会蓝屏,有过此类经验的人也给各说法阿。 |
|
|
驱动小牛
|
12楼#
发布于:2009-09-21 17:55
可能是计数问题,应该是CREATE成功了再DEREFER吧.或者自己REFER之后. 代码你就随便看看吧.
|
|