Extracting TCP connection endpoints from RxContext - possible?

Given an instance of an RxContext structure passed between rdbss.sys
and mrxsmb.sys, is it possible to figure out the endpoints of a TCP
connection that carries the corresponding SMB traffic?

Thanks,

Alex


typedef struct _RX_CONTEXT {

//
// the node type, size and reference count, aka standard header
//

NODE_TYPE_CODE NodeTypeCode;
NODE_BYTE_SIZE NodeByteSize;
ULONG ReferenceCount;

//
// the list entry to wire the context to the list of active contexts
//

LIST_ENTRY ContextListEntry;

//
// Major and minor function of the IRP associated with the context
//

UCHAR MajorFunction;
UCHAR MinorFunction;

//
// this is similar to the same field in Irps; it
// allows callback routines for async operations
// to know whether to do asynchronous work or not
//

BOOLEAN PendingReturned;

//
// indicates if the associated request is to be posted to a RDBSS
worker thread.
//

BOOLEAN PostRequest;

//
// Originating Device (required for workque algorithms)
// not currently used but could be used for local minis
//

PDEVICE_OBJECT RealDevice;

//
// ptr to the originating Irp
//

PIRP CurrentIrp;

//
// ptr to the IRP stack location
//

PIO_STACK_LOCATION CurrentIrpSp;

//
// ptr to the FCB and FOBX, derived from the context pointers in the
// file object associated with the IRP
//

PMRX_FCB pFcb;
PMRX_FOBX pFobx;
PMRX_SRV_OPEN pRelevantSrvOpen;
PNON_PAGED_FCB NonPagedFcb;

//
// device object calldown (not irpsp…)
//

PRDBSS_DEVICE_OBJECT RxDeviceObject;

//
// The original thread in which the request was initiated and the last
// thread in which some processing associated with the context was done
//

PETHREAD OriginalThread;
PETHREAD LastExecutionThread;

PVOID LockManagerContext;

//
// One word of the context is given to rdbss for dbg information
//

PVOID RdbssDbgExtension;

RX_SCAVENGER_ENTRY ScavengerEntry;

//
// global serial number for this operation
//

ULONG SerialNumber;

//
// used by minirdrs to see if multiple calls are part
// of the same larger operation and (therefore) more cacheable
//

ULONG FobxSerialNumber;

ULONG Flags;

BOOLEAN FcbResourceAcquired;
BOOLEAN FcbPagingIoResourceAcquired;
UCHAR MustSucceedDescriptorNumber;

//
// mostly you want the individual components…sometimes it’s
nice as a pair
// used to record the status when you can’t just return it; e.g., when
// RXSTATUS is not an appropriate return type or if the consumer of the
// status didn’t call directly (lowiocompletions). minirdrs will not need
// to set the information directly
//

union {
struct {
union {
NTSTATUS StoredStatus;
PVOID StoredStatusAlignment;
};
ULONG_PTR InformationToReturn;
};
IO_STATUS_BLOCK IoStatusBlock;
};

//
// the context fields provided for use by the mini redirectors
// this is defined as a union to force longlong alignment
//

union {
ULONGLONG ForceLonglongAligmentDummyField;
PVOID MRxContext[MRX_CONTEXT_FIELD_COUNT];
};

//
// The following field is included to fix the problem related to write only
// opens. This introduces a new field for the mini redirector to squirrel
// some state. This is redundant and should be removed after Windows 2000.
// Having a unique field reduces the impact of the change that we
are making
// to the specific code path. It will be ideal to use one of the MRXContext
// fields defined above
//

PVOID WriteOnlyOpenRetryContext;

//
// the cancellation routine to be invoked, set by the mini redirector
//

PMRX_CALLDOWN MRxCancelRoutine;

//
// private dispatch, if any. used in fspdisp
//

PRX_DISPATCH ResumeRoutine;

//
// for posting to worker threads
// the minirdr can use this for posting within the minirdr
// a potential problem can arise if the minirdr relies on this both
// for queueing async stuff and for queueing cancel stuff
//

//
// The OverflowListEntry is used for queueing items to the overflow queue.
// This is seperate now to allow us to distinguish between an
item in the overflow
// queue and one in the active work queue (for cancellation logic)
//

RX_WORK_QUEUE_ITEM WorkQueueItem;
LIST_ENTRY OverflowListEntry;

//
// this event is used for synchronous operations
// that have to i/f with an underlying async service. it can be used
// by the minirdr with the following provisions:
// 1) on entering the minirdr through lowio, it is set to the
// nonsignaled state (but a wise user will reset it before using
// it…particularly if it’s used multiple times.
// 2) if you are returning STATUS_PENDING on a sync operation, you must
// return with it set to the nonsignaled state; that is, either
// you don’t use it or you reset it in this case
//

KEVENT SyncEvent;

//
// this is a list head of operations that are to be released on completion
//

LIST_ENTRY BlockedOperations;

//
// this is the mutex that controls serialization of the blocked operations
//

PFAST_MUTEX BlockedOpsMutex;

//
// these links are used to serialize pipe operations on a
// per-file-object basis AND FOR LOTS OF OTHER STUFF
//

LIST_ENTRY RxContextSerializationQLinks;

union {
struct {
union {
FS_INFORMATION_CLASS FsInformationClass;
FILE_INFORMATION_CLASS FileInformationClass;
};
PVOID Buffer;
union {
LONG Length;
LONG LengthRemaining;
};
BOOLEAN ReplaceIfExists;
BOOLEAN AdvanceOnly;
} Info;

struct {
UNICODE_STRING SuppliedPathName;
NET_ROOT_TYPE NetRootType;
PIO_SECURITY_CONTEXT pSecurityContext;
} PrefixClaim;
};

//
// THIS UNION MUST BE LAST…AT SOME POINT, WE MAY START ALLOCATING
// SMALLER PER OPERATION!
//

union{
struct {
NT_CREATE_PARAMETERS NtCreateParameters; // a copy of the
createparameters
ULONG ReturnedCreateInformation;
PWCH CanonicalNameBuffer; // if the canonical name is
larger than available buffer
PRX_PREFIX_ENTRY NetNamePrefixEntry; // the entry
returned by the lookup…for dereferencing

PMRX_SRV_CALL pSrvCall; // Server Call being used
PMRX_NET_ROOT pNetRoot; // Net Root being used
PMRX_V_NET_ROOT pVNetRoot; // Virtual Net Root
//PMRX_SRV_OPEN pSrvOpen; // Server Open

PVOID EaBuffer;
ULONG EaLength;

ULONG SdLength;

ULONG PipeType;
ULONG PipeReadMode;
ULONG PipeCompletionMode;

USHORT Flags;
NET_ROOT_TYPE Type; // Type of Net
Root(Pipe/File/Mailslot…)

BOOLEAN FcbAcquired;
BOOLEAN TryForScavengingOnSharingViolation;
BOOLEAN ScavengingAlreadyTried;

BOOLEAN ThisIsATreeConnectOpen;
BOOLEAN TreeConnectOpenDeferred;
UNICODE_STRING TransportName;
UNICODE_STRING UserName;
UNICODE_STRING Password;
UNICODE_STRING UserDomainName;
} Create;
struct {
ULONG FileIndex;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
BOOLEAN InitialQuery;
} QueryDirectory;
struct {
PMRX_V_NET_ROOT pVNetRoot;
} NotifyChangeDirectory;
struct {
PUCHAR UserEaList;
ULONG UserEaListLength;
ULONG UserEaIndex;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
} QueryEa;
struct {
SECURITY_INFORMATION SecurityInformation;
ULONG Length;
} QuerySecurity;
struct {
SECURITY_INFORMATION SecurityInformation;
PSECURITY_DESCRIPTOR SecurityDescriptor;
} SetSecurity;
struct {
ULONG Length;
PSID StartSid;
PFILE_GET_QUOTA_INFORMATION SidList;
ULONG SidListLength;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
} QueryQuota;
struct {
ULONG Length;

} SetQuota;
struct {
PV_NET_ROOT VNetRoot;
PSRV_CALL SrvCall;
PNET_ROOT NetRoot;
} DosVolumeFunction;
struct {
ULONG FlagsForLowIo;
LOWIO_CONTEXT LowIoContext; // the LOWIO parameters
}; // no name here…
LUID FsdUid;
} ;

//
// CODE.IMPROVEMENT remove this to wrapperdbgprivates
//

PWCH AlsoCanonicalNameBuffer; // if the canonical name is larger
than available buffer
PUNICODE_STRING LoudCompletionString;

#ifdef RDBSS_TRACKER
LONG AcquireReleaseFcbTrackerX;
ULONG TrackerHistoryPointer;
RX_FCBTRACKER_CALLINFO TrackerHistory[RDBSS_TRACKER_HISTORY_SIZE];
#endif

#if DBG
ULONG ShadowCritOwner;
#endif

} RX_CONTEXT, *PRX_CONTEXT;

Well, it is hard to answer definitively that you can’t do
something… but I’d say, “Probably not.”

The reason is that rdbss.sys (which is the component
that declares the RxContext struct) knows nothing
about the underlying filesystem protocol (implemented
in this case by mrxsmb.sys.)

Other mini-redirectors also use rdbss (though they link
it statically, the static library is compiled of the
same code base as the .sys) Some of these filesystems
bounce the requests down to user mode for processing
(I believe the webdav redirector does this.)

The point I’m trying to make is that the connection
end point (if there even is one) is private data
to mrxsmb.sys… not part of the interface between
rdbss.sys and whatever.

So, it is only possible to get from the RxContext to
the end-point information if you know about mrxsmb.sys’s
internal private data structures (such as it’s SrvCall
extension.)

  • Joseph

Alex Barkan wrote:

Given an instance of an RxContext structure passed between rdbss.sys
and mrxsmb.sys, is it possible to figure out the endpoints of a TCP
connection that carries the corresponding SMB traffic?

Thanks,

Alex


typedef struct _RX_CONTEXT {

//
// the node type, size and reference count, aka standard header
//

NODE_TYPE_CODE NodeTypeCode;
NODE_BYTE_SIZE NodeByteSize;
ULONG ReferenceCount;

//
// the list entry to wire the context to the list of active contexts
//

LIST_ENTRY ContextListEntry;

//
// Major and minor function of the IRP associated with the context
//

UCHAR MajorFunction;
UCHAR MinorFunction;

//
// this is similar to the same field in Irps; it
// allows callback routines for async operations
// to know whether to do asynchronous work or not
//

BOOLEAN PendingReturned;

//
// indicates if the associated request is to be posted to a RDBSS
worker thread.
//

BOOLEAN PostRequest;

//
// Originating Device (required for workque algorithms)
// not currently used but could be used for local minis
//

PDEVICE_OBJECT RealDevice;

//
// ptr to the originating Irp
//

PIRP CurrentIrp;

//
// ptr to the IRP stack location
//

PIO_STACK_LOCATION CurrentIrpSp;

//
// ptr to the FCB and FOBX, derived from the context pointers in the
// file object associated with the IRP
//

PMRX_FCB pFcb;
PMRX_FOBX pFobx;
PMRX_SRV_OPEN pRelevantSrvOpen;
PNON_PAGED_FCB NonPagedFcb;

//
// device object calldown (not irpsp…)
//

PRDBSS_DEVICE_OBJECT RxDeviceObject;

//
// The original thread in which the request was initiated and the last
// thread in which some processing associated with the context was done
//

PETHREAD OriginalThread;
PETHREAD LastExecutionThread;

PVOID LockManagerContext;

//
// One word of the context is given to rdbss for dbg information
//

PVOID RdbssDbgExtension;

RX_SCAVENGER_ENTRY ScavengerEntry;

//
// global serial number for this operation
//

ULONG SerialNumber;

//
// used by minirdrs to see if multiple calls are part
// of the same larger operation and (therefore) more cacheable
//

ULONG FobxSerialNumber;

ULONG Flags;

BOOLEAN FcbResourceAcquired;
BOOLEAN FcbPagingIoResourceAcquired;
UCHAR MustSucceedDescriptorNumber;

//
// mostly you want the individual components…sometimes it’s
nice as a pair
// used to record the status when you can’t just return it; e.g., when
// RXSTATUS is not an appropriate return type or if the consumer of the
// status didn’t call directly (lowiocompletions). minirdrs will not need
// to set the information directly
//

union {
struct {
union {
NTSTATUS StoredStatus;
PVOID StoredStatusAlignment;
};
ULONG_PTR InformationToReturn;
};
IO_STATUS_BLOCK IoStatusBlock;
};

//
// the context fields provided for use by the mini redirectors
// this is defined as a union to force longlong alignment
//

union {
ULONGLONG ForceLonglongAligmentDummyField;
PVOID MRxContext[MRX_CONTEXT_FIELD_COUNT];
};

//
// The following field is included to fix the problem related to write only
// opens. This introduces a new field for the mini redirector to squirrel
// some state. This is redundant and should be removed after Windows 2000.
// Having a unique field reduces the impact of the change that we
are making
// to the specific code path. It will be ideal to use one of the MRXContext
// fields defined above
//

PVOID WriteOnlyOpenRetryContext;

//
// the cancellation routine to be invoked, set by the mini redirector
//

PMRX_CALLDOWN MRxCancelRoutine;

//
// private dispatch, if any. used in fspdisp
//

PRX_DISPATCH ResumeRoutine;

//
// for posting to worker threads
// the minirdr can use this for posting within the minirdr
// a potential problem can arise if the minirdr relies on this both
// for queueing async stuff and for queueing cancel stuff
//

//
// The OverflowListEntry is used for queueing items to the overflow queue.
// This is seperate now to allow us to distinguish between an
item in the overflow
// queue and one in the active work queue (for cancellation logic)
//

RX_WORK_QUEUE_ITEM WorkQueueItem;
LIST_ENTRY OverflowListEntry;

//
// this event is used for synchronous operations
// that have to i/f with an underlying async service. it can be used
// by the minirdr with the following provisions:
// 1) on entering the minirdr through lowio, it is set to the
// nonsignaled state (but a wise user will reset it before using
// it…particularly if it’s used multiple times.
// 2) if you are returning STATUS_PENDING on a sync operation, you must
// return with it set to the nonsignaled state; that is, either
// you don’t use it or you reset it in this case
//

KEVENT SyncEvent;

//
// this is a list head of operations that are to be released on completion
//

LIST_ENTRY BlockedOperations;

//
// this is the mutex that controls serialization of the blocked operations
//

PFAST_MUTEX BlockedOpsMutex;

//
// these links are used to serialize pipe operations on a
// per-file-object basis AND FOR LOTS OF OTHER STUFF
//

LIST_ENTRY RxContextSerializationQLinks;

union {
struct {
union {
FS_INFORMATION_CLASS FsInformationClass;
FILE_INFORMATION_CLASS FileInformationClass;
};
PVOID Buffer;
union {
LONG Length;
LONG LengthRemaining;
};
BOOLEAN ReplaceIfExists;
BOOLEAN AdvanceOnly;
} Info;

struct {
UNICODE_STRING SuppliedPathName;
NET_ROOT_TYPE NetRootType;
PIO_SECURITY_CONTEXT pSecurityContext;
} PrefixClaim;
};

//
// THIS UNION MUST BE LAST…AT SOME POINT, WE MAY START ALLOCATING
// SMALLER PER OPERATION!
//

union{
struct {
NT_CREATE_PARAMETERS NtCreateParameters; // a copy of the
createparameters
ULONG ReturnedCreateInformation;
PWCH CanonicalNameBuffer; // if the canonical name is
larger than available buffer
PRX_PREFIX_ENTRY NetNamePrefixEntry; // the entry
returned by the lookup…for dereferencing

PMRX_SRV_CALL pSrvCall; // Server Call being used
PMRX_NET_ROOT pNetRoot; // Net Root being used
PMRX_V_NET_ROOT pVNetRoot; // Virtual Net Root
//PMRX_SRV_OPEN pSrvOpen; // Server Open

PVOID EaBuffer;
ULONG EaLength;

ULONG SdLength;

ULONG PipeType;
ULONG PipeReadMode;
ULONG PipeCompletionMode;

USHORT Flags;
NET_ROOT_TYPE Type; // Type of Net
Root(Pipe/File/Mailslot…)

BOOLEAN FcbAcquired;
BOOLEAN TryForScavengingOnSharingViolation;
BOOLEAN ScavengingAlreadyTried;

BOOLEAN ThisIsATreeConnectOpen;
BOOLEAN TreeConnectOpenDeferred;
UNICODE_STRING TransportName;
UNICODE_STRING UserName;
UNICODE_STRING Password;
UNICODE_STRING UserDomainName;
} Create;
struct {
ULONG FileIndex;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
BOOLEAN InitialQuery;
} QueryDirectory;
struct {
PMRX_V_NET_ROOT pVNetRoot;
} NotifyChangeDirectory;
struct {
PUCHAR UserEaList;
ULONG UserEaListLength;
ULONG UserEaIndex;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
} QueryEa;
struct {
SECURITY_INFORMATION SecurityInformation;
ULONG Length;
} QuerySecurity;
struct {
SECURITY_INFORMATION SecurityInformation;
PSECURITY_DESCRIPTOR SecurityDescriptor;
} SetSecurity;
struct {
ULONG Length;
PSID StartSid;
PFILE_GET_QUOTA_INFORMATION SidList;
ULONG SidListLength;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
} QueryQuota;
struct {
ULONG Length;

} SetQuota;
struct {
PV_NET_ROOT VNetRoot;
PSRV_CALL SrvCall;
PNET_ROOT NetRoot;
} DosVolumeFunction;
struct {
ULONG FlagsForLowIo;
LOWIO_CONTEXT LowIoContext; // the LOWIO parameters
}; // no name here…
LUID FsdUid;
} ;

//
// CODE.IMPROVEMENT remove this to wrapperdbgprivates
//

PWCH AlsoCanonicalNameBuffer; // if the canonical name is larger
than available buffer
PUNICODE_STRING LoudCompletionString;

#ifdef RDBSS_TRACKER
LONG AcquireReleaseFcbTrackerX;
ULONG TrackerHistoryPointer;
RX_FCBTRACKER_CALLINFO TrackerHistory[RDBSS_TRACKER_HISTORY_SIZE];
#endif

#if DBG
ULONG ShadowCritOwner;
#endif

} RX_CONTEXT, *PRX_CONTEXT;


Questions? First check the IFS FAQ at https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@vandyke.com
To unsubscribe send a blank email to xxxxx@lists.osr.com