M1 Mac でのドライバの読み込み判断フロー

M1 Macになってからドライバが使えなくなってしまった。。。CatalinaやBig Surになってからドライバを使った周辺機器やソフトがエラーになってしまう。。。

こんなこと増えていませんか?ここ数年、セキュリティ対策の強化でmacOSでのドライバを取り巻く状況が大きく変わってきています。この記事では、ドライバの読み込みが上手くできない理由と対応方法などについて解説します。

ドライバには大きく2種類有る

大きく分けるとmacOSには2種類のドライバがあります。

  • KEXT (Kernel Extension)
  • DEXT (DriverKit Extension)

大きな流れとして、KEXTからDEXTへの移行があります。OSのアップグレードによりDEXTで作れる様になったドライバは、KEXTからDEXTに移行する必要があり、対象のKextはOSにより読み込まれなくなります。(この記事執筆時点では、USB HIDや、USB Serial通信、USBカスタムクラス、SCSI Parallelデバイス、仮想ネットワークインターフェイスなどはDEXTの移行対象になっています)

KEXTはシステムの中枢で動作し、DEXTはアプリ側に近い層で動作するように仕組みが異なります。安全性の面でもDEXTの方が有利なため、KEXTは徐々に廃止していくという方針が取られています。

KEXTのロード可否判断

KEXTはシステムの中枢(カーネル内)で動作するため、より慎重な動作と信頼性が求められます。そのため、OS側も不正なKEXTがシステムに入り込まないように色々な対策が取られています。その結果、ここ最近のOS、特に、Catalina以降かつT2チップ搭載Mac以降ではやや混乱も見られます。更に、M1 Macではより安全なシステム運用方針が取られたため、ユーザーから見ると使うためのハードルが高くなってしまいました。

ロード可否の判断のフローをまとめたのが次の図です。

見るからに複雑ですよね。それに判断ポイントの設定が何になっているかの確認方法や設定の変更方法についてもこの記事で解説します。

セキュリティポリシーの設定

M1 Macのセキュリティポリシーには次の2つの設定があります。

  • 完全セキュリティ
  • 低セキュリティ

後者は言葉の表現がきついですが、危険なものではありません。そして、KEXTを使用するためには後者の設定になっている必要があります。しかし、M1 Macのデフォルト設定は前者になっていまいます。そのため、デフォルト設定の前者の設定でドライバをインストールすると次のような警告メッセージが表示されます。

画面の指示に従って行くと、セキュリティポリシーの変更方法が表示されます。表示される方法の通りなのですが、少し補足すると、具体的な手順は次のようになります。

  1. Macをシステム終了する。
  2. パワーオンボタンを押したまま、「起動オプションを表示するには押し続けてください」と表示されるので、押したまましばらく待つ。
  3. 画面に「起動オプションを読み込み中」と表示されたら、指を離す。
  4. 復旧ユーティリティが表示されるので、ユーザー選択し、「次へ」をクリックし、パスワードを入力する。(表示されないこともある)
  5. FileVaultがオンになっている場合は、暗号化ディスクを選択する画面が表示されるので、ディスクを選択し、「ロックを解除」ボタンをクリックし、パスワードを入力する。
  6. 「セキュリティポリシー」ボタンをクリックする。
  7. 「低セキュリティ」を選択し、「確認済みの開発元からカーネル機能拡張のユーザ管理を許可」をチェックし、「OK」ボタンをクリックする。
  8. 「起動ディスク」メニューから「システム終了」をクリックする。

KEXTのインストールとは無関係に設定変更したいときや元の設定に戻したいとき

上記の手順でセキュリティポリシーを変更できます。但し、上記の手順は高セキュリティポリシー設定のマシンにKextをインストールしたときに表示されるエラーメッセージからシステム終了したときです。それ以外のときは、少し手順が異なり、次のようになります。設定を元に戻したいときも以下の手順で設定画面へ入れます。

  1. Macをシステム終了する。
  2. パワーオンボタンを押したまま、「起動オプションを表示するには押し続けてください」と表示されるので、押したまましばらく待つ。
  3. 画面に「起動オプションを読み込み中」と表示されたら、指を離す。
  4. 「オプション」を選択して、「続ける」をクリックする。
  5. 復旧ユーティリティが表示されるので、ユーザー選択し、「次へ」をクリックし、パスワードを入力する。(表示されないこともある)
  6. 「ユーティリティ」メニューから「起動セキュリティユーティリティ」を選択する。
  7. FileVaultがオンになっている場合は、暗号化ディスクを選択する画面が表示されるので、ディスクを選択し、「ロックを解除」ボタンをクリックし、パスワードを入力する。
  8. 「セキュリティポリシー」ボタンをクリックする。
  9. 「低セキュリティ」を選択し、「確認済みの開発元からカーネル機能拡張のユーザ管理を許可」をチェックし、「OK」ボタンをクリックする。
  10. 「起動ディスク」メニューから「システム終了」をクリックする。

KEXTの公証

KEXTはMac App Storeでは配布できないため、Developer ID Application証明書でコードサイニングして、Webサイトなどで配布します。macOS Mojave 10.14.5以降ではコードサイニングだけではロード対象になりません。公証(Notarized)が必須になっています。KEXTをApple Notarization Servicesで公証する条件はアプリと同様です。手順も同様です。通常はインストーラの形式で配布することになりますので、インストーラを作成し、DMGに固めて、DMGごとApple Notarization Servicesに登録します。

公証が通ったら、DMGごとStapleしましょう。

公証のコマンドラインでの手順は次の記事で解説しています。

SIPの設定

KEXTの開発中やデバッグ中など、その都度、公証したくないというときもあります。そのようなときは、SIP (System Integrity Protection) を無効化するという方法があります。SIPを無効にすると公証していないKEXTもロード対象になります。

しかし、あくまで開発環境専用の設定です。OSのセキュリティチェックを無効化するのでセキュリティが著しく低下することになります。デバッグ作業が完了したら元に戻すことをお勧めします。無効化するための設定方法は以下の通りです。

  1. Macをシステム終了する。
  2. パワーオンボタンを押したまま、「起動オプションを表示するには押し続けてください」と表示されるので、押したまましばらく待つ。
  3. 画面に「起動オプションを読み込み中」と表示されたら、指を離す。
  4. 「オプション」を選択して、「続ける」をクリックする。
  5. 復旧ユーティリティが表示されるので、ユーザー選択し、「次へ」をクリックし、パスワードを入力する。(表示されないこともある)
  6. 「ユーティリティ」メニューから「ターミナル」を選択する。
  7. 「ターミナル」で以下を実行する。
  8. csrutil disable
  9. Macを再起動する。

元に戻すには、リカバリーモードのターミナルで以下を実行します。csrutilはリカバリーモードでしか動作しません。

csrutil enable

KEXTのユーザー許可

KEXTが公証されていて、ロード可能となると、ユーザーにKEXTの使用許可を確認する状態になります。「システム環境設定」の「セキュリティとプライバシー」に許可を待つKEXTが表示されます。

ユーザーが許可すると、システムキャッシュの更新が行われ、KEXTがキャッシュに取り込まれて、再起動後からロードされるようになります。

許可されているがシステムキャッシュに含まれないケース

これが一番厄介です。システムキャッシュに含まれず、さらにユーザーは許可をしているという状態が、「(C)正常に読み込まれていないためロードされない」という状況です。M1 Macではこの問題に遭遇したことがありません。そのため、参考情報です。Intel MacでmacOS Catalina 10.15で以下の手順を行うとこの状態になります。

  1. USB Mass Storageのドライバをインストールする(例えば、サードパーティのハードディスクのドライバやデジカメなど、Finder上にディスクをマウントできる周辺機器のドライバ)。
  2. インストールの途中で表示されるドライバの許可確認メッセージで「セキュリティ環境設定を開く」をクリックする。
  3. インストーラがインストールを行っている途中で、ドライバの読み込みを許可する
  4. インストール完了後、インストーラで再起動する。

上記の手順で行うと、Catalinaのいくつかのバージョンで、インストールしたKEXTがシステムキャッシュに含まれない状態になることがあります。このようになると、KEXTはロードされません。

なぜ、システムキャッシュに含まれない状態になってしまうのか?

なぜ、システムキャッシュに含まれないかというと、次のような理由です。

  1. macOSのセキュリティ対策で、KEXTは再起動を行うまでは読み込まれない。
  2. インストーラの最後のシステムキャッシュ再作成では、再起動前、または、ユーザーの許可前のいずれかの条件により、インストールしたKEXTは対象にならない。
  3. 再起動前に、ユーザーがKEXTを許可しても、再起動前の条件により、システムキャッシュの対象に含まれない。
  4. 再起動後、KEXTの読み込み処理で、キャッシュに含まれないため、ロード対象にならない。
  5. キャッシュの再更新は、他のKEXTをインストールするまで行われないため、ロードされない状態になる。

インストーラの途中で許可を行わず、「OK」ボタンを押してメッセージを閉じて、再起動後に、許可すると、次のようになるため正しくロードされます。

  1. インストーラの最後のシステムキャッシュ再作成では、再起動前、の条件により、インストールしたKEXTは対象にならない。
  2. 再起動後に、KEXTをユーザーが許可すると、システム側でシステムキャッシュの再作成が行われる。インストールしたKEXTは再起動後、かつ、ユーザー許可によりシステムキャッシュの対象となる。
  3. 再起動後、KEXTの読み込み処理で、キャッシュに含まれるため、ロード対象となる。

修正するにはシステムキャッシュの更新を行う必要があり、そのためには、以下のいずれかを実行します。

  • ドライバを上書きインストールする
  • 強制的にシステムキャッシュを再作成する

修正方法1 ドライバの再インストール

同じドライバを上書きインストールすると、インストーラが最後にシステムキャッシュの再作成を行います。このとき同じドライバ(コードサイニングの署名情報が一致)であれば既にユーザーが許可しており、再起動後の扱いになるので、キャッシュ対象となります。

修正方法2 強制的にシステムキャッシュを再作成する

ターミナルで以下を実行します。

sudo kextcache -update-volume /

KEXTはRosetta2では変換できない

KEXTはRosetta2では変換できません。アプリやコマンドラインツールのようにIntel版を使うということはできません。そのため、Universal BinaryやApple Silicon Native化されたKEXTが必要となります。

まとめ

KEXTはKernel Extensionの略で、カーネルの中で動作するプログラムです。そのため、危険なこともできてしまうプログラムです。システムをより安全にしていくために、少しややこしい状況が生まれてしまいました。まだ、DEXTではできなこともあるのが現象ですが、将来的にはすべてのKEXTがDEXTに移行され、このような複雑な状況も改善されることでしょう。

投稿者プロフィール

林 晃
林 晃macOS/iOSアプリ/SDK/ミドルウェア開発が専門の開発者
アールケー開発代表。macOS/iOSアプリ/SDK/ミドルウェア開発が専門の開発者。ObjC/Swift/C++使い。豊富な開発実務経験を基に、教育コンテンツ開発、技術書執筆、技術指導、技術セミナー講師、企業内研修講師、行政・自治体職員研修講師も行います。

基礎から学ぶMetal


「基礎から学ぶMetal」を執筆しました。本書はMetalを使ってGPUプログラミングを行うための最初のステップを解説するMetalの解説書です。

私が初めてGPUプログラミングを行ったとき、どこから手をつけて、学んでいけば良いのか分からず呆然としました。もし、あのとき、これを教えてくれればという部分を解説しました。本書で解説している部分はMetalの基礎となる部分で、Metalを使うときに必ず触れることになる部分です。

詳細

基礎から学ぶSwiftUI


「基礎から学ぶ SwiftUI」というタイトルの本を執筆しました。

SwiftUIの入門書です。

SwiftUIのコンセプトは「ユーザーインターフェイスを作るための最短パスを提供する」「一度学べば(Appleのプラットフォームの)どこにでも適用できる」です。

SwiftUIの概要から始まって、一つ一つのテクノロジートピックに注目しながらSwiftUIとは何か?どんなことができるのか?どのようなコードを書けば良いのかなどを丸々一冊使って解説しています。

詳細

関連記事

  1. SwiftでCのポインタのインクリメント・デクリメントのコードを書き換…

  2. SwiftUIの2つのライフサイクル

  3. MacアプリのUIテスト – ダイアログのテスト

  4. SwiftとObjective-Cを共存させるならObjective-…

  5. コマンドライン引数でモックに差し替える

  6. WKWebViewでBasic認証を行う

最近の著書

  1. 基礎から学ぶ SwiftUI

人気記事

最近の記事