カーネルモジュールパッケージ

移動先: 案内, 検索

カーネルモジュールパッケージ (KMPs) は、カーネルのアップデートが生じた場合、誰もがそれぞれのカーネルモジュールを安全に取り扱える形でパッケージング作業を行うための仕組みです。

kABI の安定性

ロードされたカーネルモジュールは、Linux カーネルの一部としてカーネルの全てのデータ構造にアクセスします。当然このことから、カーネルモジュールは正確なカーネル設定、正確なコンパイル指定、そして最も重要である正確なソースコードで厳密にコンパイルされている必要があります。通常、コンパイル時にエクスポート指定したシンボルだけがアクセスされますが、現実として、近頃の2.6カーネルにおいてはエクスポートされるカーネルのシンボル数が6000以上になります。

カーネル内部インターフェース (kABI) は非常に移り気で頻繁に変更されるという事実から、カーネルのアップデートはいくつかのインターフェースを全く容易に変更できる能力を持つ必要があります。この能力により、古いバージョンのためにコンパイルされたカーネルモジュールを破棄することができます。幸いこれはシンボルのバージョン記述によって検出することができるので、カーネルに古いバージョンのモジュールをロードすることや不正データが発生することを未然に防止することになります。

カーネルモジュールの歴史

このカーネルとカーネルモジュールとの間の密接な関係は、SUSE/Novell を含むディストリビューターがこの2つを一緒にコンパイルし、RPM 形式の一括カーネルバイナリとして提供していたという経緯にさかのぼります。全てのカーネルモジュール(ほとんどはドライバーの類ですが)はカーネル内に取り込むことが要求されたので、カーネルのセキュリティーアップデートのたびにユーザーによって再コンパイルする必要がありました。

このカーネルモジュールの扱い方によるアプローチでは、次のような制約がありました。

  • ツリーにカーネルモジュールを受け入れようとする意欲にも関わらず、サードパーティーが作成したカーネルモジュールを含んだカーネルアップデートを行う場合、正しく扱う方法が提供されない。最悪の場合、明らかにユーザーエクスペリエンスの上では最も好ましくない、カーネルアップデート後にシステムがブートできないという状況を引き起こす。
  • カーネルモジュールは常に提供されるとは限らない。法的規制の存在により、ソースコードの品質や移植性、テストの実現性(テストを行うためのハードウェア資源不足、人手や知識不足のため)が損なわれてしまう。
  • 時にはカーネルモジュールの作成がディストリビューションのリリースまでに間に合わないために、カーネルモジュールやドライバー(または新しいバージョンのカーネルモジュール)を後から提供するという提供側の一方的な都合の良いやり方によって先送りにされてしまう。

カーネルモジュールパッケージの登場

そのアイデアは、カーネルモジュールをディストリビューターが提供する RPM 形式のカーネルバイナリの一部としてではない形で、安全に統合することにあります。誰もが正しい知識さえあれば、特定のカーネルのバージョンに適合し、正しく動作するカーネルモジュールを作成することができます。これを解決するための難しい問題は、カーネルのセキュリティーアップデートの際に提供されているカーネルモジュールの機能性が保たれるようにメンテナンスすることです。モジュールは新しいカーネルでも利用可能であれば再利用することができますし、そうでない場合は再コンパイルを必要とします。

このような問題に対応するため、カーネルの更新時には下記のような処理が動作します:

  • サードパーティ製のドライバの存在を調べる
  • それぞれのモジュールに対して、新しいカーネルで動作するかどうかを調べる (必要なすべてのシンボルとバージョンが提供されていることを確認する)
    • 動作することが期待される場合は、新しいカーネルへの対応は完了しているものとみなす
    • 動作することが期待できない場合は、さらに下記を実施:
      • 新しいカーネルモジュールの RPM をダウンロードする
      • 上記が提供されていない場合は、エラーメッセージを表示する (既定では更新を中断する)

これがユーザ側での処理のすべてです。いったんカーネルモジュールのパッケージがインストールされれば、更新は必要に応じてダウンロードされ、インストールされます。

しかし、上記のような処理を動作させるため、ディストリビュータたモジュールの提供者は、いくつかの作業を実施しています:

新しいカーネルモジュールが再コンパイルされて提供されるようにするため、ディストリビュータはそれらのモジュールを登録するように促すことがあります; モジュールの作成者は、これによって kABI の変更通知を受けられるようになり、そこから作業を始められるようになります。このような通知は必ずしも行なうべきものではありませんが、カーネルをリリースする前にかかる時間を削減することにつながります。 openSUSE の Build Service でも、今後このような機能を提供する予定です。

それ以外にも、ディストリビュータは自分自身で再コンパイルすることもできます。 Novell では Novell Partner Engineering (以前は Developer Services という名前でした) にある方法で、追加のモジュールをサービスとしてパートナーに提供しています。興味のある方は、 Linux ドライバ のページで詳細な情報を入手してください。

kABI が変更された場合も、単に変更後のカーネルソースに対してモジュールを再コンパイルするだけで、作業は完了します。これは Novell のポリシーによるもので、セキュリティアップデートでコードの変更 (kAPI の変更) を必要としないためです。これは SLES サービスパックについても同様ですが、すべての場合において可能というわけではありません。たいていの場合、再コンパイルによってこれらの問題を回避できますが、これは Novell が現行のカーネルに対して変更点を精査し、 SLES や SUSE Linux のセキュリティやメンテナンスの更新では kABI の変更が発生しないようにしているためです。しかしながら、 SLES サービスパックは kABI を部分的に変更する場合があるほか、 openSUSE Factory のカーネルは kABI を頻繁に変更して、提供元の開発に追随するようにしています。

カーネルモジュールのパッケージ形式

カーネルとモジュールとの互換性を確認する際には、 2 種類の異なる仕組みを利用しています。これは SUSE Linux のバージョンによっても異なります。 SLES9SP3/NLD9SP3/OESv1SP2/SUSE Linux 10.0 (Code9 と呼ばれるバージョン) の場合、 kernel-update-tool と呼ばれる個別のツールが存在していて、これで互換性を確認しています。 このツールはカーネルの更新時に呼び出され、確認とダウンロードのすべてを行ないます。 SLES10/SLED10/OESv2/SUSE Linux 10.1 (Code10 と呼ばれるバージョン) またはそれ以降のバージョンでは、同様の機能は通常のシステムインストールと設定、および更新の各ツールに統合されています。したがって、カーネルのシンボル情報は RPM の依存関係として割り当てられ、依存関係の解決器が利用可能なインストールまたは更新ソースを参照して、必要なモジュールのダウンロードや満たされていない依存関係の解決を実施しています。

カーネルモジュールのパッケージは通常の RPM と同じ形式で、カーネルモジュールそれ自身 (.ko ファイル) と少しのメタデータを含んでいます。サードパーティ製のカーネルモジュールについても、 openSUSE のパッケージ仕様に準拠して識別や更新の検知方法などを設定する必要があります。パッケージ仕様については、それぞれ Code9 (openSUSE 10.0 および SLES9 向け), Code10 (openSUSE 10.1 および SLES10 向け), Code11 (openSUSE 11.1 および SLES11 向け) をお読みください。

更新をダウンロードできるようにするには、さらにいくつかの作業を実施する必要があります。 Code9 の場合、特定の構造を持った http (または ftp) サーバを用意して RPM を配置する必要があるほか、 Code10, Code11 の場合は、 YaST のインストールソースの形式 (yum 形式 を推奨します) を用意する必要があります。 Code11 の場合は、 rpm-md 形式のリポジトリでも動作します。

他の RPM と同様に、カーネルモジュールのパッケージにも GnuPG の署名を付与する必要があります。更新プログラムは、この署名をチェックして、署名されていない場合や不明な発行者が署名している場合、もしくは署名が正しくない場合にそれぞれ警告を表示します。対象のパッケージをはじめてインストールする場合、インストール向けのマニュアルやスクリプトには、モジュールパッケージにある GnuPG の署名鍵をキーリングに取り込み、信頼する発行元としてマークするように推奨しています。鍵の取り込みは秘密裏に行なわれるわけではありませんが、管理者がパッケージのインストールに対して明確に同意したことを示す証拠となります。

初回のモジュールインストール

ここまでの説明では、サードパーティ製のカーネルモジュールがどのようにして更新に対応し、ユーザへのトラブルを防止しているのかを説明してきました。でも、追加のモジュールをはじめてインストールする場合は?

  • モジュールのパッケージは製品の一部として提供されている場合があります。製造元はドライバ CD やその他のソフトウエア配布方法で、 RPM を公開していることがあります。 Code10 の場合、更新元を登録し RPM キーリングに GnuPG 署名鍵を登録するための簡易なスクリプトが用意されていますので、これを実行することをお勧めします。
  • モジュールのパッケージはダウンロードすることができる場合があります。 RPM は単純にダウンロードすることができる (Code9) ほか、インストール時 (またはそれ以降) にインストーラや更新プログラムに対して、ダウンロードする場所を指定することもできます (Code10/11) 。
    • ダウンロードサイトは製造元のサイト内で検索することができるほか、製造元が提供する文書内に記されている場合や、 openSUSE が提供するヒント情報や検索エンジンなどで見つけることができます。
    • エンドユーザに対する検索の手間を省くため、ソフトウエアやドライバのポータルを提供して自動的な仕組みを用意し、 YaST に後からインストールや更新元として登録できるようにしておくとよいでしょう。検出されたハードウエアを動作させるパッケージを提供することは、デザイン面での要件でもあります。

パッケージの形式仕様では、作成されたモジュールとカーネルのバージョンの一致についても考慮されていますが、システムにインストールされているカーネルと互換性がある場合は、従来のモジュールを使用するようになっています。

サポートと認証

サポートと認証はエンタープライズ製品 (SLES, NLD/SLED, OES) についてのみ関係する項目です。 また、本章における "サポート" とは、顧客が提供元に対してサポートを要求し、報告した問題に対して個別の配慮 (技術サポートを含む) を保障させることができるものを指します。

カーネルモジュールはカーネルのアドレス領域にアクセスできる仕組みであるため、安定性や信頼性を容易に脅かすことができることができてしまいます。 Novell にとって不明なモジュールは "unsupported" (未サポート) という状態に置かれ、それらのモジュールが読み込まれる際には警告メッセージが syslog に記録され、カーネルを "taint" (汚染) という状態にします。ユーザがこのような未サポートなモジュールを読み込んでいる場合、 Novell はカーネルでの問題をあまり深く調べることはしません。その代わり、デバッグ可能な状況にする目的で、それらのモジュールを読み込まずに問題を再現させるように促します。

しかしながら、モジュールの製造元は、そのモジュールを "eXternally supported" (外部サポート済み) の状態にすることができます。これは Novell と密接に作業を進める必要がある必要はありません。 Novell サポートに対して、適切なサポート用の連絡先を公開し、顧客側で発生した問題を連携して調べることができるようにするだけです。また、モジュールの製造元は、 SLES のサポート期間にあわせてモジュールをメンテナンスすることに合意しなければなりません。そのほか、上述のルールのとおりにカーネルモジュールのパッケージを構築する必要があります。 Novell が提供するビルドサービス (Novell Partner Engineering) を利用して構築するのが最適です。この方法で構築されたモジュールは、テストと認証確認作業が行なわれ、認証済みのシステムとして公開されるようになります。

固有の仕組み

spec ファイル内には、下記のように kernel-syms (kernel-devel パッケージをインストールするようになります) と modutils を指定してください。

Requires: kernel-syms modutils
SourceN: %name-kmp-preamble

また %description の前には、 kmp サブパッケージを提供するため、下記のように指定してください:

%kernel_module_package -p %name-kmp-preamble -x ec2 xen

-p のパラメータは、各 kmp サブパッケージに対して、追加の RPM タグを指定するためのものです。また、 -x フラグを指定すると、これらのカーネルのフレーバーに対して、構築から除外することができます。逆に構築対象のフレーバーのみを指定したい場合は、フレーバー名のみを単純に指定してください。

タグによっては、空の "KMP" サブパッケージのタグを情報源とするものがあります:

%package KMP
Summary: The kernel modules for xyz
Group: System/Kernel

%description KMP
This provides blahblah.

kmp を前置きしたファイルでは、 %1 はフレーバー, %2 はパッケージのバージョンに置き換えられます。このファイル内では、 1 つ以上の下記の行を含めることができます:

  • Enhances: kernel-%1
    "Enhances" は "Suggests" を逆から指定する意味を持ちます。 kernel-(フレーバー) パッケージのインストールの際、 mypkg-kmp-(フレーバー) サブパッケージが提案されるようになります。
  • Supplements: packageand(kernel-%1:%name)
    "Supplements" は "Recommends" を逆から指定する意味を持ちます。システム内に kernel-(フレーバー) パッケージをインストールしようとしたりインストール済みである場合、 mypkg-kmp-(フレーバー) パッケージが推奨されるようになります。

それぞれの kmp は "mypkg-kmp" と "mypkg-mkmp-(フレーバー)" をそれぞれ提供します。