オブジェクト ハンドルの検証失敗
一部のドライバーは、呼び出し元によって渡されたオブジェクトを操作するか、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 ドライバーの接続、ファイル システムのボリューム、ディレクトリ、ファイル オブジェクトなど) をサポートしている場合、それらを区別する方法があることを確認してください。