カーネルがロックダウンモードにあるにもかかわらず、アクセス可能なレガシーI/Oインタフェースが放置されている ―8月4日、カーネルメンテナーのひとりであるKrzysztof Wilczyńskiが提出したパッチが承認され、約10年前から存在するレガシーI/Oインターフェースが、ロックダウンの保護対象から漏れていることが確認された。この修正パッチは今秋リリース予定の「Linux 7.3」でマージされる見込みだ。
ロックダウンモードはLinuxカーネルをユーザ空間から保護することを目的に、2019年11月の「Linux 5.4」ではじめてサポートされたセキュリティ機構だ。UNIX/Linuxでは歴史的に「rootであれば何でもできる」という思想が一般的だったが、ロックダウンは「rootであってもカーネルを書き換えることはできない」という状態を意図的に作り出す。具体的には/dev/memや/dev/kmem、PCI BAR(Base Address Register)へのアクセス、カーネルメモリの直接読み書きなどが、rootであってもできなくなる。
Linux 5.4でサポートされるまでにはロックダウン推進派と反対派/慎重派のあいだで長く議論が繰り返されてきたが、最終的には当初は慎重派だったLinus Torvaldsがロックダウンをオプションとして提供する(管理者が有効/無効を選択できる)ことに同意し、マージに至っている。
今回、Wilczyńskiが発見したのはロックダウンの“保護対象漏れ”である。/dev/memやPCI BARなど主要な経路へのアクセスはsecurity_locked_down()で塞がれていたが、sysfsに残る古いPCIデバイスなどを操作するためのレガシーインタフェースであるlegacy_ioやlegacy_memは完全に見落とされていた。その結果、「カーネルがロックダウンモードにあってもroot権限をもつユーザは依然として任意のI/Oポートへの書き込みや、レガシーI/Oおよびメモリ空間のマッピングを行うことが可能」(Wilczyński)な状態で放置されていたことになる。まさに「ロックダウンによって排除しようとしている操作そのもの」がレガシーインタフェースを通して可能になっていたのだ。
もっとも、現在では通常のデスクトップ利用や一般的なディストリビューションでこれらのレガシーインタフェースが使われることはほとんどなく、ごく一部のドライバ開発やデバッグ用途を除けば、一般への影響は非常に限定されているといっていいだろう。
新たな脅威に対応しつつ、ユーザランドを守ることの難しさ
今回の件で思い起こされるのは、Linux 5.4におけるロックダウンモードの実装にあたってLinusが示していた懸念だ。Linusは当初、「rootができないことを作るのはLinux/UNIXの思想に合わない」「Microsoftが推進するSecure Bootを前提に設計を進めることへの違和感」などに加え、「ロックダウンのためにカーネルのいたるところに個別の制限を追加するのはいかがなものか」という懸念を示していた。
ロックダウンの提案者であるMatthew Garrettは最初の本格的なパッチを2019年2月に提出した際、27に分割されたパッチを投稿し、それぞれのパッチごとに別々の箇所(/dev/mem、MSR、ACPI、PCIなど)へのロックダウンのチェックsecurity_locked_down()を追加している。つまり最初から「カーネル全体のあちこちに禁止処理を追加する」という構成を取っていたのだが、Linusやロックダウン慎重派はこの方針に対し、個別に禁止対象を列挙することでメンテナンスが難しくなることを憂慮していた。「これは禁止」「これも禁止」「あれも禁止」…とモグラ叩きのようにルールを増やしていくと、結果として「あれを禁止し忘れた」という見落としが発生する可能性も高くなる。ある意味、今回のバグ修正は当時のLinusらが懸念していた「個別に禁止対象を増やしていく設計」の難しさを象徴する出来事ともいえる。
もっともサイバー攻撃の被害が日に日に増大している現在、ロックダウンというメカニズムそのものに反対する声はあまり聞かれない。しかし、Linuxのように30年以上に渡って互換性を維持してきた巨大プロジェクトでは、新しい設計思想やセキュリティポリシーが出てきたときに、過去の資産すべてにそれを適用することは本当に難しい作業であり、今回のロックダウンのバグ発見と修正はその難しさをあらためて示した例だといえる。
Linusはカーネル開発において「We do not break userspace.」という大原則をつねに掲げており、カーネルの変更によってユーザのシステムやアプリケーションが動かなくなることを非常に嫌う。したがってLinuxカーネルはレガシーインタフェースを安易に削除するのではなく、新しいセキュリティポリシーを適用しながら共存させるという難しい選択を取り続けてきた。今後もこの大原則を維持していくためには、今回のような“設計の棚卸し”がより頻繁に求められるのかもしれない。