mapping user space to kernel

In my routine to handle deferred processing in the post op handler for IR_MJ_DIRECTORY_CONTROL I’m having a problem with the case where the MdlAddress == 0 and FLT_IS_SYSTEM_BUFFER () is false.

I call FltLockUserBuffer() , then MmGetSystemAddressForMdlSafe(). but the return from it is sometimes garbage . Needless to say, when this occurs , I crash.

As you can see in the comments, I’ve copied the documetation provided about accessing user buffers in post op operations and I think I’m doing this correctly.

Questions might be the legitimacy of doing this in the Deferred work item vs. the dispatched routine, but I don’t think that is a problem.

Other questions would be about using try/except blocks around the accesses to the buffers or maybe buffers should be further probedandlocked ? The doc’s don’t indicate that this is necessary.

Any ideas?

TIA

Larry

void SafePostDirectoryControl( IN PFLT_DEFERRED_IO_WORKITEM FltWorkItem,
IN PFLT_CALLBACK_DATA Data,
IN PVOID Context
)
{

NTSTATUS Status;
RDM_STATUS RDM_Status;

FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
PVOID DirectoryBuffer =0;
ULONG RDMState;
int DataHasBeenModified = 0;
UCHAR MinorFunction;
PUNICODE_STRING FileName;
ULONG Length;
PRDMInstanceContext pIC;
PVOID UserDirectoryBuffer ;
PMDL MdlAddress;
DirControlContext * pDirControl = (DirControlContext*) Context;
HANDLE DirectoryHandle = 0;
UNICODE_STRING DirPath;

pIC = pDirControl->pIC;
FileName = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName;
FileInformationClass = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass;
UserDirectoryBuffer = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;
MdlAddress = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress;

/* see “Accessing User Buffers in a Postoperation Callback Routine” in the IFS Documents

If an MDL exists for the buffer, call MmGetSystemAddressForMdlSafe
to obtain the system address for the buffer.
(This routine can be called at IRQL <= DISPATCH_LEVEL.) Use the system address to access the buffer.
*/
if(MdlAddress != 0)
{
DebugTrace(DEBUG_TRACE_IRPS,“[PostOp DirControl] Mdl != 0 \n " );
Status = FltLockUserBuffer(Data);
if(NT_SUCCESS(Status))
DirectoryBuffer = MmGetSystemAddressForMdlSafe(MdlAddress,NormalPagePriority);
}
else
{/*If there is no MDL for the buffer, check whether the system
buffer flag is set for the operation by using the FLT_IS_SYSTEM_BUFFER macro.
*/
DebugTrace(DEBUG_TRACE_IRPS,”[PostOp DirControl] Mdl == 0 \n " );
if (FLT_IS_SYSTEM_BUFFER(Data))
{/*If the FLT_IS_SYSTEM_BUFFER macro returns TRUE, the
operation uses buffered I/O, and the buffer can safely be accessed at IRQL DISPATCH_LEVEL*/
DebugTrace(DEBUG_TRACE_IRPS,“[PostOp DirControl] DirectoryBuffer is system buffer != 0 \n " );
DirectoryBuffer = UserDirectoryBuffer;
}
else
{/*If the FLT_IS_SYSTEM_BUFFER macro returns FALSE,
the buffer cannot safely be accessed at IRQL DISPATCH_LEVEL.
If the postoperation callback routine can be called at DISPATCH_LEVEL,
it must call FltDoCompletionProcessingWhenSafe to pend the operation until
it can be processed at IRQL <= APC_LEVEL. The SafePostCallback routine
should first call FltLockUserBuffer to lock the buffer and
then call MmGetSystemAddressForMdlSafe to obtain the system address for the buffer.
*/
DebugTrace(DEBUG_TRACE_IRPS,”[PostOp DirControl]Try to allocate Mdl == 0 , !System buffer \n " );
Status = FltLockUserBuffer(Data);
if(NT_SUCCESS(Status))
{MdlAddress = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress;
DirectoryBuffer = MmGetSystemAddressForMdlSafe(MdlAddress,NormalPagePriority);
DebugTrace(DEBUG_TRACE_IRPS,"[PostOp DirControl]allocated Mdl != 0 \n " );

}
}
}

… now that I’ve got a buffer, go do some work.


cleanup
}

>Questions might be the legitimacy of doing this in the Deferred work item vs.

the dispatched routine, but I don’t think that is a problem.

You need to call FltLockUserBuffer in the same process context which issued the original IO. Doing it in the Deferred work item in a different process cirtainly is a problem.

Alexei.

I think you just need to call FltLockUserBuffer and then MmGetSystemAddressForMdlSafe. FltLockUserBuffer function creates MdlAddress for you. I do not think you need to check for FLT_IS_SYSTEM_BUFFER at SafePostCallback. All the checks should be done in PostCallback.

Please correct if me I am wrong.

Alexei,

From IFS doc:

The caller can be running in any process context. FltLockUserBuffer automatically locks the buffer in the correct process context.