本「
IT談話館」一般公開記事は、10年以上の実務経験を持つ上級Windowsエンジニアを想定しています。
本館は、Windowsカーネル深層を解析し、クラッシュ原因をはじめとするシステム内の「異様な動き」を検出・分析する
超高度な技術と実績を保有しています。
WinDbgとCPU
本「IT談話館」の「一般公開記事」は、「Active Memory Dump とカーネルメモリダンプ」の解析結果を基に起草されています。「本館」主筆の「豊田孝」はDKOM(Direct Kernel Object Manipulation)ベースの解析手法の第一人者であり、Windowsカーネル空間の解析分野では世界の先頭を走っています。
現在、セキュリティー問題を無視することはできません。Microsoft社側の負担だけではなく、同社製品の利用者側の負担も増しています。困ったことではありますが、当面避けられません。セキュリティーの視点から「Windows10ソフトウェアセンサー」を見た場合、本「IT談話館」の確認範囲では、「カーネル層保護ロジック」に加え、次のような保護メカニズム階層が考案・実装されています。下記リンクはすべて本館記事を指しています。
- Silo/Server Silo
- Job
- Session
- Protected Process
- Mandatory Integrity Control(MIC)
- Windows API(+CPU)
- CPU
本稿では「Meltdown and Spectre」問題とWindowsカーネルの関係を取り上げます。「Meltdown and Spectre」問題は複数の視点に細分化されています。細分化の詳細、概念、あるいは、プロセッサー関連用語などの基本情報については、この「Meltdown and Spectre」公開資料に加え、次のような資料が参考になるでしょう。
- Intel社(Meltdown and Spectre)
- Microsoft社(Meltdown and Spectre)
- Microsoft社(Meltdown)
- Google社
- Google Chrome Team and Microsoft Security Team
- 比較的敷居の低い資料
- Spectre問題概要(WiKi)
- Meltdown概要(Wiki)
これらの公開資料はいずれも貴重なものですが、「Meltdown and Spectre」問題への対策作業は現在も進行中であり、公開情報の有効性はあくまでも公開時点であることには注意しておきたいところです。公開情報の賞味期限問題は、Cloudサービス時代の一般的な特徴と認識し、実装細部は常に更新されていると覚悟したほうがよいでしょう。
上記の公開資料などから「問題と対策」に関与する人々の発想と視座などを把握した後は、たとえば、「Activeメモリダンプ」を採取し、次のようなWinDbgコマンド操作を行うとよいでしょう。
0: kd> vertarget
Windows 10 Kernel Version 16299 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 16299.15.amd64fre.rs3_release.170928-1534
Machine Name:
Kernel base = 0xfffff800`5b40e000 PsLoadedModuleList = 0xfffff800`5b774fd0
Debug session time: Mon Feb 5 08:09:34.714 2018 (UTC + 9:00)
System Uptime: 0 days 21:32:03.381
0: kd> dt nt!_kprcb bp*
+0x0f8 BpbState : UChar
+0x0f8 BpbIbrsPresent : Pos 0, 1 Bit
+0x0f8 BpbStibpPresent : Pos 1, 1 Bit
+0x0f8 BpbSmepPresent : Pos 2, 1 Bit
+0x0f8 BpbSimulateIbrs : Pos 3, 1 Bit
+0x0f8 BpbSimulateIbpb : Pos 4, 1 Bit
+0x0f8 BpbReserved : Pos 5, 3 Bits
+0x0f9 BpbPad : [7] UChar
この「Activeメモリダンプ」は、2018年2月時点で採取されています。2018年5月時点で採取した「Activeメモリダンプ」のデータは後程紹介しますが、多くのデータがカーネルレベルで変更されています。本稿末には、2019年3月時点と同年12月時点のカーネル内部情報も紹介しています。一口にWindows 10といっても、ビルド番号が異なれば別物OS、と認識する必要があります。
上記の「dt nt!_kprcb bp*」コマンドは、「nt!_kprcb」オブジェクトを検索し、「bp」という文字列を含むすべてのフィールド名を表示してきます。ちなみに、「bp」は、Branch Prediction(分岐予測)、を指し、「Meltdown and Spectre」問題のうちの、Spectre問題への対策状態を示しています。ここでは、Spectre問題は、条件/間接分岐コードの解釈予測に誤りがあり、結果、その後の実行投機に失敗する、と解釈しておきます。上の公開情報の中には、Prediction(予測)、Speculation(投機)、Conditional Branch(条件分岐)、Indirect Branch(間接分岐)、Injection(外部コード挿入)、Microcode、Micro Architecture、キャッシュ、Retpolineなどの用語が頻出しています。それらの用語は、既存オブジェクトに新たに追加されるフィールド名や新規に投入される内部関数名に採用されるのが一般的です。
検索対象フィールド名が存在しない場合、つまり、Spectre問題への対策が講じられていない場合には、次のような情報が返されてきます。
0: kd> dt nt!_kprcb bp*
Cannot find specified field members.
2018年5月時点で採取した「Activeメモリダンプ」の実行結果は次のようになっています。
1: kd> vertarget
Windows 10 Kernel Version 17134 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 17134.1.amd64fre.rs4_release.180410-1804
Machine Name:
Kernel base = 0xfffff801`63699000 PsLoadedModuleList = 0xfffff801`63a561d0
Debug session time: Fri May 11 07:58:31.309 2018 (UTC + 9:00)
System Uptime: 0 days 0:32:48.173
1: kd> dt nt!_kprcb bp*
+0x0f8 BpbState : Uint2B
+0x0f8 BpbIbrsPresent : Pos 0, 1 Bit
+0x0f8 BpbStibpPresent : Pos 1, 1 Bit
+0x0f8 BpbSmepPresent : Pos 2, 1 Bit
+0x0f8 BpbSimulateSpecCtrl : Pos 3, 1 Bit
+0x0f8 BpbSimulateIbpb : Pos 4, 1 Bit
+0x0f8 BpbIbpbPresent : Pos 5, 1 Bit
+0x0f8 BpbCpuIdle : Pos 6, 1 Bit
+0x0f8 BpbClearSpecCtrlOnIdle : Pos 7, 1 Bit
+0x0f8 BpbHTDisabled : Pos 8, 1 Bit
+0x0f8 BpbUserToUserOnly : Pos 9, 1 Bit
+0x0f8 BpbReserved : Pos 10, 6 Bits
+0x0fa BpbSpecCtrlValue : UChar
+0x0fb BpbCtxSwapSetValue : UChar
+0x0fc BpbPad : [4] UChar
この情報と、先の2018年2月時点でに採取された「Activeメモリダンプ」の情報と比較しますと、有効ビット数が劇的に増えていることが分かります。追加された有効ビットはどのような役割を担っているのか?本稿では詳細解説を割愛せざるをえませんが、本館の独自解析コードを実行し、次のような2種類の解析結果を紹介しておきます。
0: kd> vertarget
Windows 10 Kernel Version 16299 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 16299.15.amd64fre.rs3_release.170928-1534
Machine Name:
Kernel base = 0xfffff800`5b40e000 PsLoadedModuleList = 0xfffff800`5b774fd0
Debug session time: Mon Feb 5 08:09:34.714 2018 (UTC + 9:00)
System Uptime: 0 days 21:32:03.381
*** 00 ***
Pcr->0xfffff8005a350000
NtTib->0xfffff8005a350000 GdtBase->0xfffff8005d679fb0
TssBase->0xfffff8005d678000 TssBase.Rsp0->0xfffff8005d67b200
IdtBase->0xfffff8005d677000
UserRsp->0x0000000000000000 CurrentPrcb->0xfffff8005a350180 LockArray->0xfffff8005a350870
+Prcb BranchPredictionAndShadow 0xfffff8005a350180
Shadow->0x3 KernelDirectoryTableBase->0x000000008b900000 BranchPrediction->0x0
RspBaseShadow->0xffffd70a81acad90 UserRspShadow->0x00000074874feb58
ContextFrame->0xfffff8005a350370 SpecialRegisters->0xfffff8005a350280
Cr0->0x0000000080050031 Cr2->0xffffc70ed1172010 Cr3->0x000000008b900000 Cr4->0x00000000000406f8 Cr8->0x0000000000000002
Process->0xffffd88dffb3c080 RestrictIndirectBranchPrediction->0x20 Name->notmyfault64.e
Shadow: DirectoryTableBase->0x000000008b900000 UserDirectoryTableBase->0x0000000000000000
kThread->0xffffd88dfef55080 SpecControl.ThreadSpecControl->0x1
1: kd> vertarget
Windows 10 Kernel Version 17134 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 17134.1.amd64fre.rs4_release.180410-1804
Machine Name:
Kernel base = 0xfffff801`63699000 PsLoadedModuleList = 0xfffff801`63a561d0
Debug session time: Fri May 11 07:58:31.309 2018 (UTC + 9:00)
System Uptime: 0 days 0:32:48.173
*** 01 ***
Pcr->0xffffe4806ada0000
NtTib->0xffffe4806ada0000 GdtBase->0xffffe4806adb3fb0
TssBase->0xffffe4806adb2000 TssBase.Rsp0->0xffffe4806adb5200
IdtBase->0xffffe4806adb1000
UserRsp->0x0000000000000000 CurrentPrcb->0xffffe4806ada0180 LockArray->0xffffe4806ada0870
-Prcb BranchPredictionAndShadow 0xffffe4806ada0180
Shadow->0x2 KernelDirectoryTableBase->0x0000000139100000 BranchPrediction->0x0
RspBaseShadow->0xfffff500937a1fd0 UserRspShadow->0x000000dd4415ece8
ContextFrame->0xffffe4806ada0370 SpecialRegisters->0xffffe4806ada0280
Cr0->0x0000000080050031 Cr2->0xffff91043865f010 Cr3->0x0000000139100000 Cr4->0x00000000000406f8 Cr8->0x0000000000000002
Process->0xffffd30643533080 RestrictIndirectBranchPrediction->0x20 Name->notmyfault64.e
Shadow: DirectoryTableBase->0x0000000139100000 UserDirectoryTableBase->0x0000000000000000
kThread->0xffffd30643155700 SpecControl.ThreadSpecControl->0x0
ここで使用した本館の解析コードは、残念ながら、2019年のWindows 10環境で採取したメモリダンプにはエラーが発生し、適応できません。本稿では最後に、2019年3月時点と12月時点で採取したメモリダンプの比較情報を紹介するにとどめます。なお、解析コードの開発知識の習得には、「時間と予算の投資」が必要です。
2019-03
1: kd> dt nt!_kprcb bp*
+0x0f8 BpbState : UChar
+0x0f8 BpbCpuIdle : Pos 0, 1 Bit
+0x0f8 BpbFlushRsbOnTrap : Pos 1, 1 Bit
+0x0f8 BpbIbpbOnReturn : Pos 2, 1 Bit
+0x0f8 BpbIbpbOnTrap : Pos 3, 1 Bit
+0x0f8 BpbStateReserved : Pos 4, 4 Bits
+0x0f9 BpbFeatures : UChar
+0x0f9 BpbClearOnIdle : Pos 0, 1 Bit
+0x0f9 BpbEnabled : Pos 1, 1 Bit
+0x0f9 BpbSmep : Pos 2, 1 Bit
+0x0f9 BpbFeaturesReserved : Pos 3, 5 Bits
+0x0fa BpbCurrentSpecCtrl : UChar
+0x0fb BpbKernelSpecCtrl : UChar
+0x0fc BpbNmiSpecCtrl : UChar
+0x0fd BpbUserSpecCtrl : UChar
+0x0fe BpbPad : [2] UChar
2019-12
0: kd> dt nt!_kprcb bp*
nt!_KPRCB
+0x0f8 BpbState : UChar
+0x0f8 BpbCpuIdle : Pos 0, 1 Bit
+0x0f8 BpbFlushRsbOnTrap : Pos 1, 1 Bit
+0x0f8 BpbIbpbOnReturn : Pos 2, 1 Bit
+0x0f8 BpbIbpbOnTrap : Pos 3, 1 Bit
+0x0f8 BpbIbpbOnRetpolineExit : Pos 4, 1 Bit
+0x0f8 BpbStateReserved : Pos 5, 3 Bits
+0x0f9 BpbFeatures : UChar
+0x0f9 BpbClearOnIdle : Pos 0, 1 Bit
+0x0f9 BpbEnabled : Pos 1, 1 Bit
+0x0f9 BpbSmep : Pos 2, 1 Bit
+0x0f9 BpbFeaturesReserved : Pos 3, 5 Bits
+0x0fa BpbCurrentSpecCtrl : UChar
+0x0fb BpbKernelSpecCtrl : UChar
+0x0fc BpbNmiSpecCtrl : UChar
+0x0fd BpbUserSpecCtrl : UChar
+0x6d0 BpbRetpolineExitSpecCtrl : UChar
+0x6d1 BpbTrappedRetpolineExitSpecCtrl : UChar
+0x6d2 BpbTrappedBpbState : UChar
+0x6d2 BpbTrappedCpuIdle : Pos 0, 1 Bit
+0x6d2 BpbTrappedFlushRsbOnTrap : Pos 1, 1 Bit
+0x6d2 BpbTrappedIbpbOnReturn : Pos 2, 1 Bit
+0x6d2 BpbTrappedIbpbOnTrap : Pos 3, 1 Bit
+0x6d2 BpbTrappedIbpbOnRetpolineExit : Pos 4, 1 Bit
+0x6d2 BpbtrappedBpbStateReserved : Pos 5, 3 Bits
+0x6d3 BpbRetpolineState : UChar
+0x6d3 BpbRunningNonRetpolineCode : Pos 0, 1 Bit
+0x6d3 BpbIndirectCallsSafe : Pos 1, 1 Bit
+0x6d3 BpbRetpolineEnabled : Pos 2, 1 Bit
+0x6d3 BpbRetpolineStateReserved : Pos 3, 5 Bits
独自の解析コードの開発知識を習得すると、ソースコード内のエラー発生コードをその場で修正し、次の解析コードを開発できるようになります。この開発作業は、時代への対応そのものであり、たいへん魅力、かつ、創造的なものです。ビルド番号変更時に発生するエラーは「カーネル層の変化」を具体的、かつ、実践的に示しています。