1. 概要

ロード可能なカーネルモジュールを使用してカーネルを変更することも可能であるため、カーネルを不明または信頼できない状態にすることもできます。 これが発生すると、カーネルが汚染されていると言います。 カーネルがそれ自体を汚染しているとマークした場合、ほとんどの場合、カーネルの実行に問題はありません。 この情報は、誰かが問題やバグを調査したい場合にのみ関連性があります。

この段階では、コミュニティはそれが期待どおりに機能することを保証できません。

2. 汚染状態

汚染ステータスは、カーネル開発者がカーネルの問題を調査できない特定の条件を識別するためのフラグのセットです。たとえば、独自のカーネルモジュールが問題を引き起こした場合、そのモジュールが原因で確実にデバッグできません。ソースコードは利用できず、その影響を判断することはできません。

同様に、以前に重大なカーネルまたはハードウェア障害が発生した場合は、カーネルスペースの整合性が損なわれている可能性があります。つまり、カーネルによって生成される後続のデバッグメッセージは信頼できない可能性があります。

2.1. カーネルエラーのデコードステータス

各カーネルのバグ、おっと、またはパニックエラーレポートには、上部に汚染されたフラグが含まれています。

「汚染されていない」カーネルのバグは次のとおりです。

BUG: unable to handle kernel paging request at ffffc90012a9c418
Oops: 0000 [#1] SMP
Modules linked in: parport_pc ppdev bnep rfcomm bluetooth libahci ...
CPU: 6 PID: 2925 Comm: ryzom_client Not tainted 3.10.0-031000rc5-generic #201306082135
Hardware name: Gigabyte Technology Co., Ltd.
task: ffff880414908000 ti: ffff880403afc000 task.ti: ffff880403afc000
RIP: 0010:[<ffffffffa03a2ace>] [<ffffffffa03a2ace>] radeon_fence_process+0x8e/0x160 [radeon]
[...]

「CPU:」で始まる行に「汚染されていない:」があります。これは、カーネルが汚染されていないことを意味します。

別のバグ、今回は汚染されたカーネルを見てみましょう。

BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
Oops: 0002 [#1] SMP PTI
CPU: 0 PID: 4424 Comm: insmod Tainted: P         W O 4.20.0-0.rc6.fc30 #1
Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
RIP: 0010:my_oops_init+0x13/0x1000 [kpanic]
[...]

ここに、「Tainted:PWO」があります。 「汚染された:」の後のフラグ文字は、文字または空白である可能性があります。 これらの文字で状態をデコードできます。 一般的なフラグのいくつかは次のとおりです。

  • P:これは、プロプライエタリライセンスモジュールがカーネルにロードされていることを意味します。 これは、GNU General Public License(GPL)または互換性のあるライセンスの下にないモジュールである可能性があります。
  • G:ロードされたすべてのモジュールは、GPLまたはGPLと互換性のあるライセンスの下でライセンスされていますが、他の何かがカーネルを汚染しています。 別のフラグがそれを示します。
  • F:これは、insmodまたはmodprobeのForceオプション-fを使用してロードされたモジュールであるため、バージョン情報を確認できません。
  • M:これは、ハードウェアに関連する問題を示すためにハードウェアによってトリガーされるマシンチェック例外(MCE)です。

その他のフラグについては、 kerneldocsを確認してください。

2.2. 実行時のデコードステータス

実行時にシステムの汚染状態を確認できます。

$ cat /proc/sys/kernel/tainted

たとえば、コマンドが 0 を返す場合、カーネルは汚染されていません。 同様に、コマンドが 4609 を返す場合、それを使用して理由をデコードできます。 このために、さまざまなカーネルツールから出荷されたスクリプトがあります。

ここに、デコードを行うための簡単なスクリプトがあります。

$ for i in $(seq 18); do echo $(($i-1)) $((4609>>($i-1)&1));done
0 1
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 1
10 0
11 0
12 1
13 0
14 0
15 0
16 0
17 0

これで、前述のドキュメントでこれらの数値を確認して、理由を見つけることができます。 私たちの場合、理由は次のとおりです。

  • 0:プロプライエタリモジュールがロードされました
  • 9:カーネルが警告を発行しました
  • 12:外部で構築された(ツリー外の)モジュールがロードされました

2.3. 汚染を排除する

前の例のようなバグレポートを見て、次のような行でセクションを確認してみましょう。

Oops: 0000 [#1] SMP

括弧内の#1 が示すように、これは起動後の最初のOopsです。 すべてのOopsおよびそれ以降に発生するその他の問題は、両方が無関係に見える場合でも、最初のOopsのフォローアップ問題である可能性があります。 最初のOopsの原因を取り除き、後で問題を再現することで、これを除外します。

この場合、カーネルの再構成または更新も役立つ場合があります。 汚染の原因を元に戻した後も、ステータスは永続的です。 たとえば、プロプライエタリカーネルモジュールをアンロードしたり、ハードウェアエラーを修正したりしても、カーネルは汚染されたままになります。 汚染フラグをリセットするには、システムを再起動する必要があります。

さらに、システムがNvidia独自のグラフィックスドライバー、VirtualBox、または外部ソースなどのカーネルモジュールをインストールするソフトウェアを使用する場合、カーネルはそれ自体を汚染します。 ここでは、通常、実際の問題を再現する前に、モジュールを一時的にアンインストールします。

ただし、汚染の理由がカーネルソースのステージングツリーにあるモジュールである場合は、問題を報告できますが、モジュールが汚染の唯一の理由であることを確認する必要があります。

3. 結論

Linuxカーネル開発者に問題を報告するには、最初に汚染を排除する必要があります。 ステータスをデコードすると、カーネルが汚染されたさまざまな理由がわかります。

このように、汚染ステータスは、Linuxカーネルに関する問題を調査して修正するプロセスを支援します。