一部のドライバーは、呼び出し元によって渡されたオブジェクトを操作するか、2 つのファイル オブジェクトを同時に処理する必要があります。 たとえば、モデム ドライバーがイベント オブジェクトへのハンドルを受け取る場合や、ネットワーク ドライバーが 2 つの異なるファイル オブジェクトへのハンドルを受け取る場合があります。 ドライバーは、これらのハンドルを検証する必要があります。 I/O マネージャーではなく呼び出し元によって渡されるため、I/O マネージャーは検証チェックを実行できません。
たとえば、次のコード スニペットでは、ドライバーは ハンドル AscInfo->AddressHandle を渡されていますが、 ObReferenceObjectByHandle を呼び出す前に検証していません。
//
// This handle is embedded in a buffered request.
//
status = ObReferenceObjectByHandle(
AscInfo->AddressHandle,
0,
NULL,
KernelMode,
&fileObject,
NULL);
if (NT_SUCCESS(status)) {
if ( (fileObject->DeviceObject == DeviceObject) &&
(fileObject->FsContext2 == TRANSPORT_SOCK) ) {
ObReferenceObjectByHandle の呼び出しは成功しますが、返されたポインターがファイル オブジェクトを参照していることを確認できません。正しい情報を渡すために呼び出し元を信頼します。
ObReferenceObjectByHandle への呼び出しのすべてのパラメーターが正しく、呼び出しが成功した場合でも、ドライバーは、ファイル オブジェクトがそのドライバーを対象としていない場合は、予期しない結果を取得できます。 次のコード フラグメントでは、ドライバーは、正常な呼び出しが予期したファイル オブジェクトへのポインターを返すと想定しています。
status = ObReferenceObjectByHandle (
AcpInfo->Handle,
0L,
DesiredAccess,
*IoFileObjectType,
Irp->RequestorMode,
(PVOID *)&AcpEndpointFileObject,
NULL);
if ( !NT_SUCCESS(status) ) {
goto complete;
}
AcpEndpoint = AcpEndpointFileObject->FsContext;
if ( AcpEndpoint->Type != BlockTypeEndpoint )
ObReferenceObjectByHandle はファイル オブジェクトへのポインターを返しますが、ドライバーはポインターが予期したファイル オブジェクトを参照する保証はありません。 この場合、ドライバーは、 AcpEndpointFileObject->FsContext でドライバー固有のデータにアクセスする前にポインターを検証する必要があります。
このような問題を回避するには、次のように、ドライバーが有効なデータを確認する必要があります。
オブジェクトの種類を調べて、ドライバーが期待するオブジェクトであることを確認します。
要求されたアクセスがオブジェクトの種類と必要なタスクに適していることを確認します。 たとえば、ドライバーが高速ファイル コピーを実行する場合は、ハンドルに読み取りアクセス権があることを確認します。
正しいアクセス モード (UserMode または KernelMode) を指定し、アクセス モードが要求されたアクセスと互換性があることを確認してください。
ドライバー自体が作成したファイル オブジェクトへのハンドルがドライバーに必要な場合は、デバイス オブジェクトまたはドライバーに対してハンドルを検証します。 ただし、奇妙なデバイスの I/O 要求を送信するフィルターを中断しないように注意してください。
ドライバーが複数の種類のファイル オブジェクト (コントロール チャネル、アドレス オブジェクト、TDI ドライバーの接続、ファイル システムのボリューム、ディレクトリ、ファイル オブジェクトなど) をサポートしている場合は、それらを区別する方法があることを確認してください。