このブログは、株式会社フィックスターズのエンジニアが、あらゆるテーマについて自由に書いているブログです。
これまで「Windowsデバイスドライバの基本動作を確認する」などでWindowsのカーネルモードデバイスドライバに関するBlog記事を書いてきましたが、ここからは具体的な用途をもつデバイスドライバを題材として、Windowsデバイスドライバに関連する技術調査を行った結果を紹介していこうと思います。
今回は、WDK (Windows Driver Kit) のサンプルデバイスドライバに含まれているRAMDiskドライバを動かしてみるとともに、一部修正を加えることでドライバの挙動がどう変化するかを調査した結果について報告します。
このドライバは、WDF (Windows Driver Foundation) の KMDF (Kernel Mode Driver Framework) に基づくドライバで、それ自身が FAT (File Allocation Table) のファイルシステムを構築してRAMDiskとして動作するようになっており、レジストリで以下のパラメータを設定することができます。
サンプルRAMDiskドライバのインストールは、このドライバの説明に記載されているとおり、WDK付属のアプリケーションである Windows Device Console (devcon) を使って、以下の手順で行いました。
C:\Setup\WdfRamdisk>devcon install ramdisk.inf ramdisk
Device node created. Install is complete when drivers are installed...
Updating drivers for ramdisk from C:\Setup\WdfRamdisk\ramdisk.inf.
Drivers installed successfully.
デバイスマネージャを開くと、デバイスが追加されている様子を確認することができます。
しかし、エクスプローラを起動してもRAMDiskのドライブ (“R:”) が見えません。Administratorとしてコマンドプロンプトを起動してみると、Rドライブに移動して、その下にファイルを作ったり、ファイルの中身を参照したりすることができますが、一般ユーザの権限でコマンドプロンプトを起動しただけでは、Rドライブにアクセスすることはできません。
Windowsのデバイスドライバは、デバイスを管理するデータ構造であるデバイスオブジェクトを生成するために IoCreateDevice() 関数を使用しますが、この関数で生成されたデバイスオブジェクトの使用は制限されており、Administratorしかアクセスすることができません。デバイスオブジェクトへのアクセス権限を変更するためには、IoCreateDeviceSecure() 関数を用いてデバイスオブジェクトを生成し、その際、誰からのどのようなアクセスを許可するかを SDDL (Security Description Definition Language) という文字列によって指定する必要があります。
今回使用したWDKのサンプルRAMDiskドライバは、KMDFベースのドライバなので、IoCreateDeviceSecure()を直接呼び出すわけではなく、KMDFのデバイスクラスのインスタンスを生成する際に、以下のような形で WdfDeviceInitAssignSDDLString() 関数を用いてSDDLを指定します。
// SDDLを指定
WdfDeviceInitAssignSDDLString(DeviceInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
// デバイスオブジェクトを生成
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
WDK提供のヘッダファイルwdmsec.hには、よく使うSDDLの文字列が定義されています。今回は、以下の5種類のSDDLについて、それを指定したときにデバイスに対するアクセスがどのように変化するか、ユーザ見えの挙動の変化を調査しました。
上のSDDLを使用し、以下の(1) ~ (5)の操作に対する挙動を確認した結果を以下に示します。
SDDL | (1) | (2) | (3) | (4) | (5) |
---|---|---|---|---|---|
SDDL_DEVOBJ_KERNEL_ONLY | × | × | n/a | n/a | n/a |
SDDL_DEVOBJ_SYS_ALL | × | 〇 | n/a | n/a | n/a |
SDDL_DEVOBJ_SYS_ALL_ADM_ALL | 〇 | 〇 | × | n/a | n/a |
SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_R | 〇 | 〇 | 〇 | × | n/a |
SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX | 〇 | 〇 | 〇 | 〇 | × |
SDDL_DEVOBJ_KERNEL_ONLYは、カーネルモードからのアクセスのみ受け付けるもので、ユーザモードからはアクセスできないため、エクスプローラにドライブが表示されず、Administratorでコマンドプロンプトを起動してドライブにアクセスすることもできません。
SDDL_DEVOBJ_SYS_ALLは、System権限で動作しているユーザモードプロセスからはアクセスできるため、エクスプローラでドライブが表示されますが、アクセスすることはできません。また、Administratorからはアクセスできないため、Administratorでコマンドプロンプトを起動してもドライブにアクセスすることはできません。
SDDL_DEVOBJ_SYS_ALL_ADM_ALLは、Administratorからのアクセスは許可されるため、Administratorでコマンドプロンプトを起動することによりドライブにアクセスして、ファイルの作成や参照を行うことができますが、エクスプローラからドライブにアクセスすることはできません。
SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_Rは、一般ユーザからのReadアクセスが許可されるため、エクスプローラからドライブにアクセスすることができますが、Writeアクセスは許可されていないため、ファイルを保存することはできません。
SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWXは、一般ユーザによるRead/Writeアクセスおよび実行が許可されており、既存のファイルの修正と保存ができるようになっています。ただ、新規ファイルの作成や既存ファイルの名前変更などはできないようです。以下は、Administratorとして起動したコマンドプロンプト上で作成したファイルをエクスプローラからNotepadで開き、別名のファイルとして保存しようとしたときのエラーメッセージです。
このSDDLは、事前定義されたSDDLの中では最も広範囲でアクセスを許可するものですが、まだ一般ユーザが自由にアクセスできるというレベルではありません。事前定義のSDDLの宣言を含むヘッダファイル wdmsec.hを確認したところ、以下のような記述がありました。
//
// SDDL_DEVOBJ_SYS_ALL_ADM_ALL_WORLD_ALL_RES_ALL is listed for completeness.
// This ACL would give *any* user *total* access to the device, including the
// ability to change the ACL, locking out other users!!!!!
//
// As this ACL is really a *very* bad idea, it isn't exported by this library.
// Don't make an ACL like this!
//
/*
DECLARE_CONST_UNICODE_STING(
SDDL_DEVOBJ_SYS_ALL_ADM_ALL_WORLD_ALL_RES_ALL,
"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;WD)(A;;GA;;;RC)"
);
extern const UNICODE_STRING SDDL_DEVOBJ_SYS_ALL_ADM_ALL_WORLD_ALL_RES_ALL;
*/
このSDDLは、全てのユーザに対して完全なアクセスを提供するものですが、これを使うのは推奨されておらず、wdmsecライブラリも公開していないとのことです。そこで、このSDDLをソースコード中に定義して、それを使うように修正してみました。
@@ -361,6 +361,9 @@ Return Value:
WDFQUEUE queue;
DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME);
+ // Give total access to any user
+ DECLARE_CONST_UNICODE_STRING(sddlString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;WD)(A;;GA;;;RC)");
+
PAGED_CODE();
UNREFERENCED_PARAMETER(Driver);
@@ -379,6 +382,9 @@ Return Value:
WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
WdfDeviceInitSetExclusive(DeviceInit, FALSE);
+ // Specify SDDL (Security Descriptor Definition Language) string to control access to the device
+ WdfDeviceInitAssignSDDLString(DeviceInit, &sddlString);
+
//
// Since this is a pure software only driver, there is no need to register
// any PNP/Power event callbacks. Framework will respond to these
このようにすることで、エクスプローラ上で新しいファイルを生成したり、エディタで編集したファイルを別の名前で保存したりできるようになりました。
本稿では、WDKのサンプルRAMDiskドライバを修正して、デバイスのアクセス権限を変更し、ドライバの外見えの動作がどう変化するかを調査した結果について紹介しました。次回以降は、実際にファイルアクセスを行うアプリケーションを使って、ドライバ内部の動きを見ていこうと思います。
コンピュータビジョンセミナーvol.2 開催のお知らせ - ニュース一覧 - 株式会社フィックスターズ in Realizing Self-Driving Cars with General-Purpose Processors 日本語版
[…] バージョンアップに伴い、オンラインセミナーを開催します。 本セミナーでは、...
【Docker】NVIDIA SDK Managerでエラー無く環境構築する【Jetson】 | マサキノート in NVIDIA SDK Manager on Dockerで快適なJetsonライフ
[…] 参考:https://proc-cpuinfo.fixstars.com/2019/06/nvidia-sdk-manager-on-docker/ […]...
Windowsカーネルドライバを自作してWinDbgで解析してみる① - かえるのほんだな in Windowsデバイスドライバの基本動作を確認する (1)
[…] 参考:Windowsデバイスドライバの基本動作を確認する (1) - Fixstars Tech Blog /proc/cpuinfo ...
2021年版G検定チートシート | エビワークス in ニューラルネットの共通フォーマット対決! NNEF vs ONNX
[…] ONNX(オニキス):Open Neural Network Exchange formatフレームワーク間のモデル変換ツー...
YOSHIFUJI Naoki in CUDAデバイスメモリもスマートポインタで管理したい
ありがとうございます。別に型にこだわる必要がないので、ユニバーサル参照を受けるよ...