|||||||||||||||||||||

なんぶ電子

- 更新: 

UbuntuでNVIDIAドライバが動かない

UbuntuでNVIDIA

日本で禁止になるまえにビットコインのマイニングに一度は触れておきたいとか思って、手元にあった古いゲーミングPCにUbuntuをインストールしたところ、NVIDIAのグラフィックボードが認識はするけれど稼働せず悩みました。

その原因と解決方法を見出すのに1週間ぐらいかかったので、ここにメモをしておきます。Ubuntuの後Debianでも同じ作業をしてみました。

ちなみに実際にマイニングした記事はこちらにありますので、興味があれば読んでみてください。

セキュアブートをOFF

手っ取り早い解決策は「セキュアブートをOFFにする」ことでした。

根本的な解決を望む場合もいったんセキュアブートをOFFにしてみて症状が改善したのなら「セキュアブート」が原因です。逆にそれで改善しなかったら、この後に書いてあることはおそらく役に立ちません。

方法はUEFI(BIOS)を立ち上げて、セキュアブートの項目をOFFにするだけです。

UEFIは画面が多彩なので、参考になるかわかりませんが、筆者の持っていたASUSボードの場合は次のような手順でした。

  1. UEFIを起動する。

    電源ON時に「F2」キーか「DELETE」キーを押すことでUEFIメニューに移動します。

  2. Advanced Mode(F7)に移動
  3. 「起動」タブに移動
  4. 「セキュアブートメニュー」に移動
  5. OSタイプを「非UEFIモード」にする

    もとに戻す時には「UEFIモード」を選択

  6. 「Exit」タブから保存して終了

    「Save Changes & Reset」を選択

これで立ち上げたあと、ドライバが起動しているか確認します。

NVIDIAのドライバの場合は「nvidia-smi」コマンドで、グラフィックボードの状態が表示されるか確認します。成功時にはトップ画像のようなメッセージが表示されます。文字だけのメッセ―ジの場合は稼働していません。

セキュアブートとは

kledgeb:「Ubuntu 20.04 その74 - UbuntuとUEFIセキュアブート」によればセキュアブートとは、UEFIによって実行されるコードが信頼できるものかを検証する仕組みです。これによりOSやファームウェアの書き換え等を検知し不正なプログラムを稼働させないようにしています。

信頼できるコードかどうかというのは「電子署名」を用いて判断します。電子署名ではSSLなどと同じ公開鍵暗号方式が用いられます。コードに署名があるか、署名があった場合は証明書により発行者を確認し、問題なければコードは実行されます。

Windows用に出荷されているPCでは、周辺機器のファームウェアにMicrosoftの証明書が組み込まれており、その存在をあまり意識せずに使うことができます。

Ubuntuでは、shimというOSをロードするプログラムをMicrosoftに署名してもらった上、shimにCanonical社の証明書を組み込み、grub等にはcanonicalの署名をすることにより、セキュアブートを実現させています。

なので、Ubuntuを使う上でも場合によってはその存在を意識せずにすむのですが、今回の筆者のようにサードパーティ製のドライバをインストールするという場合には問題になってきます。

セキュアブートが有効の状態でNVIDIAのドライバを稼働させる

セキュアブート環境でサードパーティ製や自分でビルドしたドライバを組み込みたい場合に用いるのがMOK(Machine Owner Key)とMOK Managerです。

MOKは所有者の鍵で、これで必要なドライバに署名をするという流れになります。この鍵は前述のshimやLinux kernelがカーネルモジュールを署名する目的以外では利用できません。

次のコマンドを入力することで、MOKの鍵のセットを作成できます。鍵が出力された場合のみwriteing new private keyのメッセージが出力されます。すでにファイルがある場合は何もおきませんでしたが、環境によっては上書きが致命傷になる操作なので慎重に行ってください。

$ sudo update-secureboot-policy --new-key
...
writing new private key to '/var/lib/shim-signed/mok/MOK.priv'

メッセージに表示されたMOK.privと同じ場所に、MOK.derファイルも作成されます。MOK.privが秘密鍵、MOK.derが証明書(公開鍵)に当たります。

ここで作成した証明書(MOK.der)の方を登録しておくことで、秘密鍵(MOK.priv)で署名したドライバがセキュアブートでも利用可能になります。

MOK.derの登録作業

発行した(MOK.der)証明書はUEFIに信頼できるものとして登録する必要があります。登録作業は、OSレベルで要求を出し、UEFI(実機)レベルで登録する2段構えになります。

次のコマンド入力し、次回UEFI起動時に証明書管理モードに入るようにします。この際パスワードを求められます(sudoのパスワード入力が発生した場合はその後)。このパスワードは使い捨てのパスワードで後の実機操作の際に入力します。


$ sudo mokutil --import /var/lib/shim-signed/mok/MOK.der
input password: xxxxx
input password again: xxxxx

再起動をかけて、実機を操作します。

起動後10秒ほどの猶予で、何かキーを押すように求められます。これを過ぎると通常の起動となります。

Press Any Key

次の画面ではEnroll MOKを選択します。

Perform MOK management

Continue boot
<Enroll MOK>
Enroll key from disk
Enroll hash from disk

証明書の中身を見たい場合はVeiw Keyから見ることができます。間違いなければ、Continue選択で作業を続けます。

[Enroll MOK]
Veiw Key 0
<Continue>

登録確認画面です。Yesを選択すると先に設定したパスワードの入力を求められます。

[Enroll the key(s)?]
No <Yes>
 
[Enroll the key(s)?]

password: xxxxx

再起動を選択して作業完了です。

  Perform MOK management

<Reboot>
Enroll key from disk
Enroll hash from disk

今後MOK.privで署名したモジュールはすべてセキュアブート上で稼働するようになりますので取り扱いには注意してください。また、MOK.derとMOK.priv以外の鍵のセットでも同様の登録が可能です。

署名をする場合はubuntu wiki:「Signing」に書いてあるように次のようにします。

$ sudo kmodsign sha512 /var/lib/shim-signed/mok/MOK.priv /var/lib/shim-signed/mok/MOK.der module.ko

NVIDIA GeForce GTX 960ドライバをインストール

参考として筆者の環境であるNVIDIA GTX 960の場合で話を進めていきます。NVIDIAのドライバーはインストール時に必要な鍵のセットを作成した上で署名もしてくれるようです。ここでは鍵のセットは先のMOKを利用し、署名はインストールアプリに任せます。

まずNVIDIA 「ドライバダウンロード」から、対応するドライバをダウンロードします。

このファイルは.runファイルなので、ダウンロード後に実行権限をつけて、sudoで実行します。

このプログラムは実行途中でビルドをするのでビルド環境がなかったら事前にaptでbuild-essentialをインストールしておいてください。

メーカーが公開しているこのドライバのインストールツールは、1.nouveauを停止させる設定をし、2.ドライバへの署名をするように組み込まれています。

Nouveau kernel driverの停止

これは、セキュアブートとは直接関係がない話ですが、カーネルドライバについて理解する為に書いておきます。ドライバインストール中、Nouveau kernel driverは互換性がないことからくる次のようなエラーが表示されました。


ERROR: The Nouveau kernel driver is currently in use by your system. This
driver is incompatible with the NVIDIA driver, and must be disabled
before proceeding. Please consult the NVIDIA driver README and your
Linux distribution's documentation for details on how to correctly
disable the Nouveau kernel driver.

この後Nouveau kernel driverを読み込まないようにする設定に従っても、エラーを繰り返すだけでした。Quiita:「Ubuntu17.10にNVIDIAドライバをインストールしてみた。」に、同じ症状が載っていて「sudo update-initramfs -u」を実行することを知りました。

$ sudo update-initramfs -u

これら一連の作業はカーネルモジュールの操作をしています。カーネルモジュールとは、システムの再起動せずにカーネルの機能を拡張させるためのコードです。セキュアブート環境でこれを動かすためには署名がなされていないといけません。

現在どのようなカーネルも―ジュールが利用されているかは「lsmod」から確認することができます。追加は「modprobe モジュール名」で、削除は「modprobe -r モジュール名」で操作することができます。

/etc/modules-load.dに設定ファイル(.conf)を置き、中にモジュール名を書き込むことで、「モジュール名.ko」という拡張子がついたカーネルモジュールを読み込むようになります。この時ハイフン(-)とアンダーバー(_)は区別しないそうです。

また/etc/modprobe.dに設定ファイル(.conf)を置き、「options モジュール名 パラメータ」と記載することで、モジュールにオプションを設定することができます。

ここでoptionsの代わりに、「blacklist モジュール名」とすれば、デフォルトで読み込む設定なっているモジュールの読み込みをとめることができます。

update-initramfs -uコマンドは、initramfsを更新するコマンドです。Gihyo.jp:「第384回 Initramfsのしくみ」によると、initramfsは「ミニルート」のひとつでシステムをマウントするためにメモリ上に展開される仮のルートファイルシステム(イメージ)です。この中のカーネルモジュールの設定を変更します。

ちなみに各モジュールの詳細は「modinfo モジュール名」とすることで表示されます。今回のnouveauを表示させると次のような行で始まるメッセージが表示されました。例えば、これでプログラム本体ファイルがどこにあるのかがわかります。


$ modinfo nouveau
filename: /lib/modules/5.4.0-73-generic/kernel/drivers/gpu/drm/nouveau/nouveau.ko
...

ドライバの署名

nouveauを正しく設定するとインストーラーは次のように続きます

まずセキュアブートを検知して、署名をするかきいてくるので、する方を選択します。


The target kernel has CONFIG_MODULE_SIG set, which means that it supports
cryptographic signatures on kernel modules. On some systems, the kernel may
refuse to load modules without a valid signature from a trusted key. This
system also has UEFI Secure Boot enabled; many distributions enforce module
signature verification on UEFI systems when Secure Boot is enabled. Would
you like to sign the NVIDIA kernel module?

<Sign the kernel module> Install without signing

次に署名用の鍵のセットを作成するか聞いてきます。先に紹介したようにMOK用の鍵を用意したので「Use...」側を選んで秘密鍵と証明書を指定します。新たに作成するならGenerate...側を指定します。新規作成の場合、先とはまた別の場所に鍵のセットができますので、証明書の方を先の手順でUEFIに登録する必要があります。


Would you like to sign the NVIDIA kernel module with an existing key pair,
or would you like to generate a new one?

<Use an existing key pair> Generate a new key pair

鍵の場所を指定します。入力順は先に秘密鍵、そのあとに証明書(公開鍵)になります。


Please provide the path to the private key: /var/lib/shim-signed/mok/MOK.priv
Please provide the path to the public key: /var/lib/shim-signed/mok/MOK.der

あとはメッセージの確認と、32bitやXの設定です。環境に合わせてた選択をしてください。

インストールが完了したら「nvidia-smi」コマンドで確認します。トップ画像のような表がでてきたらドライバのインストールは成功しています。

ちなみにNVIDIA製のrunファイルを使ったインストールを取り消したい場合は、--uninstallオプションをつけて実行すれば削除されます。

Debian環境

筆者がよく使うのはDebianなので、そちらでも設定してみたいと思います。

Debianの公式ドキュメント「セキュアブート」に詳しいことは掲載されていますが、MOK.derを作成するためのコマンドupdate-secureboot-policy --new-keyに相当するものがなくOpenSSLで作成するようです。opensslが存在しないようならインストールしてください。

# openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -days 36500 -subj "/CN=My Name/" -nodes

これでMOK.privとMOK.derが作成されましたのでUbuntuの時と同様に作業を進めます。環境によってはmokutilが存在しないこともあります。存在しない場合はこちらもaptでインストールしてください。

MOK.derをUEFIに登録した後、NVIDIAのドライバに実行権限をつけて実行したところ、Nouveau kernel driverの件はインストーラーに従った後再起動するだけで解決できましたが、今度は別の問題が発生しました。

Unable to find the kernel source tree for the currently running kernel. Please make sure you have installed the kernel source files for your kernel and that they are properly configured; on Red Hat Linux systems, for example, be sure you have the 'kernel-source' or 'kernel-devel' RPM installed. If you know the correct kernel source files are installed, you may specify the kernel source path with the '--kernel-source-path' command line option.

カーネルツリーが見つからないのだそうです。

カーネルとはOSの中核となる部分です。

カーネルのバージョンはOSのバージョンとは別に存在し、その情報をみたい場合はABKのメモブログによれば、unameコマンドを利用するようです。

aオプションで全ての情報が表示されます。カーネル名、ホスト名、カーネルのリリース番号、バージョン(#1から日付まで)、ハードウェア名、OSの順で表示されます。

uname -a
Linux debianPC 4.19.0-10-686-pae #1 SMP Debian 4.19.132-1 (2020-07-24) i686 GNU/Linux

Linuxのソースやヘッダはaptからlinux-sourceやlinux-header s-...を指定してインストールすることはできますが、それではエラーは回避できませんでした。そこで今度は、module-assistantというツールを使ってみたらうまくいきました。これはDebianのカーネルモジュールをビルドする際に利用するツールです。

インストールしたm-aにprepareをつけて実行すると環境の構築をしてくれます。

# apt install module-assistant
...
# m-a prepare
...

この後、再度.runファイルを起動します。あとはUbuntuと同じ流れです。MOK.privとMOK.derがある場所だけ違うと思いますので指定する際は注意してください。


参考にさせていただきました、サイトの皆様ありがとうございました。

筆者紹介


自分の写真
がーふぁ、とか、ふぃんてっく、とか世の中すっかりハイテクになってしまいました。プログラムのコーディングに触れることもある筆者ですが、自分の作業は硯と筆で文字をかいているみたいな古臭いものだと思っています。 今やこんな風にブログを書くことすらAIにとって代わられそうなほど技術は進んでいます。 生活やビジネスでPCを活用しようとするとき、そんな第一線の技術と比べてしまうとやる気が失せてしまいがちですが、おいしいお惣菜をネットで注文できる時代でも、手作りの味はすたれていません。 提示されたもの(アプリ)に自分を合わせるのでなく、自分の活動にあったアプリを作る。それがPC活用の基本なんじゃなかと思います。 そんな意見に同調していただける方向けにLinuxのDebianOSをはじめとした基本無料のアプリの使い方を紹介できたらなと考えています。

広告