セキュリティ・キャンプ全国大会2019 解析トラック E5

The SYZBOT CTF

2019.8.15

目次


第0章 概要


Google 社が開発したファジングテスト用システムである syzbot が、 Linux などのOSカーネルの不具合をものすごい勢いで発見し続けています。OSカーネルという性質上、ユーザモードで動作するプログラムには該当しない様々な制約があります。また、ほとんどの処理を自動化して、膨大な数のテスト用マシンで並列実行させるという構成ならではの制約もあります。そのため、問題発生時に情報を取得し、問題の原因個所を突き止め、原因を修正していく作業には、かなりの試行錯誤を伴います。

syzbot.png

この講義では、 syzbot が見つけた Linux カーネルの不具合の修正に全力で取り組んでいる講師が、その体験談を紹介します。C言語によるプログラムを読み書きできるスキルを有した受講者を想定しています。


0.1 syzbot とは?

ファジングテスト( fuzzing test )を行うシステムです。

脆弱性と判断される挙動を発見してしまうこともありますが、脆弱性スキャナという訳ではありません。

正確には syzbot と syzkaller という区別がありますが、この講義では両者を区別せずに syzbot と呼んでいます。

ファジングテストにより見つかった不具合の状況を追跡できるようになっています。

カーネルがクラッシュしたら不具合として報告します。

「問題を検知した場合には、深刻度に関わらずカーネルパニックで停止させる」という設定でテストを行います。クラッシュはもちろん、ハングアップ/ストール/ロックアップ/不正なメモリアクセスなど、デバッグ支援機構が問題を報告した場合にもカーネルパニックで停止させるため、相当な件数が不具合として報告されます。

およそ1回/秒のペースでクラッシュが発生するほどの規模(並列度)で稼働しているようです。

https://github.com/google/syzkaller/issues/491

クラッシュが発生してから既知の事象であるかどうかの判断が行われるまでに時間差があり、結論が出るまでの間メモリダンプ( kdump )を保持しようとするとリソースが足りなくなります。

 そのため、せっかく問題発生時にカーネルパニックで停止させる設定になっていても、カーネルパニック時点のメモリダンプを取得して解析することが現実的ではありません。

 また、メモリダンプで知ることができるのは「その瞬間」の内容だけであり、その前の数分間にどんな処理をしていたのかを知ることはできません。

その結果、クラッシュ発生時のカーネルメッセージを中心に判断することになります。

 いかにして問題となる事象に関連するメッセージを捕捉できるかが重要になります。

大規模なテストが行えるように、ほとんどの処理が自動化されています。

不具合を再現するためのプログラム( reproducer )を提示しようとします。

 手元の環境でも再現できる reproducer が見つかれば、解析/修正/テストが容易になります。

クラッシュ発生時のカーネルメッセージ(ダイイングメッセージ)から、疑わしいサブシステムを推測します。ただし・・・

 原因を特定してから報告する訳ではないので、判断が誤っていることもあります。

 クラッシュ発生時のカーネルメッセージだけでは解析できず、お手上げとなることもあります。

 残念なことに、報告を受けとった人が多忙すぎて、放置されてしまうというケースが最も多いです。

だから、問題を報告する側と問題を修正する側の間のギャップを埋める存在が必要になります。

もっと詳しく知るには?

英語ですが https://elinux.org/Syzbot_survey_response のQ&Aが良いと思います。


0.2 主な登場人物紹介?


0.3 自己紹介:熊猫の Linux との関わりについて

OSレベルでのセキュリティ強化

2003年4月から2012年3月までは、 TOMOYO Linux という Linux システム向けのアクセス制御モジュールの開発に携わってきました。

TOMOYO Linux のメインライン化にまつわる苦労話は、セキュリティ&プログラミングキャンプ2011の講義資料を参照していただければと思います。

 http://I-love.SAKURA.ne.jp/tomoyo/spc2011-kumaneko.pdf

TOMOYO Linux から始まって AKARI や CaitSith に至るまでの変遷は、セキュリティ・キャンプ2012の講義資料を参照していただければと思います。

 http://I-love.SAKURA.ne.jp/tomoyo/CaitSith-ja.pdf

ShellShock のような、OSコマンドインジェクション脆弱性への対処に興味のある方は、セキュリティ・キャンプ2015の講義資料を参照していただければと思います。

 http://I-love.SAKURA.ne.jp/tomoyo/scamp2015-kumaneko.pdf

独自アクセス制御モジュールの作り方について勉強したい方は、セキュリティ・キャンプ2017の講義資料を参照していただければと思います。

 http://I-love.SAKURA.ne.jp/tomoyo/scamp2017-kumaneko.html

Linux システムのトラブルシューティング

2012年4月から2015年3月までは、サポートセンタで Linux が関係するシステムの故障解析に携わってきました。

その時に偶然発見してしまったメモリ管理の闇に関して、 Linux 4.8 時点までの話はセキュリティ・キャンプ2016の講義資料を参照していただければと思います。

 http://I-love.SAKURA.ne.jp/The_OOM_CTF.html

また、 Linux が関係するシステムの問題を解決するためにサポートセンタを上手に活用するための話は、セキュリティ・キャンプ2018の講義資料を参照していただければと思います。

 http://I-love.SAKURA.ne.jp/tomoyo/scamp2018-kumaneko.pdf

Linux カーネルの品質向上

サポートセンタを去ってからも、メモリ管理の闇を巡る戦いは続いている訳ですが、その中でも、2018年1月にリリースされた Linux 4.15 は1つの節目を迎えました。

 http://www.intellilink.co.jp/all/topics/20180222/linux-kernel4_15.html

2017年11月頃からは、 syzbot が見つけた Linux カーネルの不具合を巡る戦いが中心になってきました。その中でも、2019年5月にリリースされた Linux 5.1 は syzbot にとって1つの節目を迎えると考えたため、今年のセキュリティ・キャンプのテーマに選びました。


0.4 今日のお話「バグハンティング」

意図せず埋め込まれた不具合を探します。

意図的に不具合や脆弱性を埋め込む「普通のCTF」とは違います。

問題の原因個所/修正方法が不明な状況ですので、かなりの試行錯誤を伴います。

自分が書いたものではないプログラム(自分が詳しくない領域)の不具合を扱うことになりますので、簡単な不具合であれば自分で修正パッチを作成してしまいますが、複雑な不具合の場合には(詳しい人に)修正パッチを作成してもらえる状況を作るためのギャップを埋める役割の人として動くことになります。

セキュリティ・キャンプ2018の講義資料でいうところの「ゼネラリスト」側の役割です。

今日紹介するのは、自動化できない領域を補っている熊猫の体験談の一部です。


第1章 Linux カーネルについて


1.1 Linux カーネルの規模について

カーネルのソースコードが2000万行を超えています。

$ cloc linux-5.0
   63092 text files.
   62630 unique files.
   12589 files ignored.

github.com/AlDanial/cloc v 1.70  T=289.13 s (174.8 files/s, 83847.4 lines/s)
---------------------------------------------------------------------------------------
Language                             files          blank        comment           code
---------------------------------------------------------------------------------------
C                                    26629        2636275        2297910       13421317
C/C++ Header                         19168         499596         920551        3748615
Assembly                              1324          47238         105013         229677
JSON                                   213              0              0         137286
make                                  2442           8984           9604          39367
Bourne Shell                           453           8528           7029          35031
Perl                                    54           5413           4000          27388
Python                                 116           3691           3890          20090
HTML                                     5            656              0           5440
yacc                                     9            697            376           4616
lex                                      8            330            321           2004
C++                                      8            290             82           1853
YAML                                    22            316            242           1849
Bourne Again Shell                      51            352            318           1722
awk                                     11            170            155           1386
TeX                                      1            108              3            915
NAnt script                              2            143              0            540
Markdown                                 2            133              0            423
Windows Module Definition                2             14              0            102
m4                                       1             15              1             95
CSS                                      1             27             28             72
XSLT                                     5             13             26             61
vim script                               1              3             12             27
Ruby                                     1              4              0             25
INI                                      1              1              0              6
sed                                      1              2              5              5
---------------------------------------------------------------------------------------
SUM:                                 50531        3212999        3349566       17679912
---------------------------------------------------------------------------------------
$ cloc linux-5.1
   63830 text files.
   63367 unique files.
   12782 files ignored.

github.com/AlDanial/cloc v 1.70  T=309.13 s (165.2 files/s, 79147.3 lines/s)
---------------------------------------------------------------------------------------
Language                             files          blank        comment           code
---------------------------------------------------------------------------------------
C                                    26890        2659248        2310515       13538614
C/C++ Header                         19360         514628         924491        3785690
Assembly                              1325          47219         105103         229484
JSON                                   222              0              0         142205
make                                  2466           9049           9591          39736
Bourne Shell                           495           9683           8153          39653
Perl                                    54           5414           4001          27400
Python                                 119           4029           3946          21367
HTML                                     5            656              0           5446
yacc                                     9            697            376           4616
YAML                                    35            596            296           3317
lex                                      8            330            321           2004
C++                                      8            300             82           1871
Bourne Again Shell                      51            354            320           1748
awk                                     11            171            155           1387
TeX                                      1            108              3            915
NAnt script                              2            142              0            535
Markdown                                 2            133              0            423
Windows Module Definition                2             14              0            103
m4                                       1             15              1             95
CSS                                      1             27             28             72
XSLT                                     5             13             26             61
vim script                               1              3             12             27
Ruby                                     1              4              0             25
INI                                      1              1              0              6
sed                                      1              2              5              5
---------------------------------------------------------------------------------------
SUM:                                 51076        3252836        3367425       17846805
---------------------------------------------------------------------------------------
$ cloc linux-5.2
   64545 text files.
   64086 unique files.
   13018 files ignored.

github.com/AlDanial/cloc v 1.70  T=297.87 s (173.1 files/s, 82317.4 lines/s)
---------------------------------------------------------------------------------------
Language                             files          blank        comment           code
---------------------------------------------------------------------------------------
C                                    27168        2680389        2246068       13670742
C/C++ Header                         19469         510828         884634        3779249
Assembly                              1326          47105         101299         228994
JSON                                   236              1              0         151381
Bourne Shell                           517          10343           8084          41975
make                                  2492           9182          10496          40317
Perl                                    55           5446           3950          27536
Python                                 125           4261           3988          22096
YAML                                    57           1037            369           6162
HTML                                     5            656              0           5446
yacc                                     9            698            376           4627
lex                                      8            332            321           2013
C++                                      8            300             82           1871
Bourne Again Shell                      51            354            296           1748
awk                                     11            171            148           1387
TeX                                      1            108              3            915
NAnt script                              2            142              0            538
Markdown                                 2            133              0            423
Windows Module Definition                2             15              0            108
m4                                       1             15              1             95
CSS                                      1             27             28             72
XSLT                                     5             13             26             61
vim script                               1              3             12             27
Ruby                                     1              4              0             25
INI                                      1              1              0              6
sed                                      1              2              5              5
---------------------------------------------------------------------------------------
SUM:                                 51555        3271566        3260186       17987819
---------------------------------------------------------------------------------------

2万人を超える Linux カーネル開発者達が作成したパッチの集まりにより成り立っています。

$ git log v2.6.12-rc2...v5.0 | grep ^Author: | awk ' { $NF = ""; print $0; } ' | sort -u | wc -l
19799
$ git log v2.6.12-rc2...v5.1 | grep ^Author: | awk ' { $NF = ""; print $0; } ' | sort -u | wc -l
20090
$ git log v2.6.12-rc2...v5.2 | grep ^Author: | awk ' { $NF = ""; print $0; } ' | sort -u | wc -l
20372

Dmitry Vyukov さんによると、2万個を超える不具合が存在していると推定されています。

https://events.linuxfoundation.org/wp-content/uploads/2017/11/Syzbot-and-the-Tale-of-Thousand-Kernel-Bugs-Dmitry-Vyukov-Google.pdf


1.2 Linux カーネルの制約事項について

Linux と呼ばれているOSの内、「カーネルモード」で動作しているプロセスが Linux カーネルです。カーネルの仕事はいろいろありますが、ハードウェアを制御し、プロセスやユーザなどの隔離を行い、「ユーザモード」で動作しているプロセスに対して資源(メモリやCPU時間など)を配分するといった基本的な機能を提供します。

Linux カーネルには、ユーザモードで動作しているプロセスに対して資源(メモリやCPU時間など)を配分するといった基本的な機能を提供する上で必要となる、カーネルモードでの「制約事項」というものが存在します。

メモリの割り当てや問題発生時の影響範囲という観点での Linux カーネルの制約事項については、セキュリティ・キャンプ2017の講義資料で体験できます。

ここでは、プロセスのスケジューリング(CPU時間の配分)を例に、 Linux カーネルの制約事項を考えてみましょう。(ユーザモードにも制約事項は存在しますが、この講義では扱いません。)

ユーザモードで動作しているプロセスの場合:

ユーザモードで動作するプロセスの処理をカーネル側が自動的に中断/再開してくれる(処理の途中で中断しても想定外の結果が生じないように面倒を見てくれる)ため、ユーザモードで動作しているプロセスであれば、”何時間も”要するような処理であっても、気にせずに実行することができます。

カーネルモードで動作しているプロセスの場合:

カーネルモードで動作するプロセスの処理をカーネル側が自動的に中断/再開させることはできない(処理の途中で中断すると想定外の結果が生じる可能性がある)ため、カーネルモードで動作しているプロセスは、何かの処理に没頭して”何分間も”応答できないような状況に陥ってしまうことを避ける必要があります。

カーネルモードで割り込み処理を行っているプロセスの場合:

カーネルは、優先度の高い要求に迅速に応答できるようにするために、「割り込み処理」という方法を用います。カーネルモードで割り込み処理を行っている間は、その割り込み処理に没頭して”何秒間も”応答できないような状況に陥ってしまうことを避ける必要があります。


1.3 Linux カーネルのデバッグ支援機能について

syzbot の報告内容を理解するために必要になる、 Linux カーネルのデバッグ支援機能を用いて見つけることができる不具合の例について紹介します。全部のパターンを網羅している訳ではありませんし、実際に発生する結果は、カーネルコンフィグやハードウェアやタイミングなどの条件により変化しますので、不具合の原因とメッセージとが1対1で対応するとは考えないようにしてください。

ケース1:単純な panic() の例

panic() 関数は、「対処できない致命的な問題」が発生したときに、システムを強制停止させるために呼ばれます。明示的に panic() 関数を呼び出すことにより、どのようなメッセージが出力されるかを見てみましょう。

panic_test.c : panic() 関数を呼び出すカーネルモジュールの例

#include <linux/module.h>

static int __init panic_test(void)
{
        panic("STOP!");
        return -EINVAL;
}

module_init(panic_test);
MODULE_LICENSE("GPL");

kdump の設定が有効になっている場合、メッセージが出力された後、処理が kdump によりロードされたカーネルへと引き継がれます。 kdump により実行されるカーネルは、メモリダンプを取得して保存後、システムを再起動します。

[   56.892807] panic_test: loading out-of-tree module taints kernel.
[   56.900070] Kernel panic - not syncing: STOP!
[   56.901347] CPU: 5 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   56.903697] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   56.906723] Call Trace:
[   56.907432]  dump_stack+0x9a/0xf0
[   56.908417]  ? 0xffffffffc0dd0000
[   56.909446]  panic+0x1ed/0x3b8
[   56.910333]  ? __warn_printk+0xd6/0xd6
[   56.911501]  ? ___slab_alloc+0x668/0x750
[   56.912603]  ? 0xffffffffc0dd0000
[   56.913580]  panic_test+0x11/0x1000 [panic_test]
[   56.914966]  do_one_initcall+0xe2/0x553
[   56.916014]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   56.918116]  ? kasan_unpoison_shadow+0x30/0x40
[   56.919606]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   56.921071]  ? do_init_module+0x49/0x680
[   56.922251]  ? kmem_cache_alloc_trace+0x14b/0x340
[   56.923531]  ? kasan_unpoison_shadow+0x30/0x40
[   56.924889]  do_init_module+0x1da/0x680
[   56.926037]  load_module+0x43e8/0x56d0
[   56.927091]  ? layout_and_allocate+0x2140/0x2140
[   56.928477]  ? kernel_read+0x8b/0x130
[   56.929684]  ? kernel_read_file+0x225/0x4f0
[   56.930842]  ? __do_sys_finit_module+0x11a/0x1b0
[   56.932224]  __do_sys_finit_module+0x11a/0x1b0
[   56.933558]  ? __ia32_sys_init_module+0xa0/0xa0
[   56.934892]  ? __audit_syscall_exit+0x712/0x990
[   56.936290]  ? rcu_read_lock_sched_held+0x102/0x120
[   56.937755]  ? do_syscall_64+0x1d/0x450
[   56.938998]  do_syscall_64+0x9a/0x450
[   56.940063]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   56.941610] RIP: 0033:0x7f60ca1b61c9
[   56.942703] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   56.948181] RSP: 002b:00007fff0f520438 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
[   56.950456] RAX: ffffffffffffffda RBX: 0000000001fed1e0 RCX: 00007f60ca1b61c9
[   56.952502] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   56.954707] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007fff0f5205d8
[   56.956847] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
[   56.959838] R13: 0000000001fec120 R14: 0000000000000000 R15: 0000000000000000
[    0.000000] Linux version 5.0.0 (root@localhost.localdomain) (gcc version 8.2.1 20180905 (Red Hat 8.2.1-3) (GCC)) #1 SMP Mon Mar 25 11:37:59 JST 2019
[    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-5.0.0 ro security=none sysrq_always_enabled console=ttyS0,115200n8 console=tty0 LANG=en_US.UTF-8 irqpoll nr_cpus=1 reset_devices cgroup_disable=memory mce=off numa=off udev.children-max=2 panic=10 rootflags=nofail acpi_no_memhotplug transparent_hugepage=never nokaslr disable_cpu_apicid=0 elfcorehdr=867732K
[    0.000000] Disabled fast string operations
[    0.000000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
[    0.000000] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
[    0.000000] x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
[    0.000000] x86/fpu: Supporting XSAVE feature 0x008: 'MPX bounds registers'
[    0.000000] x86/fpu: Supporting XSAVE feature 0x010: 'MPX CSR'
[    0.000000] x86/fpu: xstate_offset[2]:  576, xstate_sizes[2]:  256
[    0.000000] x86/fpu: xstate_offset[3]:  832, xstate_sizes[3]:   64
[    0.000000] x86/fpu: xstate_offset[4]:  896, xstate_sizes[4]:   64
[    0.000000] x86/fpu: Enabled xstate features 0x1f, context size is 960 bytes, using 'compacted' format.
[    0.000000] BIOS-provided physical RAM map:

kdump の設定が有効になっていない場合、メッセージが出力された後、システムが停止します。 /proc/sys/kernel/panic の設定が 0 ではない場合、指定された秒数の経過後にシステムを再起動します。

[   64.628947] panic_test: loading out-of-tree module taints kernel.
[   64.635300] Kernel panic - not syncing: STOP!
[   64.636582] CPU: 2 PID: 9470 Comm: insmod Tainted: G           O    T 5.0.0 #1
[   64.638627] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   64.641659] Call Trace:
[   64.642348]  dump_stack+0x9a/0xf0
[   64.643335]  ? 0xffffffffc0d58000
[   64.644309]  panic+0x1ed/0x3b8
[   64.645205]  ? __warn_printk+0xd6/0xd6
[   64.646231]  ? ___slab_alloc+0x668/0x750
[   64.647471]  ? 0xffffffffc0d58000
[   64.648496]  panic_test+0x11/0x1000 [panic_test]
[   64.649805]  do_one_initcall+0xe2/0x553
[   64.650867]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   64.652666]  ? kasan_unpoison_shadow+0x30/0x40
[   64.653917]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   64.655403]  ? do_init_module+0x49/0x680
[   64.656476]  ? kmem_cache_alloc_trace+0x14b/0x340
[   64.657783]  ? kasan_unpoison_shadow+0x30/0x40
[   64.659140]  do_init_module+0x1da/0x680
[   64.660376]  load_module+0x43e8/0x56d0
[   64.661443]  ? layout_and_allocate+0x2140/0x2140
[   64.662634]  ? kernel_read+0x8b/0x130
[   64.663806]  ? kernel_read_file+0x225/0x4f0
[   64.664981]  ? __do_sys_finit_module+0x11a/0x1b0
[   64.666538]  __do_sys_finit_module+0x11a/0x1b0
[   64.668181]  ? __ia32_sys_init_module+0xa0/0xa0
[   64.669393]  ? __audit_syscall_exit+0x712/0x990
[   64.670685]  ? rcu_read_lock_sched_held+0x102/0x120
[   64.672043]  ? do_syscall_64+0x1d/0x450
[   64.673085]  do_syscall_64+0x9a/0x450
[   64.674080]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   64.675552] RIP: 0033:0x7fc2c25cc1c9
[   64.676525] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   64.681707] RSP: 002b:00007ffc3cbc53b8 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   64.684018] RAX: ffffffffffffffda RBX: 0000000000a1f1e0 RCX: 00007fc2c25cc1c9
[   64.685853] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   64.687969] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffc3cbc5558
[   64.689776] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   64.692665] R13: 0000000000a1e120 R14: 0000000000000000 R15: 0000000000000000
[   64.695769] Kernel Offset: 0x4000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[   64.704771] ---[ end Kernel panic - not syncing: STOP! ]---

ケース2:単純な BUG_ON() の例

BUG_ON() 関数(実際にはマクロです)は、「対処できない致命的な問題」が発生したときに、プロセスを強制終了させるために呼ばれます。明示的に BUG_ON() 関数を呼び出すことにより、どのようなメッセージが出力されるかを見てみましょう。

bug_on_test.c : BUG_ON() 関数を呼び出すカーネルモジュールの例

#include <linux/module.h>

static int __init bug_on_test(void)
{
        BUG_ON(sizeof(int) != sizeof(char));
        return -EINVAL;
}

module_init(bug_on_test);
MODULE_LICENSE("GPL");

BUG_ON() 関数が実行された個所(ソースコード中のファイル名/行番号)とメッセージが出力されます。 /proc/sys/kernel/panic_on_oops が 0 ではない場合、あるいは、スケジューリングが不可能な状況で発生した場合、カーネルパニック( panic() 関数の呼び出し)が発生します。なお、カーネル内のロックを保持している状態でプロセスを強制終了させてしまうと、不整合状態が発生してしまうことでカーネルが正常に動作することを期待できなくなります。そのため、現実的には /proc/sys/kernel/panic_on_oops が 0 であったとしても速やかにシステムを再起動させることが望まれます。

[   52.897173] bug_on_test: loading out-of-tree module taints kernel.
[   52.902508] ------------[ cut here ]------------
[   52.903825] kernel BUG at test/bug_on_test.c:5!
[   52.905123] invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI
[   52.906977] CPU: 2 PID: 9466 Comm: insmod Tainted: G           O    T 5.0.0 #1
[   52.908998] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   52.912057] RIP: 0010:bug_on_test+0x0/0x1000 [bug_on_test]
[   52.913640] Code: Bad RIP value.
[   52.914608] RSP: 0018:ffff88810189f950 EFLAGS: 00010286
[   52.916010] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000000001
[   52.918097] RDX: 1ffff11020acf39d RSI: ffff888105679cdc RDI: 0000000000000246
[   52.920087] RBP: 1ffff11020313f2d R08: ffffed10140ffb88 R09: 0000000000000001
[   52.922128] R10: ffffed10140ffb87 R11: ffff8880a07fdc3b R12: ffffffffc0cd0000
[   52.924224] R13: 0000000000000002 R14: dffffc0000000000 R15: ffffffffbda65064
[   52.926175] FS:  00007f3d9d182740(0000) GS:ffff8880a0600000(0000) knlGS:0000000000000000
[   52.928379] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   52.929888] CR2: ffffffffc0ccffd6 CR3: 0000000109836004 CR4: 00000000003606e0
[   52.932050] Call Trace:
[   52.932697]  do_one_initcall+0xe2/0x553
[   52.933674]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   52.935373]  ? kasan_unpoison_shadow+0x30/0x40
[   52.936573]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   52.937888]  ? do_init_module+0x49/0x680
[   52.939125]  ? kmem_cache_alloc_trace+0x14b/0x340
[   52.940315]  ? kasan_unpoison_shadow+0x30/0x40
[   52.941528]  do_init_module+0x1da/0x680
[   52.942661]  load_module+0x43e8/0x56d0
[   52.943681]  ? layout_and_allocate+0x2140/0x2140
[   52.944916]  ? kernel_read+0x8b/0x130
[   52.946028]  ? kernel_read_file+0x225/0x4f0
[   52.947157]  ? __do_sys_finit_module+0x11a/0x1b0
[   52.948387]  __do_sys_finit_module+0x11a/0x1b0
[   52.949685]  ? __ia32_sys_init_module+0xa0/0xa0
[   52.950886]  ? __audit_syscall_exit+0x712/0x990
[   52.952147]  ? rcu_read_lock_sched_held+0x102/0x120
[   52.953693]  ? do_syscall_64+0x1d/0x450
[   52.954724]  do_syscall_64+0x9a/0x450
[   52.955709]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   52.957285] RIP: 0033:0x7f3d9c6551c9
[   52.958248] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   52.965374] RSP: 002b:00007fff66911e48 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   52.968358] RAX: ffffffffffffffda RBX: 00000000026221e0 RCX: 00007f3d9c6551c9
[   52.971396] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   52.974411] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007fff66911fe8
[   52.977331] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   52.980444] R13: 0000000002621120 R14: 0000000000000000 R15: 0000000000000000
[   52.980450] Modules linked in: bug_on_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ata_generic pata_acpi vmwgfx drm_kms_helper ahci syscopyarea sysfillrect mptspi libahci e1000 sysimgblt scsi_transport_spi fb_sys_fops mptscsih ttm mptbase drm i2c_core ata_piix libata
[   52.980537] ---[ end trace 2cb03453b67058e0 ]---
[   53.008753] RIP: 0010:bug_on_test+0x0/0x1000 [bug_on_test]
[   53.011347] Code: Bad RIP value.
[   53.013306] RSP: 0018:ffff88810189f950 EFLAGS: 00010286
[   53.015953] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000000001
[   53.019160] RDX: 1ffff11020acf39d RSI: ffff888105679cdc RDI: 0000000000000246
[   53.022557] RBP: 1ffff11020313f2d R08: ffffed10140ffb88 R09: 0000000000000001
[   53.025635] R10: ffffed10140ffb87 R11: ffff8880a07fdc3b R12: ffffffffc0cd0000
[   53.028719] R13: 0000000000000002 R14: dffffc0000000000 R15: ffffffffbda65064
[   53.031883] FS:  00007f3d9d182740(0000) GS:ffff8880a0600000(0000) knlGS:0000000000000000
[   53.035336] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   53.038143] CR2: ffffffffc0ccffd6 CR3: 0000000109836004 CR4: 00000000003606e0

ケース3:単純な WARN_ON() の例

WARN_ON() 関数(実際にはマクロです)は、「致命的ではないが注意すべき問題」が発生したときに、警告メッセージを表示するために呼ばれます。明示的に WARN_ON() 関数を呼び出すことにより、 どのようなメッセージが出力されるかを見てみましょう。

warn_on_test.c : WARN_ON() 関数を呼び出すカーネルモジュールの例

#include <linux/module.h>

static int __init warn_on_test(void)
{
        WARN_ON(sizeof(int) != sizeof(char));
        return -EINVAL;
}

module_init(warn_on_test);
MODULE_LICENSE("GPL");

WARN_ON() 関数が実行された個所(ソースコード中のファイル名/行番号)とメッセージが出力されます。 /proc/sys/kernel/panic_on_warn が 0 ではない場合、カーネルパニック( panic() 関数の呼び出し)が発生します。

[   54.307215] warn_on_test: loading out-of-tree module taints kernel.
[   54.313936] WARNING: CPU: 3 PID: 9669 at test/warn_on_test.c:5 warn_on_test+0x0/0x1000 [warn_on_test]
[   54.316525] Modules linked in: warn_on_test(O+) vmw_balloon pcspkr sg ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter i2c_piix4 vmw_vmci ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ahci e1000 mptspi libahci ata_piix scsi_transport_spi mptscsih drm mptbase libata i2c_core
[   54.333309] CPU: 3 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   54.335554] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   54.338642] RIP: 0010:warn_on_test+0x0/0x1000 [warn_on_test]
[   54.340276] Code: Bad RIP value.
[   54.341160] RSP: 0018:ffff888091637950 EFLAGS: 00010286
[   54.342561] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000000001
[   54.344624] RDX: 1ffff1101282b39d RSI: ffff888094159cdc RDI: 0000000000000246
[   54.346533] RBP: 1ffff110122c6f2d R08: ffffed101417fb88 R09: 0000000000000001
[   54.348783] R10: ffffed101417fb87 R11: ffff8880a0bfdc3b R12: ffffffffc0e18000
[   54.350760] R13: 0000000000000003 R14: dffffc0000000000 R15: ffffffffb5a65064
[   54.353174] FS:  00007fa80d2b9740(0000) GS:ffff8880a0a00000(0000) knlGS:0000000000000000
[   54.356262] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   54.357882] CR2: ffffffffc0e17fd6 CR3: 00000000937c8004 CR4: 00000000003606e0
[   54.360011] Call Trace:
[   54.360722]  do_one_initcall+0xe2/0x553
[   54.361858]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   54.363590]  ? kasan_unpoison_shadow+0x30/0x40
[   54.364827]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   54.366201]  ? do_init_module+0x49/0x680
[   54.367298]  ? kmem_cache_alloc_trace+0x14b/0x340
[   54.368650]  ? kasan_unpoison_shadow+0x30/0x40
[   54.369793]  do_init_module+0x1da/0x680
[   54.370785]  load_module+0x43e8/0x56d0
[   54.371903]  ? layout_and_allocate+0x2140/0x2140
[   54.373087]  ? kernel_read+0x8b/0x130
[   54.374032]  ? kernel_read_file+0x225/0x4f0
[   54.375121]  ? __do_sys_finit_module+0x11a/0x1b0
[   54.376485]  __do_sys_finit_module+0x11a/0x1b0
[   54.378052]  ? __ia32_sys_init_module+0xa0/0xa0
[   54.379554]  ? __audit_syscall_exit+0x712/0x990
[   54.380719]  ? rcu_read_lock_sched_held+0x102/0x120
[   54.381974]  ? do_syscall_64+0x1d/0x450
[   54.383061]  do_syscall_64+0x9a/0x450
[   54.385080]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   54.387594] RIP: 0033:0x7fa80c78c1c9
[   54.389600] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   54.397831] RSP: 002b:00007ffcdc423828 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   54.397835] RAX: ffffffffffffffda RBX: 00000000014f51e0 RCX: 00007fa80c78c1c9
[   54.397837] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   54.397838] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffcdc4239c8
[   54.397840] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   54.397841] R13: 00000000014f4120 R14: 0000000000000000 R15: 0000000000000000
[   54.397856] irq event stamp: 4076
[   54.397862] hardirqs last  enabled at (4075): [<ffffffffb362692d>] __slab_alloc+0x6d/0x90
[   54.397865] hardirqs last disabled at (4076): [<ffffffffb300546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[   54.397869] softirqs last  enabled at (4012): [<ffffffffb4c00675>] __do_softirq+0x675/0x9e3
[   54.397872] softirqs last disabled at (4005): [<ffffffffb317fe64>] irq_exit+0x274/0x2c0
[   54.397874] ---[ end trace da4c86d8adf81304 ]---

ケース4:単純な hung task の例

カーネル内で行われる処理は、「スケジューリングが発生する可能性のある(アトミックではない)処理」と、「スケジューリングが発生する可能性のない(アトミックな)処理」の2種類があります。

「スケジューリングが発生する可能性のある処理」の中で、「シグナルによる中断が不可能な方法でスケジューリングを行う」場合、その状態が長時間続いてしまうと、プロセスがハングアップしていると判断されます。

「シグナルによる中断が不可能な方法で長時間のスケジューリングが発生した」場合に、どのようなメッセージが出力されるかを見てみましょう。

hung_task_test.c : hung task 警告メッセージを出力させるカーネルモジュールの例

#include <linux/module.h>
#include <linux/sched.h>

static int __init hung_task_test(void)
{
        schedule_timeout_uninterruptible(125 * HZ);
        return -EINVAL;
}

module_init(hung_task_test);
MODULE_LICENSE("GPL");

khungtaskd というカーネルスレッドが定期的にチェックを行い、ハングアップしたと判定したスレッドについての情報を報告します。なお、 /proc/sys/kernel/hung_task_panic が 0 ではない場合、カーネルパニック( panic() 関数の呼び出し)が発生します。

[   52.760967] hung_task_test: loading out-of-tree module taints kernel.
[  176.303150] INFO: task insmod:9669 blocked for more than 120 seconds.
[  176.305586]       Tainted: G           O    T 5.0.0 #1
[  176.307567] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  176.310654] insmod          D25640  9669   9654 0x80000080
[  176.312849] Call Trace:
[  176.313889]  ? __schedule+0x71f/0x18f0
[  176.315429]  ? __sched_text_start+0x8/0x8
[  176.317060]  ? _raw_spin_unlock_irqrestore+0x46/0x60
[  176.319174]  schedule+0x77/0x170
[  176.320500]  schedule_timeout+0x391/0xc50
[  176.322065]  ? trace_raw_output_initcall_finish+0xe0/0xe0
[  176.323918]  ? deactivate_slab.isra.70+0x5f9/0x630
[  176.325568]  ? usleep_range+0x120/0x120
[  176.326879]  ? do_init_module+0x49/0x680
[  176.328067]  ? do_init_module+0x49/0x680
[  176.329283]  ? set_track+0x71/0x120
[  176.330349]  ? __next_timer_interrupt+0xe0/0xe0
[  176.331714]  ? ___slab_alloc+0x668/0x750
[  176.332778]  ? 0xffffffffc0ff0000
[  176.333682]  hung_task_test+0xa/0x1000 [hung_task_test]
[  176.335397]  do_one_initcall+0xe2/0x553
[  176.336454]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  176.337975]  ? kasan_unpoison_shadow+0x30/0x40
[  176.339100]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  176.340379]  ? do_init_module+0x49/0x680
[  176.341395]  ? kmem_cache_alloc_trace+0x14b/0x340
[  176.342583]  ? __kasan_slab_free+0x126/0x150
[  176.343669]  do_init_module+0x1da/0x680
[  176.344655]  load_module+0x43e8/0x56d0
[  176.345640]  ? layout_and_allocate+0x2140/0x2140
[  176.346809]  ? kernel_read+0x8b/0x130
[  176.347748]  ? kernel_read_file+0x225/0x4f0
[  176.348829]  ? __do_sys_finit_module+0x11a/0x1b0
[  176.350483]  __do_sys_finit_module+0x11a/0x1b0
[  176.352545]  ? __ia32_sys_init_module+0xa0/0xa0
[  176.354439]  ? __audit_syscall_exit+0x712/0x990
[  176.356012]  ? rcu_read_lock_sched_held+0x102/0x120
[  176.357721]  ? do_syscall_64+0x1d/0x450
[  176.359071]  do_syscall_64+0x9a/0x450
[  176.361609]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  176.364388] RIP: 0033:0x7f3015c751c9
[  176.366341] Code: Bad RIP value.
[  176.367998] RSP: 002b:00007fff0c4f6158 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
[  176.370710] RAX: ffffffffffffffda RBX: 00000000021331e0 RCX: 00007f3015c751c9
[  176.373331] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  176.375952] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007fff0c4f62f8
[  176.378573] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
[  176.381573] R13: 0000000002132120 R14: 0000000000000000 R15: 0000000000000000
[  176.384294] 
[  176.384294] Showing all locks held in the system:
[  176.387362] 1 lock held by khungtaskd/54:
[  176.389204]  #0: 00000000ae7ad759 (rcu_read_lock){....}, at: debug_show_all_locks+0x52/0x2a7
[  176.392222] 2 locks held by agetty/9421:
[  176.394159]  #0: 000000009b27007a (&tty->ldisc_sem){++++}, at: tty_ldisc_ref_wait+0x22/0x80
[  176.397232]  #1: 00000000bc5bce8c (&ldata->atomic_read_lock){+.+.}, at: n_tty_read+0x1f1/0x1660
[  176.400313] 
[  176.401790] =============================================
[  176.401790] 

ケース5:単純なデッドロックの例1

lockdep という機能が有効になっている場合、デッドロックが発生する可能性のあるロック処理が実行されると、デッドロックが発生する可能性のあることが報告されます。

deadlock_test1.c :再帰型ロックをしてしまうカーネルモジュールの例

#include <linux/module.h>

static int __init deadlock_test1(void)
{
        static DEFINE_MUTEX(lock);

        mutex_lock(&lock);
        mutex_lock(&lock);
        mutex_unlock(&lock);
        mutex_unlock(&lock);
        return -EINVAL;
}

module_init(deadlock_test1);
MODULE_LICENSE("GPL");

lockdep により、同じ mutex ロックを2回獲得しようとしたことが報告されています。 mutex とは、1つのスレッドだけがロックを獲得でき、ロックを獲得したスレッドだけがロックを解放できるという種類のロックです。そして、 mutex_lock() という関数はロックを獲得できるようになるまでシグナルによる中断が不可能な方法でスケジューリングを行うことと、実際にデッドロックが発生していることによりシグナルによる中断が不可能な方法でのスケジューリング状態が続いてしまったことにより、スレッドがハングアップしているというメッセージも報告されています。

[   53.433400] deadlock_test1: loading out-of-tree module taints kernel.
[   53.438965] 
[   53.439412] ============================================
[   53.441013] WARNING: possible recursive locking detected
[   53.442606] 5.0.0 #1 Tainted: G           O    T
[   53.443999] --------------------------------------------
[   53.445636] insmod/9669 is trying to acquire lock:
[   53.447275] 00000000a2a5996c (lock#6){+.+.}, at: deadlock_test1+0x1c/0x1000 [deadlock_test1]
[   53.449877] 
[   53.449877] but task is already holding lock:
[   53.451776] 00000000a2a5996c (lock#6){+.+.}, at: deadlock_test1+0xe/0x1000 [deadlock_test1]
[   53.454497] 
[   53.454497] other info that might help us debug this:
[   53.456501]  Possible unsafe locking scenario:
[   53.456501] 
[   53.458285]        CPU0
[   53.459123]        ----
[   53.459804]   lock(lock#6);
[   53.460671]   lock(lock#6);
[   53.461554] 
[   53.461554]  *** DEADLOCK ***
[   53.461554] 
[   53.463410]  May be due to missing lock nesting notation
[   53.463410] 
[   53.465434] 1 lock held by insmod/9669:
[   53.466735]  #0: 00000000a2a5996c (lock#6){+.+.}, at: deadlock_test1+0xe/0x1000 [deadlock_test1]
[   53.469288] 
[   53.469288] stack backtrace:
[   53.470598] CPU: 5 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   53.473069] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   53.476561] Call Trace:
[   53.477368]  dump_stack+0x9a/0xf0
[   53.478624]  validate_chain.isra.37.cold.57+0x216/0x32a
[   53.480217]  ? check_prev_add.constprop.41+0x14c0/0x14c0
[   53.481759]  ? sched_clock+0x5/0x10
[   53.482791]  ? sched_clock_cpu+0x18/0x170
[   53.484091]  __lock_acquire+0x778/0x1230
[   53.485353]  lock_acquire+0x17d/0x3f0
[   53.486556]  ? deadlock_test1+0x1c/0x1000 [deadlock_test1]
[   53.488189]  ? deadlock_test1+0x1c/0x1000 [deadlock_test1]
[   53.490562]  ? deadlock_test1+0x1c/0x1000 [deadlock_test1]
[   53.492908]  __mutex_lock+0x100/0x11d0
[   53.495059]  ? deadlock_test1+0x1c/0x1000 [deadlock_test1]
[   53.497607]  ? load_module+0x43e8/0x56d0
[   53.499653]  ? __do_sys_finit_module+0x11a/0x1b0
[   53.501846]  ? deadlock_test1+0x1c/0x1000 [deadlock_test1]
[   53.504384]  ? do_raw_spin_unlock+0x4f/0x220
[   53.506559]  ? mutex_lock_io_nested+0x10a0/0x10a0
[   53.508780]  ? do_init_module+0x49/0x680
[   53.510716]  ? do_init_module+0x49/0x680
[   53.513084]  ? set_track+0x71/0x120
[   53.513088]  ? init_object+0x49/0x80
[   53.513107]  ? ___slab_alloc+0x668/0x750
[   53.513112]  ? 0xffffffffc0d28000
[   53.513116]  ? deadlock_test1+0x1c/0x1000 [deadlock_test1]
[   53.513119]  ? rcu_read_lock_sched_held+0x102/0x120
[   53.513122]  deadlock_test1+0x1c/0x1000 [deadlock_test1]
[   53.513126]  do_one_initcall+0xe2/0x553
[   53.513129]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   53.533182]  ? kasan_unpoison_shadow+0x30/0x40
[   53.535243]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   53.537516]  ? do_init_module+0x49/0x680
[   53.539733]  ? kmem_cache_alloc_trace+0x14b/0x340
[   53.541819]  ? kasan_unpoison_shadow+0x30/0x40
[   53.544033]  do_init_module+0x1da/0x680
[   53.545999]  load_module+0x43e8/0x56d0
[   53.548157]  ? layout_and_allocate+0x2140/0x2140
[   53.550327]  ? kernel_read+0x8b/0x130
[   53.552219]  ? kernel_read_file+0x225/0x4f0
[   53.554332]  ? __do_sys_finit_module+0x11a/0x1b0
[   53.556562]  __do_sys_finit_module+0x11a/0x1b0
[   53.558639]  ? __ia32_sys_init_module+0xa0/0xa0
[   53.560710]  ? __audit_syscall_exit+0x712/0x990
[   53.562907]  ? rcu_read_lock_sched_held+0x102/0x120
[   53.564981]  ? do_syscall_64+0x1d/0x450
[   53.566975]  do_syscall_64+0x9a/0x450
[   53.568816]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   53.570952] RIP: 0033:0x7f2e0a21d1c9
[   53.572657] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   53.579844] RSP: 002b:00007ffe60864388 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   53.582869] RAX: ffffffffffffffda RBX: 0000000001dba1e0 RCX: 00007f2e0a21d1c9
[   53.585903] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   53.588714] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffe60864528
[   53.591851] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   53.594748] R13: 0000000001db9120 R14: 0000000000000000 R15: 0000000000000000
[  179.873367] INFO: task insmod:9669 blocked for more than 120 seconds.
[  179.879339]       Tainted: G           O    T 5.0.0 #1
[  179.881458] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  179.884580] insmod          D27312  9669   9654 0x80000080
[  179.886859] Call Trace:
[  179.888297]  ? __schedule+0x71f/0x18f0
[  179.890336]  ? __sched_text_start+0x8/0x8
[  179.892197]  ? check_flags.part.39+0x400/0x400
[  179.894157]  ? lock_unpin_lock+0x4a0/0x4a0
[  179.896035]  schedule+0x77/0x170
[  179.897698]  schedule_preempt_disabled+0xc/0x20
[  179.899685]  __mutex_lock+0x4ab/0x11d0
[  179.901578]  ? load_module+0x43e8/0x56d0
[  179.903450]  ? deadlock_test1+0x1c/0x1000 [deadlock_test1]
[  179.906034]  ? mutex_lock_io_nested+0x10a0/0x10a0
[  179.908093]  ? do_init_module+0x49/0x680
[  179.909979]  ? do_init_module+0x49/0x680
[  179.911839]  ? set_track+0x71/0x120
[  179.913571]  ? init_object+0x49/0x80
[  179.915555]  ? ___slab_alloc+0x668/0x750
[  179.917403]  ? 0xffffffffc0d28000
[  179.919114]  ? deadlock_test1+0x1c/0x1000 [deadlock_test1]
[  179.921533]  ? rcu_read_lock_sched_held+0x102/0x120
[  179.923610]  deadlock_test1+0x1c/0x1000 [deadlock_test1]
[  179.925806]  do_one_initcall+0xe2/0x553
[  179.927759]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  179.930188]  ? kasan_unpoison_shadow+0x30/0x40
[  179.932204]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  179.934391]  ? do_init_module+0x49/0x680
[  179.936514]  ? kmem_cache_alloc_trace+0x14b/0x340
[  179.938621]  ? kasan_unpoison_shadow+0x30/0x40
[  179.940618]  do_init_module+0x1da/0x680
[  179.942521]  load_module+0x43e8/0x56d0
[  179.944353]  ? layout_and_allocate+0x2140/0x2140
[  179.946375]  ? kernel_read+0x8b/0x130
[  179.948161]  ? kernel_read_file+0x225/0x4f0
[  179.950073]  ? __do_sys_finit_module+0x11a/0x1b0
[  179.952332]  __do_sys_finit_module+0x11a/0x1b0
[  179.954374]  ? __ia32_sys_init_module+0xa0/0xa0
[  179.956366]  ? __audit_syscall_exit+0x712/0x990
[  179.958371]  ? rcu_read_lock_sched_held+0x102/0x120
[  179.960394]  ? do_syscall_64+0x1d/0x450
[  179.962201]  do_syscall_64+0x9a/0x450
[  179.963907]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  179.966035] RIP: 0033:0x7f2e0a21d1c9
[  179.967896] Code: Bad RIP value.
[  179.969458] RSP: 002b:00007ffe60864388 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  179.972163] RAX: ffffffffffffffda RBX: 0000000001dba1e0 RCX: 00007f2e0a21d1c9
[  179.974753] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  179.977308] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffe60864528
[  179.979845] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[  179.982866] R13: 0000000001db9120 R14: 0000000000000000 R15: 0000000000000000
[  179.985916] INFO: lockdep is turned off.

ケース6:単純なデッドロックの例2

lockdep は、実際にデッドロックが発生したタイミングではなく、発生する可能性を検出したタイミングで報告します。

deadlock_test2.c :循環型ロックをしてしまうカーネルモジュールの例

#include <linux/module.h>

static int __init deadlock_test2(void)
{
        static DEFINE_MUTEX(lock1);
        static DEFINE_MUTEX(lock2);

        mutex_lock(&lock1);
        mutex_lock(&lock2);
        mutex_unlock(&lock2);
        mutex_unlock(&lock1);
        mutex_lock(&lock2);
        mutex_lock(&lock1);
        mutex_unlock(&lock1);
        mutex_unlock(&lock2);
        return -EINVAL;
}

module_init(deadlock_test2);
MODULE_LICENSE("GPL");

lockdep により、2つの mutex ロックの獲得順序によりデッドロックが発生する可能性があることが報告されています。なお、実際には、この例での deadlock_test2() という関数は同時に複数のスレッドから呼ばれることは無いため、実行してもデッドロックは発生しません。

[   54.376164] deadlock_test2: loading out-of-tree module taints kernel.
[   54.381629] 
[   54.382228] ======================================================
[   54.384481] WARNING: possible circular locking dependency detected
[   54.386687] 5.0.0 #1 Tainted: G           O    T
[   54.388315] ------------------------------------------------------
[   54.390291] insmod/9670 is trying to acquire lock:
[   54.391833] 00000000aaf6ba99 (lock1){+.+.}, at: deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.394284] 
[   54.394284] but task is already holding lock:
[   54.395971] 000000008bf63933 (lock2){+.+.}, at: deadlock_test2+0x42/0x1000 [deadlock_test2]
[   54.398258] 
[   54.398258] which lock already depends on the new lock.
[   54.398258] 
[   54.401023] 
[   54.401023] the existing dependency chain (in reverse order) is:
[   54.403051] 
[   54.403051] -> #1 (lock2){+.+.}:
[   54.404497]        lock_acquire+0x17d/0x3f0
[   54.405621]        __mutex_lock+0x100/0x11d0
[   54.406765]        deadlock_test2+0x1c/0x1000 [deadlock_test2]
[   54.408498]        do_one_initcall+0xe2/0x553
[   54.409706]        do_init_module+0x1da/0x680
[   54.410880]        load_module+0x43e8/0x56d0
[   54.412194]        __do_sys_finit_module+0x11a/0x1b0
[   54.413525]        do_syscall_64+0x9a/0x450
[   54.414652]        entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   54.416219] 
[   54.416219] -> #0 (lock1){+.+.}:
[   54.417417]        __lock_acquire+0x778/0x1230
[   54.418548]        lock_acquire+0x17d/0x3f0
[   54.419738]        __mutex_lock+0x100/0x11d0
[   54.420828]        deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.422411]        do_one_initcall+0xe2/0x553
[   54.423701]        do_init_module+0x1da/0x680
[   54.424811]        load_module+0x43e8/0x56d0
[   54.425896]        __do_sys_finit_module+0x11a/0x1b0
[   54.427439]        do_syscall_64+0x9a/0x450
[   54.428508]        entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   54.429913] 
[   54.429913] other info that might help us debug this:
[   54.429913] 
[   54.434197]  Possible unsafe locking scenario:
[   54.434197] 
[   54.437227]        CPU0                    CPU1
[   54.439274]        ----                    ----
[   54.441178]   lock(lock2);
[   54.442887]                                lock(lock1);
[   54.445107]                                lock(lock2);
[   54.447156]   lock(lock1);
[   54.448462] 
[   54.448462]  *** DEADLOCK ***
[   54.448462] 
[   54.451943] 1 lock held by insmod/9670:
[   54.453477]  #0: 000000008bf63933 (lock2){+.+.}, at: deadlock_test2+0x42/0x1000 [deadlock_test2]
[   54.456878] 
[   54.456878] stack backtrace:
[   54.456881] CPU: 0 PID: 9670 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   54.456882] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   54.456883] Call Trace:
[   54.456909]  dump_stack+0x9a/0xf0
[   54.456912]  print_circular_bug.isra.33.cold.52+0x1bc/0x279
[   54.456915]  ? save_trace+0xd6/0x250
[   54.456917]  check_prev_add.constprop.41+0xbe3/0x14c0
[   54.456919]  ? check_usage+0x4e0/0x4e0
[   54.456922]  ? unwind_next_frame+0xe44/0x19b0
[   54.456924]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   54.456927]  ? trace_raw_output_lock+0xe0/0xe0
[   54.456929]  ? kernel_text_address+0x11b/0x140
[   54.456931]  validate_chain.isra.37+0xd74/0x2730
[   54.456934]  ? check_prev_add.constprop.41+0x14c0/0x14c0
[   54.456936]  ? sched_clock+0x5/0x10
[   54.456938]  ? sched_clock_cpu+0x18/0x170
[   54.456940]  __lock_acquire+0x778/0x1230
[   54.456942]  lock_acquire+0x17d/0x3f0
[   54.456945]  ? deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.456947]  ? deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.456949]  ? deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.456952]  __mutex_lock+0x100/0x11d0
[   54.502146]  ? deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.504183]  ? deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.506309]  ? mutex_lock_io_nested+0x10a0/0x10a0
[   54.508072]  ? do_init_module+0x49/0x680
[   54.509940]  ? 0xffffffffc0f78000
[   54.511498]  ? __mutex_unlock_slowpath+0xdc/0x670
[   54.513435]  ? wait_for_completion+0x310/0x310
[   54.515139]  ? 0xffffffffc0f78000
[   54.516560]  ? deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.518672]  deadlock_test2+0x50/0x1000 [deadlock_test2]
[   54.520680]  do_one_initcall+0xe2/0x553
[   54.522524]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   54.524738]  ? kasan_unpoison_shadow+0x30/0x40
[   54.526558]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   54.528673]  ? do_init_module+0x49/0x680
[   54.530287]  ? kmem_cache_alloc_trace+0x14b/0x340
[   54.532384]  ? kasan_unpoison_shadow+0x30/0x40
[   54.534148]  do_init_module+0x1da/0x680
[   54.535877]  load_module+0x43e8/0x56d0
[   54.537469]  ? layout_and_allocate+0x2140/0x2140
[   54.539472]  ? kernel_read+0x8b/0x130
[   54.541053]  ? kernel_read_file+0x225/0x4f0
[   54.542898]  ? __do_sys_finit_module+0x11a/0x1b0
[   54.544838]  __do_sys_finit_module+0x11a/0x1b0
[   54.546580]  ? __ia32_sys_init_module+0xa0/0xa0
[   54.548510]  ? __audit_syscall_exit+0x712/0x990
[   54.550268]  ? rcu_read_lock_sched_held+0x102/0x120
[   54.552600]  ? do_syscall_64+0x1d/0x450
[   54.554144]  do_syscall_64+0x9a/0x450
[   54.555856]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   54.557801] RIP: 0033:0x7fa83d6781c9
[   54.559508] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   54.565906] RSP: 002b:00007ffdc1ac5b48 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   54.568830] RAX: ffffffffffffffda RBX: 0000000001ade1e0 RCX: 00007fa83d6781c9
[   54.571421] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   54.573931] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffdc1ac5ce8
[   54.576634] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   54.579707] R13: 0000000001add120 R14: 0000000000000000 R15: 0000000000000000

ケース7:単純な sleep in atomic の例

「スケジューリングが不可能な状況(アトミックなコンテキスト)」では、「スケジューリングが発生する可能性のある処理」を呼び出すことを避ける必要があります。

「スケジューリングが不可能な状況でスケジューリングが発生する可能性のある処理が呼び出された」場合に、どのようなメッセージが出力されるかを見てみましょう。

sleep_in_atomic_test.c : sleep in atomic 警告メッセージを出力させるカーネルモジュールの例

#include <linux/module.h>

static int __init sleep_in_atomic_test(void)
{
        static DEFINE_SPINLOCK(spinlock1);
        static DEFINE_MUTEX(mutex1);

        spin_lock(&spinlock1);
        mutex_lock(&mutex1);
        mutex_unlock(&mutex1);
        spin_unlock(&spinlock1);
        return -EINVAL;
}

module_init(sleep_in_atomic_test);
MODULE_LICENSE("GPL");

スピンロックを保持している間はアトミックなコンテキストとして処理する必要があるため、スピンロックを保持している間にスケジューリングが発生する可能性のある処理が呼び出されたという警告メッセージが出力されます。実際にハングアップなどの問題が発生するかどうかは、タイミングなどに依存します。

[   54.694490] sleep_in_atomic_test: loading out-of-tree module taints kernel.
[   54.700663] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:908
[   54.703101] in_atomic(): 1, irqs_disabled(): 0, pid: 9670, name: insmod
[   54.705474] 1 lock held by insmod/9670:
[   54.706640]  #0: 00000000631d4fb1 (spinlock1){+.+.}, at: sleep_in_atomic_test+0xc/0x1000 [sleep_in_atomic_test]
[   54.709550] CPU: 4 PID: 9670 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   54.711987] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   54.715171] Call Trace:
[   54.715892]  dump_stack+0x9a/0xf0
[   54.716782]  ___might_sleep.cold.82+0x121/0x13b
[   54.717994]  __mutex_lock+0xc7/0x11d0
[   54.719220]  ? sleep_in_atomic_test+0x1a/0x1000 [sleep_in_atomic_test]
[   54.721021]  ? mark_lock+0x829/0x10b0
[   54.721986]  ? mutex_lock_io_nested+0x10a0/0x10a0
[   54.723387]  ? find_held_lock+0x3a/0x1c0
[   54.724436]  ? lock_contended+0xde0/0xde0
[   54.725499]  ? 0xffffffffc0d40000
[   54.726385]  ? sleep_in_atomic_test+0x1a/0x1000 [sleep_in_atomic_test]
[   54.728293]  sleep_in_atomic_test+0x1a/0x1000 [sleep_in_atomic_test]
[   54.729937]  do_one_initcall+0xe2/0x553
[   54.731082]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   54.732566]  ? kasan_unpoison_shadow+0x30/0x40
[   54.733774]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   54.735006]  ? do_init_module+0x49/0x680
[   54.735987]  ? kmem_cache_alloc_trace+0x14b/0x340
[   54.737377]  ? kasan_unpoison_shadow+0x30/0x40
[   54.738594]  do_init_module+0x1da/0x680
[   54.739561]  load_module+0x43e8/0x56d0
[   54.740527]  ? layout_and_allocate+0x2140/0x2140
[   54.742029]  ? kernel_read+0x8b/0x130
[   54.743159]  ? kernel_read_file+0x225/0x4f0
[   54.744284]  ? __do_sys_finit_module+0x11a/0x1b0
[   54.745705]  __do_sys_finit_module+0x11a/0x1b0
[   54.747721]  ? __ia32_sys_init_module+0xa0/0xa0
[   54.749295]  ? __audit_syscall_exit+0x712/0x990
[   54.750520]  ? rcu_read_lock_sched_held+0x102/0x120
[   54.751842]  ? do_syscall_64+0x1d/0x450
[   54.752992]  do_syscall_64+0x9a/0x450
[   54.754036]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   54.755350] RIP: 0033:0x7f9167e4b1c9
[   54.757352] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   54.764644] RSP: 002b:00007ffd77eab0e8 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   54.764649] RAX: ffffffffffffffda RBX: 00000000020741e0 RCX: 00007f9167e4b1c9
[   54.764651] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   54.764652] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd77eab288
[   54.764654] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   54.764655] R13: 0000000002073120 R14: 0000000000000000 R15: 0000000000000000

ケース8:時間のかかる処理に没頭してしまう例( CONFIG_PREEMPT_VOLUNTARY=y の場合)

カーネル内では、時間のかかる処理を行う場合、応答性を維持するために、スケジューリングが可能なタイミングにおいて明示的にスケジューリングを行うようにすることが望まれます。スケジューリングを行う方法の選択肢として、 CONFIG_PREEMPT_NONE (応答性よりもスループットを優先するために、スケジューリングを行わない)、 CONFIG_PREEMPT_VOLUNTARY (応答性とスループットのバランスを考えて、明示的にスケジューリングを許可したタイミングでのみスケジューリングを行う)、 CONFIG_PRREMPT (スループットよりも応答性を優先するために、スケジューリングが禁止されていない限り自動的にスケジューリングを行う)という3種類があります。

CONFIG_PREEMPT_VOLUNTARY=y という設定でコンパイルされたカーネルに対して、明示的にスケジューリングを許可しなかった場合に、どのようなメッセージが出力されるかを見てみましょう。

softlockup_test.c :ソフトロックアップ警告メッセージを出力させるカーネルモジュールの例

#include <linux/module.h>

static int __init softlockup_test(void)
{
        volatile long i = 1;

        while (i)
                i++;
        return -EINVAL;
}

module_init(softlockup_test);
MODULE_LICENSE("GPL");

ソフトロックアップという、CPU時間を連続して使い続けていることを示す警告メッセージが出力されます。また、RCUという、 Linux 2.6 以降のカーネルで使われているロックに関して、ストール状態が発生していることを示す警告メッセージも出力されます。RCUストール警告メッセージについての説明は、 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/RCU/stallwarn.txt にあります。

[   54.271757] softlockup_test: loading out-of-tree module taints kernel.
[   81.852656] watchdog: BUG: soft lockup - CPU#7 stuck for 23s! [insmod:9669]
[   81.855470] Modules linked in: softlockup_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw e1000 ahci libahci ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm mptspi scsi_transport_spi i2c_core mptscsih ata_piix mptbase libata
[   81.876731] irq event stamp: 61656
[   81.878123] hardirqs last  enabled at (61655): [<ffffffffb0005450>] trace_hardirqs_on_thunk+0x1a/0x1c
[   81.881066] hardirqs last disabled at (61656): [<ffffffffb000546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[   81.884027] softirqs last  enabled at (11364): [<ffffffffb1c00675>] __do_softirq+0x675/0x9e3
[   81.886524] softirqs last disabled at (11355): [<ffffffffb017fe64>] irq_exit+0x274/0x2c0
[   81.889080] CPU: 7 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   81.891758] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   81.895655] RIP: 0010:softlockup_test+0x58/0x1000 [softlockup_test]
[   81.897625] Code: 48 01 d0 c7 00 f1 f1 f1 f1 c7 40 04 00 f2 f2 f2 c7 40 08 f3 f3 f3 f3 48 c7 44 24 20 01 00 00 00 48 8b 44 24 20 48 85 c0 74 0f <48> 8b 44 24 20 48 ff c0 48 89 44 24 20 eb e7 b8 ff ff 37 00 b9 03
[   81.903276] RSP: 0018:ffff88809239f8f0 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13
[   81.905690] RAX: 00000003bbafefcb RBX: 0000000000000000 RCX: 0000000000000001
[   81.907847] RDX: 1ffff11012473f1e RSI: ffff88809227c25c RDI: 0000000000000246
[   81.910178] RBP: 1ffff11012473f2d R08: ffffed101437fb88 R09: 0000000000000001
[   81.912372] R10: ffffed101437fb87 R11: ffff8880a1bfdc3b R12: ffffffffc0bb0000
[   81.914612] R13: 0000000000000007 R14: ffffffffc0ba1000 R15: ffffffffb2a65064
[   81.916834] FS:  00007fb151f01740(0000) GS:ffff8880a1a00000(0000) knlGS:0000000000000000
[   81.919398] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   81.921253] CR2: 0000000000f5b1d8 CR3: 0000000092654004 CR4: 00000000003606e0
[   81.923621] Call Trace:
[   81.924419]  ? 0xffffffffc0bb0000
[   81.925479]  ? 0xffffffffc0bb0000
[   81.926568]  ? rcu_read_lock_sched_held+0x102/0x120
[   81.928067]  do_one_initcall+0xe2/0x553
[   81.929250]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   81.931146]  ? kasan_unpoison_shadow+0x30/0x40
[   81.932605]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   81.934073]  ? do_init_module+0x49/0x680
[   81.935262]  ? kmem_cache_alloc_trace+0x14b/0x340
[   81.936865]  ? __kasan_slab_free+0x126/0x150
[   81.938198]  do_init_module+0x1da/0x680
[   81.939515]  load_module+0x43e8/0x56d0
[   81.940794]  ? layout_and_allocate+0x2140/0x2140
[   81.943573]  ? kernel_read+0x8b/0x130
[   81.946806]  ? kernel_read_file+0x225/0x4f0
[   81.949756]  ? __do_sys_finit_module+0x11a/0x1b0
[   81.952471]  __do_sys_finit_module+0x11a/0x1b0
[   81.955347]  ? __ia32_sys_init_module+0xa0/0xa0
[   81.958142]  ? __audit_syscall_exit+0x712/0x990
[   81.960821]  ? rcu_read_lock_sched_held+0x102/0x120
[   81.963877]  ? do_syscall_64+0x1d/0x450
[   81.966325]  do_syscall_64+0x9a/0x450
[   81.968666]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   81.971426] RIP: 0033:0x7fb1513d41c9
[   81.973741] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   81.981560] RSP: 002b:00007ffd03d4f328 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   81.984992] RAX: ffffffffffffffda RBX: 0000000000f5b1e0 RCX: 00007fb1513d41c9
[   81.988229] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   81.991464] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd03d4f4c8
[   81.994734] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   81.997983] R13: 0000000000f5a120 R14: 0000000000000000 R15: 0000000000000000
[   90.266025] [drm:drm_atomic_helper_wait_for_dependencies [drm_kms_helper]] *ERROR* [CRTC:37:crtc-0] flip_done timed out
[  100.505764] [drm:drm_atomic_helper_wait_for_dependencies [drm_kms_helper]] *ERROR* [PLANE:33:plane-0] flip_done timed out
[  109.852460] watchdog: BUG: soft lockup - CPU#7 stuck for 23s! [insmod:9669]
[  109.856223] Modules linked in: softlockup_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw e1000 ahci libahci ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm mptspi scsi_transport_spi i2c_core mptscsih ata_piix mptbase libata
[  109.881721] irq event stamp: 116562
[  109.884121] hardirqs last  enabled at (116561): [<ffffffffb0005450>] trace_hardirqs_on_thunk+0x1a/0x1c
[  109.888444] hardirqs last disabled at (116562): [<ffffffffb000546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[  109.892723] softirqs last  enabled at (11364): [<ffffffffb1c00675>] __do_softirq+0x675/0x9e3
[  109.896856] softirqs last disabled at (11355): [<ffffffffb017fe64>] irq_exit+0x274/0x2c0
[  109.900533] CPU: 7 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O L  T 5.0.0 #1
[  109.904617] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  109.909481] RIP: 0010:softlockup_test+0x65/0x1000 [softlockup_test]
[  109.912718] Code: f2 f2 f2 c7 40 08 f3 f3 f3 f3 48 c7 44 24 20 01 00 00 00 48 8b 44 24 20 48 85 c0 74 0f 48 8b 44 24 20 48 ff c0 48 89 44 24 20 <eb> e7 b8 ff ff 37 00 b9 03 00 00 00 48 c1 e0 2a 48 01 c2 31 c0 48
[  109.921705] RSP: 0018:ffff88809239f8f0 EFLAGS: 00000206 ORIG_RAX: ffffffffffffff13
[  109.925739] RAX: 00000007644a400a RBX: 0000000000000000 RCX: 0000000000000001
[  109.929546] RDX: 1ffff11012473f1e RSI: ffff88809227c25c RDI: 0000000000000246
[  109.933259] RBP: 1ffff11012473f2d R08: ffffed101437fb88 R09: 0000000000000001
[  109.937013] R10: ffffed101437fb87 R11: ffff8880a1bfdc3b R12: ffffffffc0bb0000
[  109.940820] R13: 0000000000000007 R14: ffffffffc0ba1000 R15: ffffffffb2a65064
[  109.944546] FS:  00007fb151f01740(0000) GS:ffff8880a1a00000(0000) knlGS:0000000000000000
[  109.948796] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  109.952062] CR2: 0000000000f5b1d8 CR3: 0000000092654004 CR4: 00000000003606e0
[  109.956157] Call Trace:
[  109.959132]  ? 0xffffffffc0bb0000
[  109.961896]  ? 0xffffffffc0bb0000
[  109.964995]  ? rcu_read_lock_sched_held+0x102/0x120
[  109.968055]  do_one_initcall+0xe2/0x553
[  109.971011]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  109.974457]  ? kasan_unpoison_shadow+0x30/0x40
[  109.977384]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  109.980521]  ? do_init_module+0x49/0x680
[  109.983351]  ? kmem_cache_alloc_trace+0x14b/0x340
[  109.986425]  ? __kasan_slab_free+0x126/0x150
[  109.989707]  do_init_module+0x1da/0x680
[  109.992319]  load_module+0x43e8/0x56d0
[  109.995091]  ? layout_and_allocate+0x2140/0x2140
[  109.997978]  ? kernel_read+0x8b/0x130
[  110.000559]  ? kernel_read_file+0x225/0x4f0
[  110.003436]  ? __do_sys_finit_module+0x11a/0x1b0
[  110.006573]  __do_sys_finit_module+0x11a/0x1b0
[  110.009471]  ? __ia32_sys_init_module+0xa0/0xa0
[  110.012601]  ? __audit_syscall_exit+0x712/0x990
[  110.015396]  ? rcu_read_lock_sched_held+0x102/0x120
[  110.018498]  ? do_syscall_64+0x1d/0x450
[  110.021077]  do_syscall_64+0x9a/0x450
[  110.023593]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  110.026574] RIP: 0033:0x7fb1513d41c9
[  110.028982] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[  110.037233] RSP: 002b:00007ffd03d4f328 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  110.040926] RAX: ffffffffffffffda RBX: 0000000000f5b1e0 RCX: 00007fb1513d41c9
[  110.044647] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  110.048416] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd03d4f4c8
[  110.052080] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[  110.056148] R13: 0000000000f5a120 R14: 0000000000000000 R15: 0000000000000000
[  119.275437] rcu: INFO: rcu_sched self-detected stall on CPU
[  119.278534] rcu: 	7-....: (61948 ticks this GP) idle=f9e/1/0x4000000000000002 softirq=9269/9269 fqs=15413 
[  119.283599] rcu: 	 (t=65000 jiffies g=14181 q=1506)
[  119.286250] NMI backtrace for cpu 7
[  119.288935] CPU: 7 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O L  T 5.0.0 #1
[  119.293421] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  119.298429] Call Trace:
[  119.301259]  <IRQ>
[  119.303337]  dump_stack+0x9a/0xf0
[  119.306008]  nmi_cpu_backtrace.cold.4+0x13/0x6e
[  119.308924]  ? lapic_can_unplug_cpu.cold.23+0x3f/0x3f
[  119.312399]  nmi_trigger_cpumask_backtrace+0x199/0x21e
[  119.315463]  rcu_dump_cpu_stacks+0x17c/0x1c8
[  119.318104]  rcu_check_callbacks.cold.64+0x3c8/0x6cc
[  119.320804]  ? rcu_read_lock_sched_held+0x102/0x120
[  119.323524]  update_process_times+0x23/0x60
[  119.326002]  tick_sched_handle+0x6f/0x130
[  119.328771]  tick_sched_timer+0x32/0xe0
[  119.331153]  __hrtimer_run_queues+0x2fb/0xb30
[  119.334099]  ? tick_sched_do_timer+0x200/0x200
[  119.337391]  ? hrtimer_start_range_ns+0x9a0/0x9a0
[  119.340314]  ? ktime_get_update_offsets_now+0x97/0x2b0
[  119.343253]  hrtimer_interrupt+0x2c2/0x750
[  119.346568]  smp_apic_timer_interrupt+0x105/0x5b0
[  119.349174]  apic_timer_interrupt+0xf/0x20
[  119.351751]  </IRQ>
[  119.353755] RIP: 0010:softlockup_test+0x65/0x1000 [softlockup_test]
[  119.357022] Code: f2 f2 f2 c7 40 08 f3 f3 f3 f3 48 c7 44 24 20 01 00 00 00 48 8b 44 24 20 48 85 c0 74 0f 48 8b 44 24 20 48 ff c0 48 89 44 24 20 <eb> e7 b8 ff ff 37 00 b9 03 00 00 00 48 c1 e0 2a 48 01 c2 31 c0 48
[  119.366165] RSP: 0018:ffff88809239f8f0 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13
[  119.369983] RAX: 000000089b02e4cb RBX: 0000000000000000 RCX: 0000000000000001
[  119.374134] RDX: 1ffff11012473f1e RSI: ffff88809227c25c RDI: 0000000000000246
[  119.378099] RBP: 1ffff11012473f2d R08: ffffed101437fb88 R09: 0000000000000001
[  119.382196] R10: ffffed101437fb87 R11: ffff8880a1bfdc3b R12: ffffffffc0bb0000
[  119.385696] R13: 0000000000000007 R14: ffffffffc0ba1000 R15: ffffffffb2a65064
[  119.389516]  ? 0xffffffffc0bb0000
[  119.392269]  ? 0xffffffffc0bb0000
[  119.394560]  ? 0xffffffffc0bb0000
[  119.396866]  ? rcu_read_lock_sched_held+0x102/0x120
[  119.399866]  do_one_initcall+0xe2/0x553
[  119.402467]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  119.405434]  ? kasan_unpoison_shadow+0x30/0x40
[  119.408252]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  119.411265]  ? do_init_module+0x49/0x680
[  119.413785]  ? kmem_cache_alloc_trace+0x14b/0x340
[  119.416530]  ? __kasan_slab_free+0x126/0x150
[  119.419135]  do_init_module+0x1da/0x680
[  119.421457]  load_module+0x43e8/0x56d0
[  119.424058]  ? layout_and_allocate+0x2140/0x2140
[  119.426608]  ? kernel_read+0x8b/0x130
[  119.428824]  ? kernel_read_file+0x225/0x4f0
[  119.431175]  ? __do_sys_finit_module+0x11a/0x1b0
[  119.433561]  __do_sys_finit_module+0x11a/0x1b0
[  119.435793]  ? __ia32_sys_init_module+0xa0/0xa0
[  119.438090]  ? __audit_syscall_exit+0x712/0x990
[  119.440412]  ? rcu_read_lock_sched_held+0x102/0x120
[  119.442799]  ? do_syscall_64+0x1d/0x450
[  119.444864]  do_syscall_64+0x9a/0x450
[  119.447045]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  119.449742] RIP: 0033:0x7fb1513d41c9
[  119.451786] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[  119.459845] RSP: 002b:00007ffd03d4f328 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  119.463433] RAX: ffffffffffffffda RBX: 0000000000f5b1e0 RCX: 00007fb1513d41c9
[  119.466667] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  119.469775] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd03d4f4c8
[  119.473109] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[  119.476261] R13: 0000000000f5a120 R14: 0000000000000000 R15: 0000000000000000
[  125.593436] rcu: INFO: rcu_sched detected expedited stalls on CPUs/tasks: { 7-... } 65914 jiffies s: 8393 root: 0x1/.
[  125.598682] rcu: blocking rcu_node structures: l=1:0-15:0x80/.
[  125.602257] Task dump for CPU 7:
[  125.604717] insmod          R  running task    27312  9669   9654 0x80000088
[  125.609696] Call Trace:
[  125.612871]  ? is_bpf_text_address+0x81/0xe0
[  125.616532]  ? kernel_text_address+0x11b/0x140
[  125.621864]  ? __kernel_text_address+0x9/0x30
[  125.626927]  ? unwind_get_return_address+0x5a/0xa0
[  125.632079]  ? __save_stack_trace+0x8d/0xf0
[  125.635252]  ? save_stack+0x8c/0xb0
[  125.637565]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  125.640219]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[  125.642628]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[  125.645120]  ? retint_kernel+0x10/0x10
[  125.647262]  ? 0xffffffffc0bb0000
[  125.649813]  ? softlockup_test+0x58/0x1000 [softlockup_test]
[  125.652542]  ? 0xffffffffc0bb0000
[  125.654729]  ? 0xffffffffc0bb0000
[  125.656997]  ? rcu_read_lock_sched_held+0x102/0x120
[  125.659676]  ? do_one_initcall+0xe2/0x553
[  125.661926]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  125.664756]  ? kasan_unpoison_shadow+0x30/0x40
[  125.668909]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  125.671536]  ? do_init_module+0x49/0x680
[  125.673711]  ? kmem_cache_alloc_trace+0x14b/0x340
[  125.677242]  ? __kasan_slab_free+0x126/0x150
[  125.679643]  ? do_init_module+0x1da/0x680
[  125.681875]  ? load_module+0x43e8/0x56d0
[  125.684187]  ? layout_and_allocate+0x2140/0x2140
[  125.686714]  ? kernel_read+0x8b/0x130
[  125.688859]  ? kernel_read_file+0x225/0x4f0
[  125.691162]  ? __do_sys_finit_module+0x11a/0x1b0
[  125.693655]  ? __do_sys_finit_module+0x11a/0x1b0
[  125.696711]  ? __ia32_sys_init_module+0xa0/0xa0
[  125.699546]  ? __audit_syscall_exit+0x712/0x990
[  125.702521]  ? rcu_read_lock_sched_held+0x102/0x120
[  125.708015]  ? do_syscall_64+0x1d/0x450
[  125.712326]  ? do_syscall_64+0x9a/0x450
[  125.716462]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  145.852509] watchdog: BUG: soft lockup - CPU#7 stuck for 22s! [insmod:9669]
[  145.855717] Modules linked in: softlockup_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw e1000 ahci libahci ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm mptspi scsi_transport_spi i2c_core mptscsih ata_piix mptbase libata
[  145.879513] irq event stamp: 186828
[  145.881967] hardirqs last  enabled at (186827): [<ffffffffb0005450>] trace_hardirqs_on_thunk+0x1a/0x1c
[  145.886183] hardirqs last disabled at (186828): [<ffffffffb000546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[  145.890085] softirqs last  enabled at (11364): [<ffffffffb1c00675>] __do_softirq+0x675/0x9e3
[  145.893844] softirqs last disabled at (11355): [<ffffffffb017fe64>] irq_exit+0x274/0x2c0
[  145.897704] CPU: 7 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O L  T 5.0.0 #1
[  145.901234] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  145.905644] RIP: 0010:softlockup_test+0x65/0x1000 [softlockup_test]
[  145.908546] Code: f2 f2 f2 c7 40 08 f3 f3 f3 f3 48 c7 44 24 20 01 00 00 00 48 8b 44 24 20 48 85 c0 74 0f 48 8b 44 24 20 48 ff c0 48 89 44 24 20 <eb> e7 b8 ff ff 37 00 b9 03 00 00 00 48 c1 e0 2a 48 01 c2 31 c0 48
[  145.916917] RSP: 0018:ffff88809239f8f0 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13
[  145.920406] RAX: 0000000c19ead1c4 RBX: 0000000000000000 RCX: 0000000000000001
[  145.923895] RDX: 1ffff11012473f1e RSI: ffff88809227c25c RDI: 0000000000000246
[  145.927323] RBP: 1ffff11012473f2d R08: ffffed101437fb88 R09: 0000000000000001
[  145.930884] R10: ffffed101437fb87 R11: ffff8880a1bfdc3b R12: ffffffffc0bb0000
[  145.934430] R13: 0000000000000007 R14: ffffffffc0ba1000 R15: ffffffffb2a65064
[  145.938168] FS:  00007fb151f01740(0000) GS:ffff8880a1a00000(0000) knlGS:0000000000000000
[  145.941965] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  145.945189] CR2: 0000000000f5b1d8 CR3: 0000000092654004 CR4: 00000000003606e0
[  145.948742] Call Trace:
[  145.950926]  ? 0xffffffffc0bb0000
[  145.953250]  ? 0xffffffffc0bb0000
[  145.955623]  ? rcu_read_lock_sched_held+0x102/0x120
[  145.958609]  do_one_initcall+0xe2/0x553
[  145.961496]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  145.964670]  ? kasan_unpoison_shadow+0x30/0x40
[  145.967695]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  145.970629]  ? do_init_module+0x49/0x680
[  145.973395]  ? kmem_cache_alloc_trace+0x14b/0x340
[  145.976230]  ? __kasan_slab_free+0x126/0x150
[  145.978935]  do_init_module+0x1da/0x680
[  145.981493]  load_module+0x43e8/0x56d0
[  145.983941]  ? layout_and_allocate+0x2140/0x2140
[  145.987045]  ? kernel_read+0x8b/0x130
[  145.989713]  ? kernel_read_file+0x225/0x4f0
[  145.992422]  ? __do_sys_finit_module+0x11a/0x1b0
[  145.996025]  __do_sys_finit_module+0x11a/0x1b0
[  145.999489]  ? __ia32_sys_init_module+0xa0/0xa0
[  146.003180]  ? __audit_syscall_exit+0x712/0x990
[  146.006367]  ? rcu_read_lock_sched_held+0x102/0x120
[  146.009317]  ? do_syscall_64+0x1d/0x450
[  146.012366]  do_syscall_64+0x9a/0x450
[  146.014951]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  146.017958] RIP: 0033:0x7fb1513d41c9
[  146.020796] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[  146.029950] RSP: 002b:00007ffd03d4f328 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  146.033812] RAX: ffffffffffffffda RBX: 0000000000f5b1e0 RCX: 00007fb1513d41c9
[  146.037622] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  146.041657] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd03d4f4c8
[  146.045652] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[  146.049043] R13: 0000000000f5a120 R14: 0000000000000000 R15: 0000000000000000

ケース9:RCUロックを保持したまま時間のかかる処理に没頭してしまう例

RCUロックを保持している間はアトミックなコンテキストとして処理する必要があるため、時間のかかる処理を避ける必要があります。RCUロックを保持したまま時間のかかる処理を行ってしまった場合に、どのようなメッセージが出力されるかを見てみましょう。

rcu_stall_test.c :RCUストール警告メッセージを出力させるカーネルモジュールの例

#include <linux/module.h>

static int __init rcu_stall_test(void)
{
        volatile long i = 1;

        rcu_read_lock();
        while (i)
                i++;
        rcu_read_unlock();
        return -EINVAL;
}

module_init(rcu_stall_test);
MODULE_LICENSE("GPL");

RCUロックを保持していない場合と同様に、ソフトロックアップ警告メッセージやRCUストール警告メッセージが出力されます。しかし、RCUロックを保持した状態でスケジューリングを行うことは許されないことから、RCUロックが解放される(正確には、RCU猶予期間と呼ばれる処理が完了する)のを待つ処理は、短い時間内に完了することが期待されます。そのため、RCUロックを保持したままの状態が続いていることにより、RCUロックが解放されるのを待っているスレッドがハングアップしているというメッセージも報告されています。デッドロックが発生した訳ではないのに、単に時間がかかっていることにより、ハングアップと判断されてしまっている訳です。

[   54.421316] rcu_stall_test: loading out-of-tree module taints kernel.
[   81.851604] watchdog: BUG: soft lockup - CPU#5 stuck for 23s! [insmod:9670]
[   81.853826] Modules linked in: rcu_stall_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ahci libahci e1000 ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt mptspi fb_sys_fops scsi_transport_spi ttm ata_piix mptscsih mptbase libata drm i2c_core
[   81.872701] irq event stamp: 60784
[   81.874013] hardirqs last  enabled at (60783): [<ffffffff96005450>] trace_hardirqs_on_thunk+0x1a/0x1c
[   81.876668] hardirqs last disabled at (60784): [<ffffffff9600546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[   81.879742] softirqs last  enabled at (9066): [<ffffffff97c00675>] __do_softirq+0x675/0x9e3
[   81.882451] softirqs last disabled at (9057): [<ffffffff9617fe64>] irq_exit+0x274/0x2c0
[   81.884801] CPU: 5 PID: 9670 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   81.887298] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   81.890511] RIP: 0010:rcu_stall_test+0xb7/0x1000 [rcu_stall_test]
[   81.892370] Code: 75 49 d5 84 c0 75 1f 48 c7 c2 80 10 e4 c0 be 61 02 00 00 48 c7 c7 e0 10 e4 c0 c6 05 13 20 ff ff 01 e8 c3 16 44 d5 48 8b 45 b8 <48> 85 c0 74 0d 48 8b 45 b8 48 ff c0 48 89 45 b8 eb ea e8 22 07 49
[   81.898938] RSP: 0018:ffff88808ea6f8e0 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13
[   81.901366] RAX: 00000003991e024a RBX: 1ffff11011d4df1c RCX: ffffffff962e75fc
[   81.903628] RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffff8880a13fdc38
[   81.905800] RBP: ffff88808ea6f948 R08: ffffed101427fb88 R09: ffffed101427fb87
[   81.908114] R10: ffffed101427fb87 R11: ffff8880a13fdc3b R12: ffffffffc0e50000
[   81.910207] R13: 0000000000000005 R14: dffffc0000000000 R15: ffffffff98a65064
[   81.912353] FS:  00007fd5a692c740(0000) GS:ffff8880a1200000(0000) knlGS:0000000000000000
[   81.914989] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   81.916902] CR2: 0000000000ff21d8 CR3: 00000000980ee001 CR4: 00000000003606e0
[   81.919151] Call Trace:
[   81.919977]  ? 0xffffffffc0e50000
[   81.921009]  ? 0xffffffffc0e50000
[   81.922113]  do_one_initcall+0xe2/0x553
[   81.923327]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   81.925257]  ? kasan_unpoison_shadow+0x30/0x40
[   81.926740]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   81.928380]  ? do_init_module+0x49/0x680
[   81.929596]  ? kmem_cache_alloc_trace+0x14b/0x340
[   81.931379]  ? kasan_unpoison_shadow+0x30/0x40
[   81.932731]  do_init_module+0x1da/0x680
[   81.934068]  load_module+0x43e8/0x56d0
[   81.935279]  ? layout_and_allocate+0x2140/0x2140
[   81.936670]  ? kernel_read+0x8b/0x130
[   81.939201]  ? kernel_read_file+0x225/0x4f0
[   81.941881]  ? __do_sys_finit_module+0x11a/0x1b0
[   81.944713]  __do_sys_finit_module+0x11a/0x1b0
[   81.947612]  ? __ia32_sys_init_module+0xa0/0xa0
[   81.950294]  ? __audit_syscall_exit+0x712/0x990
[   81.953091]  ? rcu_read_lock_sched_held+0x102/0x120
[   81.956071]  ? do_syscall_64+0x1d/0x450
[   81.958677]  do_syscall_64+0x9a/0x450
[   81.961299]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   81.964475] RIP: 0033:0x7fd5a5dff1c9
[   81.967100] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   81.975541] RSP: 002b:00007ffd20191428 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   81.979272] RAX: ffffffffffffffda RBX: 0000000000ff21e0 RCX: 00007fd5a5dff1c9
[   81.982971] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   81.986430] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd201915c8
[   81.990361] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   81.993815] R13: 0000000000ff1120 R14: 0000000000000000 R15: 0000000000000000
[  109.851450] watchdog: BUG: soft lockup - CPU#5 stuck for 23s! [insmod:9670]
[  109.854762] Modules linked in: rcu_stall_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ahci libahci e1000 ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt mptspi fb_sys_fops scsi_transport_spi ttm ata_piix mptscsih mptbase libata drm i2c_core
[  109.878754] irq event stamp: 115426
[  109.881000] hardirqs last  enabled at (115425): [<ffffffff96005450>] trace_hardirqs_on_thunk+0x1a/0x1c
[  109.885031] hardirqs last disabled at (115426): [<ffffffff9600546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[  109.889012] softirqs last  enabled at (9066): [<ffffffff97c00675>] __do_softirq+0x675/0x9e3
[  109.892680] softirqs last disabled at (9057): [<ffffffff9617fe64>] irq_exit+0x274/0x2c0
[  109.896225] CPU: 5 PID: 9670 Comm: insmod Kdump: loaded Tainted: G           O L  T 5.0.0 #1
[  109.899928] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  109.904236] RIP: 0010:rcu_stall_test+0xc3/0x1000 [rcu_stall_test]
[  109.907342] Code: e4 c0 be 61 02 00 00 48 c7 c7 e0 10 e4 c0 c6 05 13 20 ff ff 01 e8 c3 16 44 d5 48 8b 45 b8 48 85 c0 74 0d 48 8b 45 b8 48 ff c0 <48> 89 45 b8 eb ea e8 22 07 49 d5 85 c0 74 31 80 3d e7 1f ff ff 00
[  109.915971] RSP: 0018:ffff88808ea6f8e0 EFLAGS: 00000206 ORIG_RAX: ffffffffffffff13
[  109.919662] RAX: 000000072a2a970a RBX: 1ffff11011d4df1c RCX: ffffffff962e75fc
[  109.923276] RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffff8880a13fdc38
[  109.927299] RBP: ffff88808ea6f948 R08: ffffed101427fb88 R09: ffffed101427fb87
[  109.931155] R10: ffffed101427fb87 R11: ffff8880a13fdc3b R12: ffffffffc0e50000
[  109.935083] R13: 0000000000000005 R14: dffffc0000000000 R15: ffffffff98a65064
[  109.938970] FS:  00007fd5a692c740(0000) GS:ffff8880a1200000(0000) knlGS:0000000000000000
[  109.943279] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  109.947343] CR2: 0000000000ff21d8 CR3: 00000000980ee001 CR4: 00000000003606e0
[  109.951796] Call Trace:
[  109.954656]  ? 0xffffffffc0e50000
[  109.957648]  ? 0xffffffffc0e50000
[  109.960259]  do_one_initcall+0xe2/0x553
[  109.963109]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  109.966606]  ? kasan_unpoison_shadow+0x30/0x40
[  109.969413]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  109.972558]  ? do_init_module+0x49/0x680
[  109.975319]  ? kmem_cache_alloc_trace+0x14b/0x340
[  109.978351]  ? kasan_unpoison_shadow+0x30/0x40
[  109.981358]  do_init_module+0x1da/0x680
[  109.983993]  load_module+0x43e8/0x56d0
[  109.986558]  ? layout_and_allocate+0x2140/0x2140
[  109.989321]  ? kernel_read+0x8b/0x130
[  109.991848]  ? kernel_read_file+0x225/0x4f0
[  109.994466]  ? __do_sys_finit_module+0x11a/0x1b0
[  109.997209]  __do_sys_finit_module+0x11a/0x1b0
[  109.999887]  ? __ia32_sys_init_module+0xa0/0xa0
[  110.002602]  ? __audit_syscall_exit+0x712/0x990
[  110.005388]  ? rcu_read_lock_sched_held+0x102/0x120
[  110.008273]  ? do_syscall_64+0x1d/0x450
[  110.010810]  do_syscall_64+0x9a/0x450
[  110.013808]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  110.016623] RIP: 0033:0x7fd5a5dff1c9
[  110.018993] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[  110.027476] RSP: 002b:00007ffd20191428 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  110.031216] RAX: ffffffffffffffda RBX: 0000000000ff21e0 RCX: 00007fd5a5dff1c9
[  110.034542] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  110.038259] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd201915c8
[  110.041617] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[  110.045308] R13: 0000000000ff1120 R14: 0000000000000000 R15: 0000000000000000
[  119.422821] rcu: INFO: rcu_sched self-detected stall on CPU
[  119.427110] rcu: 	5-....: (62830 ticks this GP) idle=bd6/1/0x4000000000000002 softirq=9326/9326 fqs=15346 
[  119.431758] rcu: 	 (t=65000 jiffies g=14133 q=1626)
[  119.434432] NMI backtrace for cpu 5
[  119.436623] CPU: 5 PID: 9670 Comm: insmod Kdump: loaded Tainted: G           O L  T 5.0.0 #1
[  119.440307] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  119.444623] Call Trace:
[  119.446575]  <IRQ>
[  119.448461]  dump_stack+0x9a/0xf0
[  119.451022]  nmi_cpu_backtrace.cold.4+0x13/0x6e
[  119.455198]  ? lapic_can_unplug_cpu.cold.23+0x3f/0x3f
[  119.458496]  nmi_trigger_cpumask_backtrace+0x199/0x21e
[  119.461904]  rcu_dump_cpu_stacks+0x17c/0x1c8
[  119.465230]  rcu_check_callbacks.cold.64+0x3c8/0x6cc
[  119.468403]  ? rcu_read_lock_sched_held+0x102/0x120
[  119.471584]  update_process_times+0x23/0x60
[  119.474700]  tick_sched_handle+0x6f/0x130
[  119.477330]  tick_sched_timer+0x32/0xe0
[  119.480022]  __hrtimer_run_queues+0x2fb/0xb30
[  119.482808]  ? tick_sched_do_timer+0x200/0x200
[  119.485554]  ? hrtimer_start_range_ns+0x9a0/0x9a0
[  119.488322]  ? ktime_get_update_offsets_now+0x97/0x2b0
[  119.491500]  hrtimer_interrupt+0x2c2/0x750
[  119.495229]  smp_apic_timer_interrupt+0x105/0x5b0
[  119.498677]  apic_timer_interrupt+0xf/0x20
[  119.501623]  </IRQ>
[  119.503951] RIP: 0010:rcu_stall_test+0xc7/0x1000 [rcu_stall_test]
[  119.507474] Code: 02 00 00 48 c7 c7 e0 10 e4 c0 c6 05 13 20 ff ff 01 e8 c3 16 44 d5 48 8b 45 b8 48 85 c0 74 0d 48 8b 45 b8 48 ff c0 48 89 45 b8 <eb> ea e8 22 07 49 d5 85 c0 74 31 80 3d e7 1f ff ff 00 75 28 e8 f0
[  119.516346] RSP: 0018:ffff88808ea6f8e0 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13
[  119.519958] RAX: 0000000857d9a532 RBX: 1ffff11011d4df1c RCX: ffffffff962e75fc
[  119.523334] RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffff8880a13fdc38
[  119.527041] RBP: ffff88808ea6f948 R08: ffffed101427fb88 R09: ffffed101427fb87
[  119.531192] R10: ffffed101427fb87 R11: ffff8880a13fdc3b R12: ffffffffc0e50000
[  119.534821] R13: 0000000000000005 R14: dffffc0000000000 R15: ffffffff98a65064
[  119.538824]  ? 0xffffffffc0e50000
[  119.541076]  ? rcu_is_watching+0x2c/0x80
[  119.543576]  ? 0xffffffffc0e50000
[  119.546154]  ? 0xffffffffc0e50000
[  119.548692]  do_one_initcall+0xe2/0x553
[  119.551002]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  119.554896]  ? kasan_unpoison_shadow+0x30/0x40
[  119.558318]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  119.562078]  ? do_init_module+0x49/0x680
[  119.564431]  ? kmem_cache_alloc_trace+0x14b/0x340
[  119.567019]  ? kasan_unpoison_shadow+0x30/0x40
[  119.569525]  do_init_module+0x1da/0x680
[  119.571828]  load_module+0x43e8/0x56d0
[  119.575929]  ? layout_and_allocate+0x2140/0x2140
[  119.579897]  ? kernel_read+0x8b/0x130
[  119.583995]  ? kernel_read_file+0x225/0x4f0
[  119.586807]  ? __do_sys_finit_module+0x11a/0x1b0
[  119.590831]  __do_sys_finit_module+0x11a/0x1b0
[  119.594613]  ? __ia32_sys_init_module+0xa0/0xa0
[  119.597852]  ? __audit_syscall_exit+0x712/0x990
[  119.600942]  ? rcu_read_lock_sched_held+0x102/0x120
[  119.603670]  ? do_syscall_64+0x1d/0x450
[  119.605841]  do_syscall_64+0x9a/0x450
[  119.608331]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  119.611327] RIP: 0033:0x7fd5a5dff1c9
[  119.613769] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[  119.621918] RSP: 002b:00007ffd20191428 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  119.625763] RAX: ffffffffffffffda RBX: 0000000000ff21e0 RCX: 00007fd5a5dff1c9
[  119.629830] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  119.633627] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd201915c8
[  119.637209] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[  119.640755] R13: 0000000000ff1120 R14: 0000000000000000 R15: 0000000000000000
[  129.721864] rcu: INFO: rcu_sched detected expedited stalls on CPUs/tasks: { 5-... } 68730 jiffies s: 8393 root: 0x1/.
[  129.728195] rcu: blocking rcu_node structures: l=1:0-15:0x20/.
[  129.731824] Task dump for CPU 5:
[  129.735227] insmod          R  running task    27120  9670   9655 0x80000088
[  129.739724] Call Trace:
[  129.741690]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  129.744774]  ? kasan_unpoison_shadow+0x30/0x40
[  129.747434]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  129.751899]  ? do_init_module+0x49/0x680
[  129.755494]  ? kmem_cache_alloc_trace+0x14b/0x340
[  129.759272]  ? kasan_unpoison_shadow+0x30/0x40
[  129.762629]  ? do_init_module+0x1da/0x680
[  129.765898]  ? load_module+0x43e8/0x56d0
[  129.769006]  ? layout_and_allocate+0x2140/0x2140
[  129.774336]  ? kernel_read+0x8b/0x130
[  129.776644]  ? kernel_read_file+0x225/0x4f0
[  129.780387]  ? __do_sys_finit_module+0x11a/0x1b0
[  129.783162]  ? __do_sys_finit_module+0x11a/0x1b0
[  129.786083]  ? __ia32_sys_init_module+0xa0/0xa0
[  129.789766]  ? __audit_syscall_exit+0x712/0x990
[  129.793004]  ? rcu_read_lock_sched_held+0x102/0x120
[  129.796704]  ? do_syscall_64+0x1d/0x450
[  129.799567]  ? do_syscall_64+0x9a/0x450
[  129.803623]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  145.852052] watchdog: BUG: soft lockup - CPU#5 stuck for 22s! [insmod:9670]
[  145.855207] Modules linked in: rcu_stall_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ahci libahci e1000 ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt mptspi fb_sys_fops scsi_transport_spi ttm ata_piix mptscsih mptbase libata drm i2c_core
[  145.880379] irq event stamp: 185284
[  145.882927] hardirqs last  enabled at (185283): [<ffffffff96005450>] trace_hardirqs_on_thunk+0x1a/0x1c
[  145.887312] hardirqs last disabled at (185284): [<ffffffff9600546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[  145.891676] softirqs last  enabled at (9066): [<ffffffff97c00675>] __do_softirq+0x675/0x9e3
[  145.895562] softirqs last disabled at (9057): [<ffffffff9617fe64>] irq_exit+0x274/0x2c0
[  145.899383] CPU: 5 PID: 9670 Comm: insmod Kdump: loaded Tainted: G           O L  T 5.0.0 #1
[  145.903220] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  145.907928] RIP: 0010:rcu_stall_test+0xc7/0x1000 [rcu_stall_test]
[  145.911144] Code: 02 00 00 48 c7 c7 e0 10 e4 c0 c6 05 13 20 ff ff 01 e8 c3 16 44 d5 48 8b 45 b8 48 85 c0 74 0d 48 8b 45 b8 48 ff c0 48 89 45 b8 <eb> ea e8 22 07 49 d5 85 c0 74 31 80 3d e7 1f ff ff 00 75 28 e8 f0
[  145.919566] RSP: 0018:ffff88808ea6f8e0 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13
[  145.923164] RAX: 0000000bbf8a9d86 RBX: 1ffff11011d4df1c RCX: ffffffff962e75fc
[  145.926690] RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffff8880a13fdc38
[  145.930302] RBP: ffff88808ea6f948 R08: ffffed101427fb88 R09: ffffed101427fb87
[  145.933983] R10: ffffed101427fb87 R11: ffff8880a13fdc3b R12: ffffffffc0e50000
[  145.937527] R13: 0000000000000005 R14: dffffc0000000000 R15: ffffffff98a65064
[  145.941070] FS:  00007fd5a692c740(0000) GS:ffff8880a1200000(0000) knlGS:0000000000000000
[  145.945049] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  145.948407] CR2: 0000000000ff21d8 CR3: 00000000980ee001 CR4: 00000000003606e0
[  145.952185] Call Trace:
[  145.954381]  ? 0xffffffffc0e50000
[  145.956853]  ? 0xffffffffc0e50000
[  145.959208]  do_one_initcall+0xe2/0x553
[  145.961857]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  145.964924]  ? kasan_unpoison_shadow+0x30/0x40
[  145.967655]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  145.970489]  ? do_init_module+0x49/0x680
[  145.973161]  ? kmem_cache_alloc_trace+0x14b/0x340
[  145.975794]  ? kasan_unpoison_shadow+0x30/0x40
[  145.978449]  do_init_module+0x1da/0x680
[  145.981197]  load_module+0x43e8/0x56d0
[  145.983836]  ? layout_and_allocate+0x2140/0x2140
[  145.986587]  ? kernel_read+0x8b/0x130
[  145.989076]  ? kernel_read_file+0x225/0x4f0
[  145.991882]  ? __do_sys_finit_module+0x11a/0x1b0
[  145.994683]  __do_sys_finit_module+0x11a/0x1b0
[  145.997458]  ? __ia32_sys_init_module+0xa0/0xa0
[  146.000323]  ? __audit_syscall_exit+0x712/0x990
[  146.003155]  ? rcu_read_lock_sched_held+0x102/0x120
[  146.006175]  ? do_syscall_64+0x1d/0x450
[  146.008683]  do_syscall_64+0x9a/0x450
[  146.011476]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  146.014424] RIP: 0033:0x7fd5a5dff1c9
[  146.016863] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[  146.025313] RSP: 002b:00007ffd20191428 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  146.029010] RAX: ffffffffffffffda RBX: 0000000000ff21e0 RCX: 00007fd5a5dff1c9
[  146.032614] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  146.035929] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd201915c8
[  146.039206] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[  146.042466] R13: 0000000000ff1120 R14: 0000000000000000 R15: 0000000000000000
[  173.851896] watchdog: BUG: soft lockup - CPU#5 stuck for 22s! [insmod:9670]
[  173.855266] Modules linked in: rcu_stall_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ahci libahci e1000 ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea sysfillrect sysimgblt mptspi fb_sys_fops scsi_transport_spi ttm ata_piix mptscsih mptbase libata drm i2c_core
[  173.879949] irq event stamp: 240666
[  173.882400] hardirqs last  enabled at (240665): [<ffffffff96005450>] trace_hardirqs_on_thunk+0x1a/0x1c
[  173.886735] hardirqs last disabled at (240666): [<ffffffff9600546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[  173.891091] softirqs last  enabled at (9066): [<ffffffff97c00675>] __do_softirq+0x675/0x9e3
[  173.894812] softirqs last disabled at (9057): [<ffffffff9617fe64>] irq_exit+0x274/0x2c0
[  173.898755] CPU: 5 PID: 9670 Comm: insmod Kdump: loaded Tainted: G           O L  T 5.0.0 #1
[  173.902657] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  173.907472] RIP: 0010:rcu_stall_test+0xbc/0x1000 [rcu_stall_test]
[  173.910711] Code: 75 1f 48 c7 c2 80 10 e4 c0 be 61 02 00 00 48 c7 c7 e0 10 e4 c0 c6 05 13 20 ff ff 01 e8 c3 16 44 d5 48 8b 45 b8 48 85 c0 74 0d <48> 8b 45 b8 48 ff c0 48 89 45 b8 eb ea e8 22 07 49 d5 85 c0 74 31
[  173.919484] RSP: 0018:ffff88808ea6f8e0 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13
[  173.923297] RAX: 0000000f6c751225 RBX: 1ffff11011d4df1c RCX: ffffffff962e75fc
[  173.927091] RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffff8880a13fdc38
[  173.930854] RBP: ffff88808ea6f948 R08: ffffed101427fb88 R09: ffffed101427fb87
[  173.934723] R10: ffffed101427fb87 R11: ffff8880a13fdc3b R12: ffffffffc0e50000
[  173.938294] R13: 0000000000000005 R14: dffffc0000000000 R15: ffffffff98a65064
[  173.942018] FS:  00007fd5a692c740(0000) GS:ffff8880a1200000(0000) knlGS:0000000000000000
[  173.946008] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  173.949329] CR2: 0000000000ff21d8 CR3: 00000000980ee001 CR4: 00000000003606e0
[  173.953213] Call Trace:
[  173.955948]  ? 0xffffffffc0e50000
[  173.958606]  ? 0xffffffffc0e50000
[  173.961184]  do_one_initcall+0xe2/0x553
[  173.963819]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  173.967076]  ? kasan_unpoison_shadow+0x30/0x40
[  173.969991]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  173.973073]  ? do_init_module+0x49/0x680
[  173.975884]  ? kmem_cache_alloc_trace+0x14b/0x340
[  173.978770]  ? kasan_unpoison_shadow+0x30/0x40
[  173.981947]  do_init_module+0x1da/0x680
[  173.984959]  load_module+0x43e8/0x56d0
[  173.988023]  ? layout_and_allocate+0x2140/0x2140
[  173.991153]  ? kernel_read+0x8b/0x130
[  173.994190]  ? kernel_read_file+0x225/0x4f0
[  173.996881]  ? __do_sys_finit_module+0x11a/0x1b0
[  173.999565]  __do_sys_finit_module+0x11a/0x1b0
[  174.002310]  ? __ia32_sys_init_module+0xa0/0xa0
[  174.005096]  ? __audit_syscall_exit+0x712/0x990
[  174.007842]  ? rcu_read_lock_sched_held+0x102/0x120
[  174.010774]  ? do_syscall_64+0x1d/0x450
[  174.013504]  do_syscall_64+0x9a/0x450
[  174.016269]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  174.019708] RIP: 0033:0x7fd5a5dff1c9
[  174.022375] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[  174.031943] RSP: 002b:00007ffd20191428 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[  174.035984] RAX: ffffffffffffffda RBX: 0000000000ff21e0 RCX: 00007fd5a5dff1c9
[  174.039387] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  174.043395] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd201915c8
[  174.047298] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[  174.050728] R13: 0000000000ff1120 R14: 0000000000000000 R15: 0000000000000000
[  187.064626] INFO: task systemd-hostnam:5560 blocked for more than 120 seconds.
[  187.068198]       Tainted: G           O L  T 5.0.0 #1
[  187.071266] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  187.074786] systemd-hostnam D25200  5560      1 0x80000082
[  187.077714] Call Trace:
[  187.079683]  ? __schedule+0x71f/0x18f0
[  187.082058]  ? __sched_text_start+0x8/0x8
[  187.084480]  schedule+0x77/0x170
[  187.087113]  _synchronize_rcu_expedited.constprop.54+0x3ba/0x540
[  187.091151]  ? wait_rcu_exp_gp+0x70/0x70
[  187.093549]  ? wait_woken+0x260/0x260
[  187.095992]  ? find_held_lock+0x3a/0x1c0
[  187.098333]  ? sched_clock+0x5/0x10
[  187.101035]  ? sched_clock_cpu+0x18/0x170
[  187.105686]  ? find_held_lock+0x3a/0x1c0
[  187.109736]  ? rcu_barrier_func+0xd0/0xd0
[  187.112286]  ? sync_rcu_exp_select_cpus+0x7d0/0x7d0
[  187.115107]  namespace_unlock+0xcc/0xf0
[  187.117770]  ? m_start+0x2e0/0x2e0
[  187.120020]  ? do_raw_spin_unlock+0x4f/0x220
[  187.122399]  ? _raw_spin_unlock+0x1f/0x30
[  187.124830]  put_mnt_ns+0x4b/0x60
[  187.127304]  free_nsproxy+0x31/0x1a0
[  187.130729]  do_exit+0x97e/0x2ad0
[  187.132815]  ? mm_update_next_owner+0x5c0/0x5c0
[  187.135321]  ? syscall_trace_enter+0x5b9/0xde0
[  187.137659]  ? syscall_slow_exit_work+0x470/0x470
[  187.140401]  ? up_read+0x131/0x170
[  187.142547]  do_group_exit+0xeb/0x2d0
[  187.144846]  __x64_sys_exit_group+0x35/0x40
[  187.147199]  do_syscall_64+0x9a/0x450
[  187.149368]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  187.152718] RIP: 0033:0x7f69efca11d9
[  187.157133] Code: Bad RIP value.
[  187.160096] RSP: 002b:00007ffe5b33d128 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
[  187.163496] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f69efca11d9
[  187.167184] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[  187.170547] RBP: 00007f69eff9e838 R08: 000000000000003c R09: 00000000000000e7
[  187.174603] R10: fffffffffffffe10 R11: 0000000000000246 R12: 00007f69eff9e838
[  187.178268] R13: 00007f69effa3e80 R14: 0000000000000000 R15: 0000000000000000
[  187.182091] 
[  187.182091] Showing all locks held in the system:
[  187.185951] 1 lock held by khungtaskd/54:
[  187.188528]  #0: 00000000811f67dd (rcu_read_lock){....}, at: debug_show_all_locks+0x52/0x2a7
[  187.194415] 2 locks held by kworker/1:1/65:
[  187.198499]  #0: 0000000073eb71b6 ((wq_completion)"rcu_gp"){+.+.}, at: process_one_work+0xa65/0x1d10
[  187.205265]  #1: 000000005750ff1b ((work_completion)(&rew.rew_work)){+.+.}, at: process_one_work+0xa99/0x1d10
[  187.209318] 1 lock held by systemd-journal/4651:
[  187.211655]  #0: 00000000306f5d60 (&rq->lock){-.-.}, at: pick_next_task_fair+0x1158/0x1970
[  187.215493] 1 lock held by systemd-hostnam/5560:
[  187.217792]  #0: 00000000632a8c8a (rcu_state.exp_mutex){+.+.}, at: _synchronize_rcu_expedited.constprop.54+0x264/0x540
[  187.223731] 2 locks held by agetty/9412:
[  187.226921]  #0: 000000009ad72d94 (&tty->ldisc_sem){++++}, at: tty_ldisc_ref_wait+0x22/0x80
[  187.230647]  #1: 0000000029a6cee3 (&ldata->atomic_read_lock){+.+.}, at: n_tty_read+0x1f1/0x1660
[  187.234332] 1 lock held by insmod/9670:
[  187.236938] 
[  187.238564] =============================================
[  187.238564] 

ケース10:割り込みを禁止したまま時間のかかる処理に没頭してしまう例

割り込みを禁止している間も、時間のかかる処理を避ける必要があります。割り込みを禁止したまま時間のかかる処理を行ってしまった場合に、どのようなメッセージが出力されるかを見てみましょう。

irq_stall_test.c :割り込み禁止ストール警告メッセージを出力させるカーネルモジュールの例

#include <linux/module.h>

static int __init irq_stall_test(void)
{
        volatile long i = 1;

        local_irq_disable();
        while (i)
                i++;
        local_irq_enable();
        return -EINVAL;
}

module_init(irq_stall_test);
MODULE_LICENSE("GPL");

NMI(マスク不可能な割り込み処理)という処理を発生させることにより、割り込みを禁止している状態で時間のかかる処理を実行している場所が報告されます。

[   54.382165] irq_stall_test: loading out-of-tree module taints kernel.
[  119.385265] rcu: INFO: rcu_sched detected stalls on CPUs/tasks:
[  119.387179] rcu: 	5-...0: (3 ticks this GP) idle=682/1/0x4000000000000000 softirq=9897/9897 fqs=14493 
[  119.390032] rcu: 	(detected by 4, t=65002 jiffies, g=14185, q=1179)
[  119.392085] Sending NMI from CPU 4 to CPUs 5:
[  119.395291] NMI backtrace for cpu 5
[  119.395293] CPU: 5 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[  119.395295] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  119.395297] RIP: 0010:irq_stall_test+0x72/0x1000 [irq_stall_test]
[  119.395300] Code: 44 24 20 01 00 00 00 fa 66 0f 1f 44 00 00 e8 b5 b2 67 da 48 8b 44 24 20 48 85 c0 74 0f 48 8b 44 24 20 48 ff c0 48 89 44 24 20 <eb> e7 e8 37 b4 67 da fb 66 0f 1f 44 00 00 b8 ff ff 37 00 b9 03 00
[  119.395301] RSP: 0018:ffff88809b84f8e8 EFLAGS: 00000002
[  119.395305] RAX: 000000086e31685b RBX: 1ffff11013709f1d RCX: 0000000000000000
[  119.395306] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8880968e82d4
[  119.395308] RBP: 1ffff11013709f2d R08: ffffed101427fb88 R09: 0000000000000001
[  119.395309] R10: ffffed101427fb87 R11: ffff8880a13fdc3b R12: ffffffffc0db8000
[  119.395311] R13: 0000000000000005 R14: ffffffffc0da9000 R15: ffffffff9da65064
[  119.395312] FS:  00007f70ba0d0740(0000) GS:ffff8880a1200000(0000) knlGS:0000000000000000
[  119.395314] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  119.395315] CR2: 0000000000b9d1d8 CR3: 0000000095178001 CR4: 00000000003606e0
[  119.395316] Call Trace:
[  119.395318]  ? 0xffffffffc0db8000
[  119.395319]  ? 0xffffffffc0db8000
[  119.395320]  ? rcu_read_lock_sched_held+0x102/0x120
[  119.395322]  do_one_initcall+0xe2/0x553
[  119.395323]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  119.395325]  ? kasan_unpoison_shadow+0x30/0x40
[  119.395326]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  119.395327]  ? do_init_module+0x49/0x680
[  119.395329]  ? kmem_cache_alloc_trace+0x14b/0x340
[  119.395330]  ? __kasan_slab_free+0x126/0x150
[  119.395331]  do_init_module+0x1da/0x680
[  119.395333]  load_module+0x43e8/0x56d0
[  119.395334]  ? layout_and_allocate+0x2140/0x2140
[  119.395335]  ? kernel_read+0x8b/0x130
[  119.395337]  ? kernel_read_file+0x225/0x4f0
[  119.395338]  ? __do_sys_finit_module+0x11a/0x1b0
[  119.395339]  __do_sys_finit_module+0x11a/0x1b0
[  119.395341]  ? __ia32_sys_init_module+0xa0/0xa0
[  119.395342]  ? __audit_syscall_exit+0x712/0x990
[  119.395343]  ? rcu_read_lock_sched_held+0x102/0x120
[  119.395345]  ? do_syscall_64+0x1d/0x450
[  119.395346]  do_syscall_64+0x9a/0x450
[  119.395347]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  119.395349] RIP: 0033:0x7f70b95a31c9
[  119.395351] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[  119.395353] RSP: 002b:00007ffc5cf40b68 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
[  119.395356] RAX: ffffffffffffffda RBX: 0000000000b9d1e0 RCX: 00007f70b95a31c9
[  119.395357] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[  119.395359] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffc5cf40d08
[  119.395360] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
[  119.395362] R13: 0000000000b9c120 R14: 0000000000000000 R15: 0000000000000000
[  125.662814] rcu: INFO: rcu_sched detected expedited stalls on CPUs/tasks: { 5-... } 65254 jiffies s: 8393 root: 0x1/.
[  125.667619] rcu: blocking rcu_node structures: l=1:0-15:0x20/.
[  125.670572] Task dump for CPU 5:
[  125.672973] insmod          R  running task    27976  9669   9654 0x80000088
[  125.676333] Call Trace:
[  125.678353]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[  125.681557]  ? kasan_unpoison_shadow+0x30/0x40
[  125.685097]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[  125.690059]  ? do_init_module+0x49/0x680
[  125.692628]  ? kmem_cache_alloc_trace+0x14b/0x340
[  125.695227]  ? __kasan_slab_free+0x126/0x150
[  125.697559]  ? do_init_module+0x1da/0x680
[  125.701641]  ? load_module+0x43e8/0x56d0
[  125.705795]  ? layout_and_allocate+0x2140/0x2140
[  125.709450]  ? kernel_read+0x8b/0x130
[  125.711612]  ? kernel_read_file+0x225/0x4f0
[  125.714148]  ? __do_sys_finit_module+0x11a/0x1b0
[  125.716851]  ? __do_sys_finit_module+0x11a/0x1b0
[  125.719543]  ? __ia32_sys_init_module+0xa0/0xa0
[  125.722316]  ? __audit_syscall_exit+0x712/0x990
[  125.725324]  ? rcu_read_lock_sched_held+0x102/0x120
[  125.728049]  ? do_syscall_64+0x1d/0x450
[  125.730216]  ? do_syscall_64+0x9a/0x450
[  125.732433]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  186.079267] INFO: task systemd-hostnam:5632 blocked for more than 120 seconds.
[  186.083045]       Tainted: G           O    T 5.0.0 #1
[  186.086561] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  186.090126] systemd-hostnam D25200  5632      1 0x80000082
[  186.093147] Call Trace:
[  186.095018]  ? __schedule+0x71f/0x18f0
[  186.097351]  ? __sched_text_start+0x8/0x8
[  186.102029]  schedule+0x77/0x170
[  186.106156]  _synchronize_rcu_expedited.constprop.54+0x3ba/0x540
[  186.110275]  ? wait_rcu_exp_gp+0x70/0x70
[  186.115071]  ? wait_woken+0x260/0x260
[  186.118757]  ? find_held_lock+0x3a/0x1c0
[  186.121193]  ? sched_clock+0x5/0x10
[  186.123550]  ? sched_clock_cpu+0x18/0x170
[  186.125907]  ? find_held_lock+0x3a/0x1c0
[  186.128160]  ? rcu_barrier_func+0xd0/0xd0
[  186.130482]  ? sync_rcu_exp_select_cpus+0x7d0/0x7d0
[  186.132982]  namespace_unlock+0xcc/0xf0
[  186.135585]  ? m_start+0x2e0/0x2e0
[  186.137964]  ? do_raw_spin_unlock+0x4f/0x220
[  186.140689]  ? _raw_spin_unlock+0x1f/0x30
[  186.144956]  put_mnt_ns+0x4b/0x60
[  186.149001]  free_nsproxy+0x31/0x1a0
[  186.153266]  do_exit+0x97e/0x2ad0
[  186.157237]  ? mm_update_next_owner+0x5c0/0x5c0
[  186.160851]  ? syscall_trace_enter+0x5b9/0xde0
[  186.163054]  ? syscall_slow_exit_work+0x470/0x470
[  186.165525]  ? up_read+0x131/0x170
[  186.169291]  do_group_exit+0xeb/0x2d0
[  186.171327]  __x64_sys_exit_group+0x35/0x40
[  186.173451]  do_syscall_64+0x9a/0x450
[  186.175340]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  186.177801] RIP: 0033:0x7faad7dda1d9
[  186.179848] Code: Bad RIP value.
[  186.181988] RSP: 002b:00007ffe1b63c948 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
[  186.187001] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007faad7dda1d9
[  186.190793] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[  186.193942] RBP: 00007faad80d7838 R08: 000000000000003c R09: 00000000000000e7
[  186.197581] R10: fffffffffffffe10 R11: 0000000000000246 R12: 00007faad80d7838
[  186.203118] R13: 00007faad80dce80 R14: 0000000000000000 R15: 0000000000000000
[  186.207692] 
[  186.207692] Showing all locks held in the system:
[  186.214162] 1 lock held by khungtaskd/54:
[  186.216769]  #0: 00000000bba3c3f2 (rcu_read_lock){....}, at: debug_show_all_locks+0x52/0x2a7
[  186.221228] 2 locks held by kworker/2:2/211:
[  186.223400]  #0: 00000000776f4a2d ((wq_completion)"rcu_gp"){+.+.}, at: process_one_work+0xa65/0x1d10
[  186.228068]  #1: 00000000f4c1fccf ((work_completion)(&rew.rew_work)){+.+.}, at: process_one_work+0xa99/0x1d10
[  186.235730] 1 lock held by systemd-hostnam/5632:
[  186.238226]  #0: 00000000bfe232a2 (rcu_state.exp_mutex){+.+.}, at: _synchronize_rcu_expedited.constprop.54+0x264/0x540
[  186.242539] 2 locks held by agetty/9412:
[  186.244934]  #0: 000000006688673b (&tty->ldisc_sem){++++}, at: tty_ldisc_ref_wait+0x22/0x80
[  186.248807]  #1: 0000000013d418ab (&ldata->atomic_read_lock){+.+.}, at: n_tty_read+0x1f1/0x1660
[  186.252444] 
[  186.254105] =============================================
[  186.254105] 

ケース11:単純な use-after-free の例

動的に割り当て/解放されるメモリ領域に関して、既に解放されたメモリ領域にアクセスしてしまった場合、( KASAN という機能が有効であれば) use-after-free として報告されます。

use_after_free_test.c : use-after-free をしてしまうカーネルモジュールの例

#include <linux/module.h>
#include <linux/slab.h>

static int __init use_after_free_test(void)
{
        char *ptr = kmalloc(PAGE_SIZE, GFP_KERNEL | __GFP_NOFAIL);

        memset(ptr, 0, PAGE_SIZE);
        kfree(ptr);
        return *ptr == '\0' ? 0 : -EINVAL;
}

module_init(use_after_free_test);
MODULE_LICENSE("GPL");

KASAN により、 use-after-free として報告されています。 syzbot を用いたテストでは、 syzbot がマルチスレッドなテストケースを実行し、 KASAN がメモリ領域へのアクセスを検査することで、いろいろな個所で use-after-free バグを検出してくれています。

[   53.053166] use_after_free_test: loading out-of-tree module taints kernel.
[   53.059240] ==================================================================
[   53.061331] BUG: KASAN: use-after-free in use_after_free_test+0x74/0x1000 [use_after_free_test]
[   53.063701] Read of size 1 at addr ffff88809614c588 by task insmod/9669
[   53.065552] 
[   53.065984] CPU: 4 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   53.068250] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   53.071293] Call Trace:
[   53.072035]  dump_stack+0x9a/0xf0
[   53.073460]  ? use_after_free_test+0x74/0x1000 [use_after_free_test]
[   53.075321]  print_address_description.cold.4+0x9/0x230
[   53.076865]  ? use_after_free_test+0x74/0x1000 [use_after_free_test]
[   53.078562]  ? use_after_free_test+0x74/0x1000 [use_after_free_test]
[   53.080380]  kasan_report.cold.5+0x1a/0x32
[   53.081582]  ? use_after_free_test+0x74/0x1000 [use_after_free_test]
[   53.083434]  ? 0xffffffffc0f70000
[   53.084573]  use_after_free_test+0x74/0x1000 [use_after_free_test]
[   53.086234]  do_one_initcall+0xe2/0x553
[   53.087282]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   53.089274]  ? kasan_unpoison_shadow+0x30/0x40
[   53.090482]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   53.091957]  ? do_init_module+0x49/0x680
[   53.093148]  ? kmem_cache_alloc_trace+0x14b/0x340
[   53.094421]  ? __kasan_slab_free+0x126/0x150
[   53.095583]  do_init_module+0x1da/0x680
[   53.096747]  load_module+0x43e8/0x56d0
[   53.097798]  ? layout_and_allocate+0x2140/0x2140
[   53.099047]  ? kernel_read+0x8b/0x130
[   53.100169]  ? kernel_read_file+0x225/0x4f0
[   53.101322]  ? __do_sys_finit_module+0x11a/0x1b0
[   53.102565]  __do_sys_finit_module+0x11a/0x1b0
[   53.104047]  ? __ia32_sys_init_module+0xa0/0xa0
[   53.105300]  ? __audit_syscall_exit+0x712/0x990
[   53.106829]  ? rcu_read_lock_sched_held+0x102/0x120
[   53.108086]  ? do_syscall_64+0x1d/0x450
[   53.109076]  do_syscall_64+0x9a/0x450
[   53.110021]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   53.111552] RIP: 0033:0x7f986395b1c9
[   53.112477] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   53.118569] RSP: 002b:00007fffa34a03e8 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[   53.121523] RAX: ffffffffffffffda RBX: 00000000025b61e0 RCX: 00007f986395b1c9
[   53.124985] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   53.127908] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007fffa34a0588
[   53.130738] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000000000
[   53.133625] R13: 00000000025b5120 R14: 0000000000000000 R15: 0000000000000000
[   53.136797] 
[   53.136801] Allocated by task 9669:
[   53.136808]  __kasan_kmalloc.constprop.8+0xc1/0xd0
[   53.136810]  kmem_cache_alloc_trace+0x14b/0x340
[   53.136816]  use_after_free_test+0x39/0x1000 [use_after_free_test]
[   53.136819]  do_one_initcall+0xe2/0x553
[   53.136821]  do_init_module+0x1da/0x680
[   53.136823]  load_module+0x43e8/0x56d0
[   53.136825]  __do_sys_finit_module+0x11a/0x1b0
[   53.136827]  do_syscall_64+0x9a/0x450
[   53.136830]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   53.136831] 
[   53.136833] Freed by task 9669:
[   53.136835]  __kasan_slab_free+0x111/0x150
[   53.136837]  slab_free_freelist_hook+0x60/0x120
[   53.136840]  kfree+0xd6/0x2e0
[   53.136842]  use_after_free_test+0x53/0x1000 [use_after_free_test]
[   53.136846]  do_one_initcall+0xe2/0x553
[   53.136847]  do_init_module+0x1da/0x680
[   53.136849]  load_module+0x43e8/0x56d0
[   53.177123]  __do_sys_finit_module+0x11a/0x1b0
[   53.179002]  do_syscall_64+0x9a/0x450
[   53.180849]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   53.182905] 
[   53.184113] The buggy address belongs to the object at ffff88809614c588
[   53.184113]  which belongs to the cache kmalloc-4k of size 4096
[   53.189427] The buggy address is located 0 bytes inside of
[   53.189427]  4096-byte region [ffff88809614c588, ffff88809614d588)
[   53.194147] The buggy address belongs to the page:
[   53.196325] page:ffffea0002585200 count:1 mapcount:0 mapping:ffff888107c165c0 index:0xffff88809614d6e8 compound_mapcount: 0
[   53.200057] flags: 0x1fffff80010200(slab|head)
[   53.202151] raw: 001fffff80010200 ffffea000408e808 ffff888107c01050 ffff888107c165c0
[   53.205439] raw: ffff88809614d6e8 0000000000070006 00000001ffffffff 0000000000000000
[   53.208609] page dumped because: kasan: bad access detected
[   53.211211] 
[   53.212609] Memory state around the buggy address:
[   53.215015]  ffff88809614c480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[   53.217960]  ffff88809614c500: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[   53.220998] >ffff88809614c580: fc fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   53.224134]                       ^
[   53.226186]  ffff88809614c600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   53.228980]  ffff88809614c680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   53.231901] ==================================================================
[   53.234857] Disabling lock debugging due to kernel taint

ケース12:単純な NULL pointer dereference の例

ポインタを返却する処理でエラーが発生した場合に、(エラーの原因が自明であるなどの理由により)エラーコードを返却する必要が無い場合は、 NULL が返却されます。しかし、 NULL が返却された場合に、誤ってアクセスしてしまうと、 NULL pointer dereference と呼ばれる問題が発生します。

null_pointer_deref_test.c : NULL ポインタを参照してしまうカーネルモジュールの例

#include <linux/module.h>

static int __init null_pointer_deref_test(void)
{
        char *ptr = NULL;

        return *ptr == '\0' ? 0 : -EINVAL;
}

module_init(null_pointer_deref_test);
MODULE_LICENSE("GPL");

誤ってアクセスしてしまった際のアドレスが0番地の近くになるという性質があります。

[   52.822420] null_pointer_deref_test: loading out-of-tree module taints kernel.
[   52.829446] kasan: CONFIG_KASAN_INLINE enabled
[   52.830871] kasan: GPF could be caused by NULL-ptr deref or user memory access
[   52.832952] general protection fault: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI
[   52.834924] CPU: 4 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   52.837302] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   52.837309] RIP: 0010:null_pointer_deref_test+0x0/0x1000 [null_pointer_deref_test]
[   52.837313] Code: Bad RIP value.
[   52.837331] RSP: 0018:ffff88809ba5f950 EFLAGS: 00010286
[   52.837332] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000000001
[   52.837334] RDX: 1ffff1101353d84d RSI: ffff88809a9ec25c RDI: 0000000000000246
[   52.837335] RBP: 1ffff1101374bf2d R08: ffffed10141ffb88 R09: 0000000000000001
[   52.837336] R10: ffffed10141ffb87 R11: ffff8880a0ffdc3b R12: ffffffffc0d00000
[   52.837337] R13: 0000000000000004 R14: ffffffffc0ce1000 R15: ffffffffb3a65064
[   52.837338] FS:  00007fccb029b740(0000) GS:ffff8880a0e00000(0000) knlGS:0000000000000000
[   52.837339] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   52.837340] CR2: ffffffffc0cfffd6 CR3: 0000000091ef4003 CR4: 00000000003606e0
[   52.837365] Call Trace:
[   52.861499]  do_one_initcall+0xe2/0x553
[   52.861506]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   52.861512]  ? kasan_unpoison_shadow+0x30/0x40
[   52.861515]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   52.861518]  ? do_init_module+0x49/0x680
[   52.861522]  ? kmem_cache_alloc_trace+0x14b/0x340
[   52.869493]  ? __kasan_slab_free+0x126/0x150
[   52.869498]  do_init_module+0x1da/0x680
[   52.869503]  load_module+0x43e8/0x56d0
[   52.869513]  ? layout_and_allocate+0x2140/0x2140
[   52.869517]  ? kernel_read+0x8b/0x130
[   52.869520]  ? kernel_read_file+0x225/0x4f0
[   52.869527]  ? __do_sys_finit_module+0x11a/0x1b0
[   52.869528]  __do_sys_finit_module+0x11a/0x1b0
[   52.869530]  ? __ia32_sys_init_module+0xa0/0xa0
[   52.869534]  ? __audit_syscall_exit+0x712/0x990
[   52.869537]  ? rcu_read_lock_sched_held+0x102/0x120
[   52.869542]  ? do_syscall_64+0x1d/0x450
[   52.869544]  do_syscall_64+0x9a/0x450
[   52.869548]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   52.869550] RIP: 0033:0x7fccaf76e1c9
[   52.869553] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   52.869554] RSP: 002b:00007ffee39b74f8 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
[   52.869556] RAX: ffffffffffffffda RBX: 0000000000b7e1e0 RCX: 00007fccaf76e1c9
[   52.869557] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   52.869558] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffee39b7698
[   52.869559] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
[   52.869560] R13: 0000000000b7d120 R14: 0000000000000000 R15: 0000000000000000
[   52.869564] Modules linked in: null_pointer_deref_test(O+) vmw_balloon pcspkr ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter sg i2c_piix4 vmw_vmci ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ata_generic pata_acpi e1000 vmwgfx ahci libahci drm_kms_helper syscopyarea sysfillrect sysimgblt mptspi fb_sys_fops scsi_transport_spi mptscsih ttm mptbase drm ata_piix i2c_core libata
[   52.935860] ---[ end trace 7e64b73e3c02ba76 ]---
[   52.935871] RIP: 0010:null_pointer_deref_test+0x0/0x1000 [null_pointer_deref_test]
[   52.935876] Code: Bad RIP value.
[   52.935878] RSP: 0018:ffff88809ba5f950 EFLAGS: 00010286
[   52.935881] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000000001
[   52.949979] RDX: 1ffff1101353d84d RSI: ffff88809a9ec25c RDI: 0000000000000246
[   52.949981] RBP: 1ffff1101374bf2d R08: ffffed10141ffb88 R09: 0000000000000001
[   52.949982] R10: ffffed10141ffb87 R11: ffff8880a0ffdc3b R12: ffffffffc0d00000
[   52.949983] R13: 0000000000000004 R14: ffffffffc0ce1000 R15: ffffffffb3a65064
[   52.949984] FS:  00007fccb029b740(0000) GS:ffff8880a0e00000(0000) knlGS:0000000000000000
[   52.949985] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   52.949986] CR2: ffffffffc0cfffd6 CR3: 0000000091ef4003 CR4: 00000000003606e0

ケース13:単純な error pointer dereference の例

ユーザランドでは、何かの処理を行った場合のエラーは errno という変数に0より大きな整数値を格納することで、エラーが発生したことを伝えます。そのため、ポインタを返却する処理でエラーが発生した場合には、関数は errno にエラーコードを設定の上、関数自体は NULL を返却します。

しかし、 Linux カーネルの世界では、何かの処理を行った場合のエラーは error という変数を使わずに、関数の戻り値として0より小さな整数値を返却するという方法でエラーが発生したことを伝えます。そのため、ポインタを返却する処理でエラーが発生した場合、関数自体は NULL の代わりにエラーコードをキャストを用いてポインタ化したものを返却します。

そのため、 Linux カーネルの世界には、ポインタの値がエラーコードの範囲(エラーポインタ)かどうかをチェックせずにアクセスしてしまうことにより、 NULL pointer dereference と似たような問題が発生します。

error_pointer_deref_test.c :エラーポインタを参照してしまうカーネルモジュールの例

#include <linux/module.h>

static int __init error_pointer_deref_test(void)
{
        struct mutex *mutex = ERR_PTR(-EINVAL);

        return atomic_long_read(&mutex->owner) == 0 ? 0 : -EINVAL;
}

module_init(error_pointer_deref_test);
MODULE_LICENSE("GPL");

エラーコードは -4095 以上 -1 以下の整数値として表現されるため、誤ってアクセスしてしまった際のアドレスが0番地の近くになるという性質があります。

[   55.173963] error_pointer_deref_test: loading out-of-tree module taints kernel.
[   55.179553] BUG: unable to handle kernel paging request at ffffffffffffffea
[   55.181608] #PF error: [normal kernel read fault]
[   55.182962] PGD 6741e067 P4D 6741e067 PUD 67420067 PMD 0 
[   55.184627] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI
[   55.186136] CPU: 1 PID: 9670 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   55.188475] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   55.191280] RIP: 0010:error_pointer_deref_test+0x54/0x1000 [error_pointer_deref_test]
[   55.193600] Code: 9e c1 84 d2 0f 95 c2 84 d1 75 0e 3c 01 0f 9e c2 84 c0 0f 95 c0 84 c2 74 11 be 08 00 00 00 48 c7 c7 ea ff ff ff e8 ec df 9c c9 <48> 8b 04 25 ea ff ff ff 48 83 f8 01 19 c0 f7 d0 83 e0 ea c3 00 00
[   55.198602] RSP: 0018:ffff88809a0ef950 EFLAGS: 00010246
[   55.200216] RAX: fffffbffffffff00 RBX: 0000000000000000 RCX: ffffffffc0c60001
[   55.202094] RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffffffffffffffea
[   55.204130] RBP: 1ffff1101341df2d R08: fffffbffffffffff R09: fffffbfffffffffd
[   55.206001] R10: fffffbfffffffffe R11: fffffffffffffff1 R12: ffffffffc0c60000
[   55.207999] R13: 0000000000000001 R14: ffffffffc0c51000 R15: ffffffff8ca65064
[   55.209868] FS:  00007f6bd00ec740(0000) GS:ffff8880a0200000(0000) knlGS:0000000000000000
[   55.212259] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   55.213787] CR2: ffffffffffffffea CR3: 000000009212c003 CR4: 00000000003606e0
[   55.215758] Call Trace:
[   55.216468]  do_one_initcall+0xe2/0x553
[   55.217439]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   55.219054]  ? kasan_unpoison_shadow+0x30/0x40
[   55.220302]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   55.221563]  ? do_init_module+0x49/0x680
[   55.222632]  ? kmem_cache_alloc_trace+0x14b/0x340
[   55.223965]  ? __kasan_slab_free+0x126/0x150
[   55.225051]  do_init_module+0x1da/0x680
[   55.226070]  load_module+0x43e8/0x56d0
[   55.227031]  ? layout_and_allocate+0x2140/0x2140
[   55.228197]  ? kernel_read+0x8b/0x130
[   55.229127]  ? kernel_read_file+0x225/0x4f0
[   55.230298]  ? __do_sys_finit_module+0x11a/0x1b0
[   55.231462]  __do_sys_finit_module+0x11a/0x1b0
[   55.232730]  ? __ia32_sys_init_module+0xa0/0xa0
[   55.234316]  ? __audit_syscall_exit+0x712/0x990
[   55.235463]  ? rcu_read_lock_sched_held+0x102/0x120
[   55.236695]  ? do_syscall_64+0x1d/0x450
[   55.237817]  do_syscall_64+0x9a/0x450
[   55.238753]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   55.240814] RIP: 0033:0x7f6bcf5bf1c9
[   55.243101] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   55.249848] RSP: 002b:00007ffd7d76c0f8 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
[   55.253404] RAX: ffffffffffffffda RBX: 0000000000ab91e0 RCX: 00007f6bcf5bf1c9
[   55.253405] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   55.253406] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffd7d76c298
[   55.253407] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
[   55.253408] R13: 0000000000ab8120 R14: 0000000000000000 R15: 0000000000000000
[   55.253413] Modules linked in: error_pointer_deref_test(O+) vmw_balloon pcspkr sg ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter vmw_vmci i2c_piix4 ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ata_generic pata_acpi vmwgfx drm_kms_helper syscopyarea ahci sysfillrect libahci sysimgblt fb_sys_fops e1000 ttm drm ata_piix mptspi i2c_core scsi_transport_spi libata mptscsih mptbase
[   55.253455] CR2: ffffffffffffffea
[   55.253457] ---[ end trace 02869cfd52ddc9e3 ]---
[   55.253465] RIP: 0010:error_pointer_deref_test+0x54/0x1000 [error_pointer_deref_test]
[   55.298049] Code: 9e c1 84 d2 0f 95 c2 84 d1 75 0e 3c 01 0f 9e c2 84 c0 0f 95 c0 84 c2 74 11 be 08 00 00 00 48 c7 c7 ea ff ff ff e8 ec df 9c c9 <48> 8b 04 25 ea ff ff ff 48 83 f8 01 19 c0 f7 d0 83 e0 ea c3 00 00
[   55.305172] RSP: 0018:ffff88809a0ef950 EFLAGS: 00010246
[   55.307630] RAX: fffffbffffffff00 RBX: 0000000000000000 RCX: ffffffffc0c60001
[   55.310497] RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffffffffffffffea
[   55.313354] RBP: 1ffff1101341df2d R08: fffffbffffffffff R09: fffffbfffffffffd
[   55.316399] R10: fffffbfffffffffe R11: fffffffffffffff1 R12: ffffffffc0c60000
[   55.319391] R13: 0000000000000001 R14: ffffffffc0c51000 R15: ffffffff8ca65064
[   55.322410] FS:  00007f6bd00ec740(0000) GS:ffff8880a0200000(0000) knlGS:0000000000000000
[   55.325384] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   55.327994] CR2: ffffffffffffffea CR3: 000000009212c003 CR4: 00000000003606e0
[   55.330942] BUG: sleeping function called from invalid context at include/linux/percpu-rwsem.h:34
[   55.334365] in_atomic(): 0, irqs_disabled(): 1, pid: 9670, name: insmod
[   55.337013] INFO: lockdep is turned off.
[   55.339256] irq event stamp: 4006
[   55.341108] hardirqs last  enabled at (4005): [<ffffffff8a62692d>] __slab_alloc+0x6d/0x90
[   55.344383] hardirqs last disabled at (4006): [<ffffffff8a00546c>] trace_hardirqs_off_thunk+0x1a/0x1c
[   55.347833] softirqs last  enabled at (3942): [<ffffffff8bc00675>] __do_softirq+0x675/0x9e3
[   55.351165] softirqs last disabled at (3935): [<ffffffff8a17fe64>] irq_exit+0x274/0x2c0
[   55.354428] CPU: 1 PID: 9670 Comm: insmod Kdump: loaded Tainted: G      D    O    T 5.0.0 #1
[   55.357689] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   55.361542] Call Trace:
[   55.363354]  dump_stack+0x9a/0xf0
[   55.365613]  ___might_sleep.cold.82+0x121/0x13b
[   55.367883]  exit_signals+0x70/0x620
[   55.370072]  ? get_signal+0x1930/0x1930
[   55.372134]  do_exit+0x1ef/0x2ad0
[   55.374370]  ? mm_update_next_owner+0x5c0/0x5c0
[   55.376595]  ? do_syscall_64+0x1d/0x450
[   55.379107]  rewind_stack_do_exit+0x17/0x20

ケース14:単純な random pointer dereference の例

NULL pointer dereference も error pointer dereference も厄介ですが、もっと厄介なのはアクセスしようとしたアドレスに規則性が無い random pointer dereference です。動的に割り当て/解放されるメモリ領域に関して、アクセスしたタイミングで解放済みであれば、 use-after-free として報告してもらえます。しかし、解放されたメモリ領域が再度割り当てられた後にアクセスしてしまった場合、 use-after-free としては報告してもらえません。再度割り当てられたメモリ領域に新しい値が書き込まれてしまうことにより、予想外のアドレスにアクセスしようとして、 random pointer dereference となります。この状況が発生した場合、競合状態に起因した不具合を疑う必要があります。

random_pointer_deref_test.c :ランダムなポインタを参照してしまうカーネルモジュールの例

#include <linux/module.h>
#include <linux/random.h>

static int __init random_pointer_deref_test(void)
{
        char *ptr = NULL;

        get_random_bytes(&ptr, sizeof(ptr));
        return *ptr == '\0' ? 0 : -EINVAL;
}

module_init(random_pointer_deref_test);
MODULE_LICENSE("GPL");

ソースコードを確認しても明らかな誤りが見つからない場合、どのような問題が発生しているのかを試行錯誤しながら調査していくことになります。

[   53.164214] random_pointer_deref_test: loading out-of-tree module taints kernel.
[   53.171322] kasan: CONFIG_KASAN_INLINE enabled
[   53.172626] kasan: GPF could be caused by NULL-ptr deref or user memory access
[   53.174652] general protection fault: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI
[   53.176673] CPU: 4 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   53.176674] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   53.176680] RIP: 0010:random_pointer_deref_test+0x7e/0x1000 [random_pointer_deref_test]
[   53.176682] Code: 00 00 00 48 89 44 24 58 31 c0 48 c7 44 24 20 00 00 00 00 e8 04 41 00 e4 48 8b 6c 24 20 48 89 e8 48 89 ea 48 c1 e8 03 83 e2 07 <42> 8a 04 20 38 d0 7f 0c 84 c0 74 08 48 89 ef e8 be de 84 e3 80 7d
[   53.176683] RSP: 0018:ffff8880928ff8d8 EFLAGS: 00010202
[   53.176685] RAX: 134e6fdbb4bc1cde RBX: 1ffff1101251ff1b RCX: 0000000000000000
[   53.176686] RDX: 0000000000000004 RSI: 0000000000000000 RDI: ffff8880928ff860
[   53.176687] RBP: 9a737edda5e0e6f4 R08: ffffed101251ff0c R09: 0000000000000000
[   53.176688] R10: ffff8880928ff820 R11: ffff8880928ff85f R12: dffffc0000000000
[   53.176689] R13: 0000000000000004 R14: ffffffffc0dd1000 R15: ffffffffa6a65064
[   53.176691] FS:  00007f8968aa5740(0000) GS:ffff8880a0e00000(0000) knlGS:0000000000000000
[   53.176692] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   53.176693] CR2: 00000000012f31d8 CR3: 0000000093982005 CR4: 00000000003606e0
[   53.176717] Call Trace:
[   53.176721]  ? 0xffffffffc0de0000
[   53.176725]  ? 0xffffffffc0de0000
[   53.176728]  do_one_initcall+0xe2/0x553
[   53.176731]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   53.176734]  ? kasan_unpoison_shadow+0x30/0x40
[   53.176736]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   53.176739]  ? do_init_module+0x49/0x680
[   53.213145]  ? kmem_cache_alloc_trace+0x14b/0x340
[   53.213148]  ? __kasan_slab_free+0x126/0x150
[   53.213153]  do_init_module+0x1da/0x680
[   53.213157]  load_module+0x43e8/0x56d0
[   53.213168]  ? layout_and_allocate+0x2140/0x2140
[   53.213172]  ? kernel_read+0x8b/0x130
[   53.213174]  ? kernel_read_file+0x225/0x4f0
[   53.213182]  ? __do_sys_finit_module+0x11a/0x1b0
[   53.213183]  __do_sys_finit_module+0x11a/0x1b0
[   53.213185]  ? __ia32_sys_init_module+0xa0/0xa0
[   53.213189]  ? __audit_syscall_exit+0x712/0x990
[   53.213193]  ? rcu_read_lock_sched_held+0x102/0x120
[   53.226619]  ? do_syscall_64+0x1d/0x450
[   53.226622]  do_syscall_64+0x9a/0x450
[   53.226626]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   53.226629] RIP: 0033:0x7f8967f781c9
[   53.226631] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   53.226632] RSP: 002b:00007ffe5eaffe98 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
[   53.226634] RAX: ffffffffffffffda RBX: 00000000012f31e0 RCX: 00007f8967f781c9
[   53.226635] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   53.226636] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffe5eb00038
[   53.226637] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
[   53.226638] R13: 00000000012f2120 R14: 0000000000000000 R15: 0000000000000000
[   53.226642] Modules linked in: random_pointer_deref_test(O+) vmw_balloon pcspkr sg vmw_vmci i2c_piix4 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables xfs libcrc32c sd_mod sr_mod cdrom serio_raw ata_generic pata_acpi vmwgfx drm_kms_helper ahci syscopyarea e1000 sysfillrect libahci mptspi sysimgblt fb_sys_fops scsi_transport_spi ata_piix ttm mptscsih drm libata mptbase i2c_core
[   53.277566] ---[ end trace 887d28b67e86ae48 ]---
[   53.277577] RIP: 0010:random_pointer_deref_test+0x7e/0x1000 [random_pointer_deref_test]
[   53.284413] Code: 00 00 00 48 89 44 24 58 31 c0 48 c7 44 24 20 00 00 00 00 e8 04 41 00 e4 48 8b 6c 24 20 48 89 e8 48 89 ea 48 c1 e8 03 83 e2 07 <42> 8a 04 20 38 d0 7f 0c 84 c0 74 08 48 89 ef e8 be de 84 e3 80 7d
[   53.284415] RSP: 0018:ffff8880928ff8d8 EFLAGS: 00010202
[   53.284417] RAX: 134e6fdbb4bc1cde RBX: 1ffff1101251ff1b RCX: 0000000000000000
[   53.284418] RDX: 0000000000000004 RSI: 0000000000000000 RDI: ffff8880928ff860
[   53.284419] RBP: 9a737edda5e0e6f4 R08: ffffed101251ff0c R09: 0000000000000000
[   53.284420] R10: ffff8880928ff820 R11: ffff8880928ff85f R12: dffffc0000000000
[   53.284421] R13: 0000000000000004 R14: ffffffffc0dd1000 R15: ffffffffa6a65064
[   53.284423] FS:  00007f8968aa5740(0000) GS:ffff8880a0e00000(0000) knlGS:0000000000000000
[   53.284424] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   53.284425] CR2: 00000000012f31d8 CR3: 0000000093982005 CR4: 00000000003606e0

第2章 カーネルメッセージを読めるようにするための試行錯誤について


第1章では、 Linux カーネルのデバッグ支援機能が出力するメッセージの例について紹介しました。これらのメッセージを出力するために、カーネルには printk() という関数が存在しています。

printk() は、ユーザランドで動作するプログラムにおける printf() に相当する関数です。 /sys/module/printk/parameters/time に Y が設定されている場合、 printk() はコンソールに出力するメッセージの先頭に「システムが起動してからの経過時間」という情報を追加します。つまり、「いつ」「どんな発言をしたか」を記録して出力することができます。例えば、クラッシュが発生する数秒前のメッセージと数年前のメッセージとが存在する場合、前者は問題に関連している可能性が高く、後者は問題に関連している可能性が低いと考えることができます。そのため、「いつ」という情報は、問題との関連性の有無を判断する上で重要な手がかりとなります。

printk.png

ファジングテストでは普段行われないような動作を繰り返したり、普段指定しないような値を意図的に指定したりするので、大量のメッセージが出力されます。そして、問題が発生したかどうかを判定するためには、問題に関連したメッセージを確実に抽出できることが重要になります。実際に syzbot によるファジングテストが出力したメッセージのサンプルを見てみましょう。

[   42.160082] WARNING: CPU: 1 PID: 6327 at net/core/stream.c:206 sk_stream_kill_queues+0x3e7/0x540
[   42.160099] WARNING: CPU: 0 PID: 6328 at net/core/stream.c:206 sk_stream_kill_queues+0x3e7/0x540
[   42.160119] Kernel panic - not syncing: panic_on_warn set ...
[   42.160119]
[   42.169122] Modules linked in:
[   42.178088] CPU: 0 PID: 6328 Comm: syz-executor635 Not tainted 4.18.0-rc7+ #36
[   42.188592] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[   42.195938] CPU: 1 PID: 6327 Comm: syz-executor635 Not tainted 4.18.0-rc7+ #36
[   42.205274] Call Trace:
[   42.212612] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[   42.215183]  dump_stack+0x1c9/0x2b4
[   42.224522] RIP: 0010:sk_stream_kill_queues+0x3e7/0x540
[   42.228137]  ? dump_stack_print_info.cold.2+0x52/0x52
[   42.233473] Code: 48 c1 ea
[   42.238662]  panic+0x238/0x4e7
[   42.238679]  ? add_taint.cold.5+0x16/0x16
[   42.241578] 03 0f
[   42.244767]  ? __warn.cold.8+0x148/0x1ba
[   42.248878] b6 04
[   42.251023]  ? __warn.cold.8+0x117/0x1ba
[   42.255060] 02
[   42.257202]  ? sk_stream_kill_queues+0x3e7/0x540
[   42.261230] 84
[   42.263116]  __warn.cold.8+0x163/0x1ba
[   42.267841] c0
[   42.269718]  ? sk_stream_kill_queues+0x3e7/0x540
[   42.273569] 74 04
[   42.275455]  report_bug+0x252/0x2d0
[   42.280193] 3c
[   42.282323]  do_error_trap+0x1fc/0x4d0
[   42.285939] 03
[   42.287814]  ? math_error+0x3e0/0x3e0
[   42.291672] 7e
[   42.293556]  ? __sanitizer_cov_trace_cmp8+0x18/0x20
[   42.297338] 41
[   42.299218]  ? percpu_counter_add_batch+0xf2/0x150
[   42.304205] 44
[   42.306086]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[   42.310981] 8b
[   42.312857]  do_invalid_op+0x1b/0x20
[   42.317843] a3
[   42.319723]  invalid_op+0x14/0x20
[   42.323402] f0 01
[   42.325287] RIP: 0010:sk_stream_kill_queues+0x3e7/0x540
[   42.328709] 00
[   42.330838] Code:
[   42.336174] 00 e9
[   42.338048] 48
[   42.340177] 5f
[   42.342303] c1
[   42.344167] ff ff
[   42.346041] ea
[   42.347904] ff e8
[   42.350037] 03
[   42.351897] 72 01
[   42.354031] 0f
[   42.355897] 71
[   42.358024] b6
[   42.359894] fc
[   42.361763] 04
[   42.363624] 0f 0b
[   42.365505] 02
[   42.367381] eb
[   42.369524] 84
[   42.371392] 96
[   42.373259] c0
[   42.375147] e8
[   42.377031] 74
[   42.378898] 69
[   42.380770] 04 3c
[   42.382640] 01 71
[   42.384514] 03
[   42.386641] fc
[   42.388767] 7e 41
[   42.390639] <0f>
[   42.392505] 44
[   42.394633] 0b
[   42.396670] 8b a3
[   42.398540] eb a1
[   42.400422] f0
[   42.402547] e8
[   42.404670] 01 00
[   42.406546] 60
[   42.408413] 00
[   42.410541] 01
[   42.412402] e9 5f
[   42.414277] 71
[   42.416144] ff
[   42.418282] fc
[   42.420149] ff
[   42.422017] 0f
[   42.423891] ff
[   42.425759] 0b
[   42.427623] e8 72
[   42.429497] e9
[   42.431362] 01 71
[   42.433498] 9f
[   42.435365] fc
[   42.437500] fe
[   42.439366] 0f
[   42.441232] ff
[   42.443098] 0b
[   42.444964] ff
[   42.446825] eb 96
[   42.448698] 4c
[   42.450558] e8 69
[   42.452696] 89
[   42.454558] 01 71
[   42.456715] ef
[   42.458585] fc <0f>
[   42.460720] e8
[   42.462589] 0b
[   42.464885] 51 de
[   42.466766] eb a1
[   42.470773] e8 60
[   42.472907] RSP: 0018:ffff8801c829f638 EFLAGS: 00010293
[   42.472915] 01
[   42.480481] 71 fc
[   42.482358] RAX: ffff8801c6b0e000 RBX: 0000000000000000 RCX: ffffffff850b15d7
[   42.482366] 0f
[   42.484501] RDX: 0000000000000000 RSI: ffffffff850b1637 RDI: 0000000000000005
[   42.491743] 0b e9
[   42.493625] RBP: ffff8801c829f678 R08: ffff8801c6b0e000 R09: ffffed003b6246d6
[   42.500866] 9f fe
[   42.503006] R10: ffffed003b6246d6 R11: ffff8801db1236b3 R12: 0000000000000fe3
[   42.510246] ff ff
[   42.512406] R13: ffff8801aecd0230 R14: ffffffff8a349b40 R15: 0000000000000007
[   42.519666] 4c 89
[   42.521817] FS:  00007f2308e75700(0000) GS:ffff8801db100000(0000) knlGS:0000000000000000
[   42.529060] ef
[   42.531197] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   42.531208] CR2: 000000000063f210 CR3: 00000001ae3b6000 CR4: 00000000001406e0
[   42.539505] e8
[   42.541382] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   42.547240] 51
[   42.554495] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   42.556358] de
[   42.563607] Call Trace:
[   42.572752]  inet_csk_destroy_sock+0x1a7/0x440
[   42.574605] RSP: 0018:ffff8801c68a7638 EFLAGS: 00010293
[   42.577175]  tcp_close+0xb89/0x12d0
[   42.587083]  ? tcp_check_oom+0x530/0x530
[   42.590693] RAX: ffff8801ba3aa300 RBX: 0000000000000000 RCX: ffffffff850b15d7
[   42.594743]  ? down_write+0x8f/0x130
[   42.601989] RDX: 0000000000000000 RSI: ffffffff850b1637 RDI: 0000000000000005
[   42.605691]  ? ip_mc_drop_socket+0x20f/0x270
[   42.612948] RBP: ffff8801c68a7678 R08: ffff8801ba3aa300 R09: ffffed003b6046d6
[   42.617342]  ? down_read+0x1d0/0x1d0
[   42.624586] R10: ffffed003b6046d6 R11: ffff8801db0236b3 R12: 0000000000000fe3
[   42.628281]  inet_release+0x104/0x1f0
[   42.635530] R13: ffff8801c4842e30 R14: ffffffff8a349b40 R15: 0000000000000007
[   42.635552]  ? sk_stream_kill_queues+0x387/0x540
[   42.639331]  __sock_release+0xd7/0x260
[   42.646579]  ? sk_stream_kill_queues+0x3e7/0x540
[   42.651324]  ? __sock_release+0x260/0x260
[   42.655190]  ? sk_stream_kill_queues+0x3e7/0x540
[   42.659924]  sock_close+0x19/0x20
[   42.664055]  inet_csk_destroy_sock+0x1a7/0x440
[   42.668787]  __fput+0x355/0x8b0
[   42.672220]  tcp_close+0xb89/0x12d0
[   42.676790]  ? fput+0x1a0/0x1a0
[   42.680049]  ? tcp_check_oom+0x530/0x530
[   42.683657]  ? _raw_spin_unlock_irq+0x27/0x70
[   42.686920]  ? down_write+0x8f/0x130
[   42.690964]  ____fput+0x15/0x20
[   42.695438]  ? ip_mc_drop_socket+0x20f/0x270
[   42.699134]  task_work_run+0x1ec/0x2a0
[   42.702399]  ? down_read+0x1d0/0x1d0
[   42.706794]  ? task_work_cancel+0x250/0x250
[   42.710662]  inet_release+0x104/0x1f0
[   42.714366]  ? kasan_check_read+0x11/0x20
[   42.718674]  __sock_release+0xd7/0x260
[   42.722448]  get_signal+0x1559/0x1970
[   42.726576]  ? __sock_release+0x260/0x260
[   42.730455]  ? ptrace_notify+0x130/0x130
[   42.734233]  sock_close+0x19/0x20
[   42.738371]  ? expand_files.part.8+0x9c0/0x9c0
[   42.742409]  __fput+0x355/0x8b0
[   42.745844]  ? __local_bh_enable_ip+0x161/0x230
[   42.750404]  ? fput+0x1a0/0x1a0
[   42.753662]  ? trace_hardirqs_on_caller+0x421/0x5c0
[   42.758329]  ? _raw_spin_unlock_irq+0x27/0x70
[   42.761591]  ? trace_hardirqs_on+0xd/0x10
[   42.766587]  ____fput+0x15/0x20
[   42.771065]  do_signal+0x9c/0x21c0
[   42.775191]  task_work_run+0x1ec/0x2a0
[   42.778449]  ? __fget_light+0x2f7/0x440
[   42.781970]  ? task_work_cancel+0x250/0x250
[   42.785835]  ? fget_raw+0x20/0x20
[   42.789791]  ? kasan_check_read+0x11/0x20
[   42.794099]  ? __local_bh_enable_ip+0x161/0x230
[   42.797531]  get_signal+0x1559/0x1970
[   42.801661]  ? setup_sigcontext+0x7d0/0x7d0
[   42.806314]  ? ptrace_notify+0x130/0x130
[   42.810091]  ? task_work_add+0x123/0x1f0
[   42.814392]  ? expand_files.part.8+0x9c0/0x9c0
[   42.818443]  ? cpumask_weight.constprop.5+0x3f/0x3f
[   42.822483]  ? __local_bh_enable_ip+0x161/0x230
[   42.827044]  ? tcp_setsockopt+0x9a/0xe0
[   42.832149]  ? trace_hardirqs_on_caller+0x421/0x5c0
[   42.836809]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[   42.840771]  ? trace_hardirqs_on+0xd/0x10
[   42.845766]  ? fput+0x130/0x1a0
[   42.851634]  do_signal+0x9c/0x21c0
[   42.855766]  ? __sys_setsockopt+0x257/0x3b0
[   42.859023]  ? __fget_light+0x2f7/0x440
[   42.862544]  ? exit_to_usermode_loop+0x8c/0x370
[   42.866841]  ? fget_raw+0x20/0x20
[   42.870809]  exit_to_usermode_loop+0x2e0/0x370
[   42.875456]  ? __local_bh_enable_ip+0x161/0x230
[   42.878888]  ? syscall_slow_exit_work+0x500/0x500
[   42.883629]  ? setup_sigcontext+0x7d0/0x7d0
[   42.888288]  do_syscall_64+0x6be/0x820
[   42.893109]  ? task_work_add+0x123/0x1f0
[   42.897417]  ? finish_task_switch+0x1d3/0x870
[   42.901286]  ? cpumask_weight.constprop.5+0x3f/0x3f
[   42.905327]  ? syscall_return_slowpath+0x5e0/0x5e0
[   42.909799]  ? tcp_setsockopt+0x9a/0xe0
[   42.914805]  ? syscall_return_slowpath+0x31d/0x5e0
[   42.919717]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[   42.923678]  ? entry_SYSCALL_64_after_hwframe+0x59/0xbe
[   42.928673]  ? fput+0x130/0x1a0
[   42.934193]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[   42.939535]  ? __sys_setsockopt+0x257/0x3b0
[   42.942795]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   42.947618]  ? exit_to_usermode_loop+0x8c/0x370
[   42.952002] RIP: 0033:0x446d69
[   42.957174]  exit_to_usermode_loop+0x2e0/0x370
[   42.961808] Code: e8
[   42.964999]  ? syscall_slow_exit_work+0x500/0x500
[   42.970080] 4c
[   42.972588]  do_syscall_64+0x6be/0x820
[   42.977381] e7 ff
[   42.979266]  ? finish_task_switch+0x1d3/0x870
[   42.983116] ff 48
[   42.985268]  ? syscall_return_slowpath+0x5e0/0x5e0
[   42.989725] 83 c4
[   42.991871]  ? syscall_return_slowpath+0x31d/0x5e0
[   42.996764] 18 c3
[   42.998911]  ? entry_SYSCALL_64_after_hwframe+0x59/0xbe
[   43.003803] 0f 1f
[   43.005952]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[   43.011279] 80 00
[   43.013425]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   43.018235] 00
[   43.020547] RIP: 0033:0x446d69
[   43.025713] 00
[   43.027580] Code:
[   43.030747] 00 48
[   43.032621] e8
[   43.034754] 89 f8
[   43.036892] 4c
[   43.038759] 48
[   43.040890] e7
[   43.042758] 89
[   43.044624] ff
[   43.046491] f7
[   43.048358] ff
[   43.050223] 48
[   43.052097] 48
[   43.053963] 89
[   43.055830] 83
[   43.057697] d6
[   43.059567] c4
[   43.061444] 48 89
[   43.063324] 18
[   43.065187] ca 4d
[   43.067324] c3 0f
[   43.069198] 89
[   43.071321] 1f 80
[   43.073457] c2
[   43.075324] 00
[   43.077451] 4d
[   43.079326] 00
[   43.081191] 89
[   43.083063] 00 00
[   43.084934] c8 4c
[   43.086810] 48
[   43.088945] 8b
[   43.091087] 89 f8
[   43.092964] 4c
[   43.094826] 48 89
[   43.096962] 24
[   43.098829] f7 48
[   43.100964] 08
[   43.102831] 89
[   43.104952] 0f 05
[   43.106835] d6
[   43.108702] <48>
[   43.110911] 48 89
[   43.112787] 3d
[   43.114830] ca
[   43.116952] 01 f0
[   43.118827] 4d
[   43.120689] ff ff
[   43.122819] 89 c2
[   43.124702] 0f
[   43.126828] 4d
[   43.128951] 83 3b
[   43.130829] 89 c8
[   43.132704] 08
[   43.134834] 4c
[   43.136975] fc ff
[   43.138859] 8b
[   43.140728] c3
[   43.142849] 4c 24
[   43.144725] 66
[   43.146591] 08
[   43.148726] 2e
[   43.150596] 0f 05
[   43.152469] 0f
[   43.154336] <48>
[   43.156462] 1f
[   43.158325] 3d 01
[   43.160368] 84 00
[   43.162250] f0
[   43.164373] 00 00
[   43.166509] ff
[   43.168378] 00
[   43.170517] ff
[   43.174264] 0f 83
[   43.176140] RSP: 002b:00007f2308e74da8 EFLAGS: 00000293
[   43.176148] 3b
[   43.178275]  ORIG_RAX: 0000000000000036
[   43.183618] 08 fc
[   43.185500] RAX: 0000000000000000 RBX: 00000000006dcc58 RCX: 0000000000446d69
[   43.189446] ff
[   43.191586] RDX: 0000000000000001 RSI: 0000000000000029 RDI: 0000000000000005
[   43.198836] c3
[   43.200710] RBP: 00000000006dcc50 R08: 0000000000000004 R09: 0000000000000000
[   43.207956] 66
[   43.209837] R10: 0000000020000240 R11: 0000000000000293 R12: 00000000006dcc5c
[   43.217092] 2e
[   43.218976] R13: d5979ab4093c3ebb R14: 0100000000000000 R15: 0000000000000005
[   43.226230] 0f
[   43.228109] irq event stamp: 411
[   43.235345] 1f 84
[   43.237245] hardirqs last  enabled at (410): [<ffffffff8166f883>] __call_rcu.constprop.67+0x3b3/0xc00
[   43.240575] 00
[   43.242712] hardirqs last disabled at (411): [<ffffffff86c01166>] error_entry+0x76/0xd0
[   43.242730] softirqs last  enabled at (382): [<ffffffff8506c9cc>] release_sock+0x1ec/0x2c0
[   43.252051] 00 00
[   43.253936] softirqs last disabled at (384): [<ffffffff857e0af5>] tcp_close+0x6f5/0x12d0
[   43.253945] ---[ end trace bf7027becfd3b093 ]---
[   43.262058] 00
[   43.270914] WARNING: CPU: 1 PID: 6327 at net/ipv4/af_inet.c:156 inet_sock_destruct+0x796/0x9c0
[   43.272784] RSP: 002b:00007f2308e74da8 EFLAGS: 00000293 ORIG_RAX: 0000000000000036
[   43.272802] RAX: 0000000000000000 RBX: 00000000006dcc58 RCX: 0000000000446d69
[   43.281051] Modules linked in:
[   43.285794] RDX: 0000000000000001 RSI: 0000000000000029 RDI: 0000000000000005
[   43.285805] RBP: 00000000006dcc50 R08: 0000000000000004 R09: 0000000000000000
[   43.287683] CPU: 1 PID: 6327 Comm: syz-executor635 Tainted: G        W         4.18.0-rc7+ #36
[   43.296414] R10: 0000000020000240 R11: 0000000000000293 R12: 00000000006dcc5c
[   43.304095] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[   43.304114] RIP: 0010:inet_sock_destruct+0x796/0x9c0
[   43.311354] R13: d5979ab4093c3ebb R14: 0100000000000000 R15: 0000000000000005
[   43.366683] Code: fb 41 80 ff 07 0f 84 78 fc ff ff e9 95 97 00 00 e8 1f 03 ef fb 44 89 f6 48 89 df e8 c4 a6 79 ff e9 11 fc ff ff e8 0a 03 ef fb <0f> 0b e9 62 fe ff ff e8 fe 02 ef fb 0f 0b e9 c8 fd ff ff e8 f2 02
[   43.385930] RSP: 0018:ffff8801c829f2d8 EFLAGS: 00010293
[   43.391282] RAX: ffff8801c6b0e000 RBX: ffff8801aecd0040 RCX: ffffffff858d12f6
[   43.398541] RDX: 0000000000000000 RSI: ffffffff858d1496 RDI: 0000000000000005
[   43.405798] RBP: ffff8801c829f408 R08: ffff8801c6b0e000 R09: ffffed0035d9a04f
[   43.413053] R10: ffffed0035d9a04f R11: ffff8801aecd027f R12: ffff8801aecd0178
[   43.420321] R13: ffff8801c829f3e0 R14: 0000000000000fe3 R15: 0000000000000000
[   43.427589] FS:  00007f2308e75700(0000) GS:ffff8801db100000(0000) knlGS:0000000000000000
[   43.435811] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   43.441678] CR2: 000000000063f210 CR3: 00000001ae3b6000 CR4: 00000000001406e0
[   43.448938] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   43.456193] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   43.463445] Call Trace:
[   43.466021]  ? printk+0xa7/0xcf
[   43.469290]  ? kmsg_dump_rewind_nolock+0xe4/0xe4
[   43.474053]  ? ipv4_mib_init_net+0x580/0x580
[   43.478452]  ? print_oops_end_marker+0x1b/0x60
[   43.483022]  ? graph_lock+0x170/0x170
[   43.486811]  ? add_taint+0x29/0x60
[   43.490352]  ? print_usage_bug+0xc0/0xc0
[   43.494400]  ? sk_stream_kill_queues+0x3e7/0x540
[   43.499144]  ? ipv4_mib_init_net+0x580/0x580
[   43.503541]  __sk_destruct+0x107/0xa60
[   43.507418]  ? sock_warn_obsolete_bsdism+0xb0/0xb0
[   43.512353]  ? lock_downgrade+0x8f0/0x8f0
[   43.516493]  ? kasan_check_read+0x11/0x20
[   43.520627]  ? rcu_is_watching+0x8c/0x150
[   43.524763]  ? rcu_report_qs_rnp+0x7a0/0x7a0
[   43.529254]  ? netlink_has_listeners+0x2da/0x4c0
[   43.533998]  ? netlink_tap_init_net+0x3e0/0x3e0
[   43.538654]  ? mark_held_locks+0xc9/0x160
[   43.542794]  sk_destruct+0x78/0x90
[   43.546321]  __sk_free+0xcf/0x300
[   43.549765]  sk_free+0x42/0x50
[   43.552949]  tcp_close+0xd1e/0x12d0
[   43.556567]  ? tcp_check_oom+0x530/0x530
[   43.560623]  ? down_write+0x8f/0x130
[   43.564333]  ? ip_mc_drop_socket+0x20f/0x270
[   43.568731]  ? down_read+0x1d0/0x1d0
[   43.572434]  inet_release+0x104/0x1f0
[   43.576241]  __sock_release+0xd7/0x260
[   43.580120]  ? __sock_release+0x260/0x260
[   43.584256]  sock_close+0x19/0x20
[   43.587698]  __fput+0x355/0x8b0
[   43.590970]  ? fput+0x1a0/0x1a0
[   43.594239]  ? _raw_spin_unlock_irq+0x27/0x70
[   43.598725]  ____fput+0x15/0x20
[   43.602005]  task_work_run+0x1ec/0x2a0
[   43.605890]  ? task_work_cancel+0x250/0x250
[   43.610212]  ? kasan_check_read+0x11/0x20
[   43.614611]  get_signal+0x1559/0x1970
[   43.618498]  ? ptrace_notify+0x130/0x130
[   43.622549]  ? expand_files.part.8+0x9c0/0x9c0
[   43.627128]  ? __local_bh_enable_ip+0x161/0x230
[   43.631872]  ? trace_hardirqs_on_caller+0x421/0x5c0
[   43.636879]  ? trace_hardirqs_on+0xd/0x10
[   43.641021]  do_signal+0x9c/0x21c0
[   43.644549]  ? __fget_light+0x2f7/0x440
[   43.648511]  ? fget_raw+0x20/0x20
[   43.651953]  ? __local_bh_enable_ip+0x161/0x230
[   43.656613]  ? setup_sigcontext+0x7d0/0x7d0
[   43.660926]  ? task_work_add+0x123/0x1f0
[   43.664990]  ? cpumask_weight.constprop.5+0x3f/0x3f
[   43.669994]  ? tcp_setsockopt+0x9a/0xe0
[   43.673958]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[   43.679481]  ? fput+0x130/0x1a0
[   43.682751]  ? __sys_setsockopt+0x257/0x3b0
[   43.687147]  ? exit_to_usermode_loop+0x8c/0x370
[   43.691809]  exit_to_usermode_loop+0x2e0/0x370
[   43.696382]  ? syscall_slow_exit_work+0x500/0x500
[   43.701218]  do_syscall_64+0x6be/0x820
[   43.705096]  ? finish_task_switch+0x1d3/0x870
[   43.709583]  ? syscall_return_slowpath+0x5e0/0x5e0
[   43.714507]  ? syscall_return_slowpath+0x31d/0x5e0
[   43.719429]  ? entry_SYSCALL_64_after_hwframe+0x59/0xbe
[   43.724790]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[   43.729626]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   43.734806] RIP: 0033:0x446d69
[   43.737978] Code: e8 4c e7 ff ff 48 83 c4 18 c3 0f 1f 80 00 00 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 3b 08 fc ff c3 66 2e 0f 1f 84 00 00 00 00
[   43.757244] RSP: 002b:00007f2308e74da8 EFLAGS: 00000293 ORIG_RAX: 0000000000000036
[   43.764942] RAX: 0000000000000000 RBX: 00000000006dcc58 RCX: 0000000000446d69
[   43.772209] RDX: 0000000000000001 RSI: 0000000000000029 RDI: 0000000000000005
[   43.779464] RBP: 00000000006dcc50 R08: 0000000000000004 R09: 0000000000000000
[   43.786824] R10: 0000000020000240 R11: 0000000000000293 R12: 00000000006dcc5c
[   43.794104] R13: d5979ab4093c3ebb R14: 0100000000000000 R15: 0000000000000005
[   43.801372] irq event stamp: 418
[   43.804731] hardirqs last  enabled at (417): [<ffffffff814904a1>] __local_bh_enable_ip+0x161/0x230
[   43.813814] hardirqs last disabled at (418): [<ffffffff86c01166>] error_entry+0x76/0xd0
[   43.821945] softirqs last  enabled at (416): [<ffffffff857e0eb0>] tcp_close+0xab0/0x12d0
[   43.830159] softirqs last disabled at (384): [<ffffffff857e0af5>] tcp_close+0x6f5/0x12d0
[   43.838370] ---[ end trace bf7027becfd3b094 ]---
[   43.843550] Dumping ftrace buffer:
[   43.847257]    (ftrace buffer empty)
[   43.850948] Kernel Offset: disabled
[   43.854559] Rebooting in 86400 seconds..
[  304.835370] CPU: 1 PID: 10946 Comm: syz-executor1 Not tainted 4.19.0-rc8+ #67
[  304.835439] ICMPv6: ndisc: ndisc_alloc_skb failed to allocate an skb
[  304.842644] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[  304.842649] Call Trace:
[  304.842656]  <IRQ>
[  304.842675]  dump_stack+0x1c4/0x2b6
[  304.842694]  ? dump_stack_print_info.cold.1+0x20/0x20
[  304.849222] syz-executor1: page allocation failure: order:0, mode:0x484020(GFP_ATOMIC|__GFP_COMP), nodemask=(null)
[  304.858531]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  304.861093] syz-executor1 cpuset=
[  304.863239]  warn_alloc.cold.119+0xb7/0x1bd
[  304.866836] syz1
[  304.872016]  ? zone_watermark_ok_safe+0x3f0/0x3f0
[  304.882482]  mems_allowed=0
[  304.888030]  ? lock_downgrade+0x900/0x900
[  304.909619]  ? trace_hardirqs_off+0xb8/0x310
[  304.914043]  ? trace_hardirqs_off+0xb8/0x310
[  304.918463]  __alloc_pages_slowpath+0x265e/0x2d70
[  304.923348]  ? warn_alloc+0x120/0x120
[  304.927149]  ? trace_hardirqs_on+0x310/0x310
[  304.931561]  ? warn_alloc+0x120/0x120
[  304.935365]  ? print_usage_bug+0xc0/0xc0
[  304.939424]  ? warn_alloc+0x120/0x120
[  304.943274]  ? ktime_get+0x2e1/0x440
[  304.946986]  ? print_usage_bug+0xc0/0xc0
[  304.951055]  ? __lock_acquire+0x7ec/0x4ec0
[  304.955291]  ? __lock_acquire+0x7ec/0x4ec0
[  304.959528]  ? kasan_check_read+0x11/0x20
[  304.963676]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[  304.969212]  ? should_fail+0x22d/0xd01
[  304.973098]  ? rcu_bh_qs+0xc0/0xc0
[  304.976640]  ? fault_create_debugfs_attr+0x1f0/0x1f0
[  304.981748]  ? __lock_acquire+0x7ec/0x4ec0
[  304.985987]  ? fault_create_debugfs_attr+0x1f0/0x1f0
[  304.991092]  ? __lock_acquire+0x7ec/0x4ec0
[  304.995324]  ? should_fail+0x22d/0xd01
[  304.999215]  ? rcu_idle_enter+0x4b0/0x4b0
[  305.003378]  ? mark_held_locks+0x130/0x130
[  305.007639]  ? mark_held_locks+0x130/0x130
[  305.011879]  ? mark_held_locks+0xc7/0x130
[  305.016031]  ? smp_apic_timer_interrupt+0x1cb/0x760
[  305.021052]  ? graph_lock+0x170/0x170
[  305.024850]  ? print_usage_bug+0xc0/0xc0
[  305.028915]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.034457]  ? check_preemption_disabled+0x48/0x280
[  305.039484]  ? check_preemption_disabled+0x48/0x280
[  305.044526]  ? __lock_is_held+0xb5/0x140
[  305.048598]  __alloc_pages_nodemask+0xa80/0xde0
[  305.053267]  ? graph_lock+0x170/0x170
[  305.057074]  ? __alloc_pages_slowpath+0x2d70/0x2d70
[  305.062090]  ? graph_lock+0x170/0x170
[  305.065900]  ? find_held_lock+0x36/0x1c0
[  305.069976]  ? ____cache_alloc_node+0x1c7/0x1e0
[  305.074656]  ? lock_downgrade+0x900/0x900
[  305.078811]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.084355]  cache_grow_begin+0x91/0x8c0
[  305.088419]  ? do_raw_spin_unlock+0xa7/0x330
[  305.092838]  fallback_alloc+0x203/0x2e0
[  305.096818]  ____cache_alloc_node+0x1c7/0x1e0
[  305.101318]  kmem_cache_alloc_node+0xe3/0x730
[  305.105813]  ? ipv6_get_ifaddr+0x42e/0x620
[  305.110059]  __alloc_skb+0x119/0x770
[  305.113776]  ? rcu_dynticks_curr_cpu_in_eqs+0x9f/0x160
[  305.119071]  ? skb_scrub_packet+0x490/0x490
[  305.123396]  ? lock_downgrade+0x900/0x900
[  305.127761]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.133300]  ? refcount_sub_and_test_checked+0x203/0x310
[  305.138754]  ? refcount_inc_not_zero_checked+0x2f0/0x2f0
[  305.144205]  ? addrconf_rs_timer+0x690/0x690
[  305.148629]  ndisc_alloc_skb+0x144/0x340
[  305.152697]  ndisc_send_rs+0x331/0x6e0
[  305.156595]  addrconf_rs_timer+0x314/0x690
[  305.160838]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  305.165089]  call_timer_fn+0x272/0x920
[  305.168975]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  305.173210]  ? process_timeout+0x40/0x40
[  305.177273]  ? find_held_lock+0x36/0x1c0
[  305.181344]  ? __run_timers+0x7da/0xc70
[  305.185324]  ? _raw_spin_unlock_irq+0x27/0x80
[  305.189818]  ? _raw_spin_unlock_irq+0x27/0x80
[  305.194311]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  305.198565]  ? lockdep_hardirqs_on+0x19e/0x5c0
[  305.203154]  ? trace_hardirqs_on+0xbd/0x310
[  305.207513]  ? kasan_check_read+0x11/0x20
[  305.211663]  ? __run_timers+0x7da/0xc70
[  305.215652]  ? __bpf_trace_preemptirq_template+0x30/0x30
[  305.221115]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  305.225358]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  305.229593]  __run_timers+0x7e5/0xc70
[  305.233410]  ? __bpf_trace_timer_expire_entry+0x30/0x30
[  305.238775]  ? __sanitizer_cov_trace_cmp8+0x18/0x20
[  305.243791]  ? graph_lock+0x170/0x170
[  305.247599]  ? enqueue_hrtimer+0x1a5/0x560
[  305.251829]  ? lock_release+0x970/0x970
[  305.255802]  ? hrtimer_update_softirq_timer+0xa0/0xa0
[  305.260997]  ? find_held_lock+0x36/0x1c0
[  305.265063]  ? graph_lock+0x170/0x170
[  305.268865]  ? pvclock_read_flags+0x160/0x160
[  305.273359]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.278896]  ? check_preemption_disabled+0x48/0x280
[  305.283922]  ? __lock_is_held+0xb5/0x140
[  305.287985]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.293526]  ? check_preemption_disabled+0x48/0x280
[  305.298551]  run_timer_softirq+0x52/0xb0
[  305.302617]  ? rcu_read_lock_sched_held+0x108/0x120
[  305.307637]  __do_softirq+0x30c/0xb03
[  305.311450]  ? __irqentry_text_end+0x1f9618/0x1f9618
[  305.316562]  ? pvclock_read_flags+0x160/0x160
[  305.321057]  ? lapic_next_event+0x5a/0x90
[  305.325209]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.330747]  ? check_preemption_disabled+0x48/0x280
[  305.335763]  ? check_preemption_disabled+0x48/0x280
[  305.340791]  ? kvm_clock_read+0x18/0x30
[  305.344766]  ? kvm_sched_clock_read+0x9/0x20
[  305.349176]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.354717]  ? check_preemption_disabled+0x48/0x280
[  305.359745]  irq_exit+0x17f/0x1c0
[  305.363217]  smp_apic_timer_interrupt+0x1cb/0x760
[  305.368063]  ? smp_reschedule_interrupt+0x109/0x650
[  305.373107]  ? smp_call_function_single_interrupt+0x650/0x650
[  305.378995]  ? interrupt_entry+0xb5/0xf0
[  305.383065]  ? trace_hardirqs_off_caller+0xbb/0x310
[  305.388081]  ? trace_hardirqs_off_caller+0xbb/0x310
[  305.393102]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[  305.397950]  ? trace_hardirqs_on_caller+0x310/0x310
[  305.402965]  ? trace_hardirqs_on_caller+0x310/0x310
[  305.407986]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.413532]  ? check_preemption_disabled+0x48/0x280
[  305.418562]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.424108]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[  305.428962]  apic_timer_interrupt+0xf/0x20
[  305.433187]  </IRQ>
[  305.435425] RIP: 0010:kmem_cache_alloc+0x297/0x730
[  305.440365] Code: 7e 0f 85 cf fe ff ff e8 56 be 3e ff e9 c5 fe ff ff e8 5d f8 c2 ff 48 83 3d 8d 32 70 07 00 0f 84 3b 03 00 00 48 8b 7d d0 57 9d <0f> 1f 44 00 00 e9 54 fe ff ff 31 d2 be a5 01 00 00 48 c7 c7 d2 9e
[  305.460917] RSP: 0018:ffff880199b47748 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
[  305.468630] RAX: 0000000000000000 RBX: 0000000000480020 RCX: 0000000000000000
[  305.475894] RDX: 0000000000000000 RSI: ffff880198e44a80 RDI: 0000000000000286
[  305.483160] RBP: ffff880199b477b0 R08: ffff880198e44200 R09: 0000000000000000
[  305.490425] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[  305.497693] R13: ffff8801d9be7680 R14: ffff8801d9be7680 R15: 0000000000480020
[  305.505006]  skb_clone+0x1bb/0x500
[  305.508553]  ? finish_task_switch+0x1b4/0x910
[  305.513051]  ? skb_split+0x11e0/0x11e0
[  305.516941]  ? preempt_notifier_register+0x200/0x200
[  305.522045]  ? __switch_to_asm+0x34/0x70
[  305.526105]  ? __switch_to_asm+0x34/0x70
[  305.530161]  ? __switch_to_asm+0x40/0x70
[  305.534217]  ? __switch_to_asm+0x34/0x70
[  305.538275]  ? __switch_to_asm+0x40/0x70
[  305.542331]  ? __switch_to_asm+0x34/0x70
[  305.546386]  ? __switch_to_asm+0x40/0x70
[  305.550442]  ? __switch_to_asm+0x34/0x70
[  305.554510]  ? __switch_to_asm+0x34/0x70
[  305.558580]  ? __switch_to_asm+0x40/0x70
[  305.562640]  ? __switch_to_asm+0x34/0x70
[  305.566707]  bpf_clone_redirect+0xb9/0x490
[  305.570948]  ? __schedule+0x874/0x1ed0
[  305.574844]  bpf_prog_bebbfe2050753572+0x1fa/0x1000
[  305.579864]  ? __sched_text_start+0x8/0x8
[  305.584013]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[  305.588790]  ? find_held_lock+0x36/0x1c0
[  305.592859]  ? lock_acquire+0x1ed/0x520
[  305.596832]  ? bpf_test_run+0x32e/0x5a0
[  305.600806]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.606345]  ? check_preemption_disabled+0x48/0x280
[  305.611368]  ? kasan_check_read+0x11/0x20
[  305.615522]  ? rcu_dynticks_curr_cpu_in_eqs+0x9f/0x160
[  305.620799]  ? rcu_bh_qs+0xc0/0xc0
[  305.624340]  ? preempt_schedule+0x4d/0x60
[  305.628487]  ? ___preempt_schedule+0x16/0x18
[  305.632912]  ? bpf_test_run+0x1c0/0x5a0
[  305.636901]  ? netlink_diag_dump+0x2a0/0x2a0
[  305.641311]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[  305.646845]  ? bpf_test_init.isra.9+0x70/0x100
[  305.651429]  ? bpf_prog_test_run_skb+0x634/0xb40
[  305.656190]  ? bpf_test_finish.isra.8+0x1f0/0x1f0
[  305.661041]  ? __sanitizer_cov_trace_const_cmp1+0x1a/0x20
[  305.666574]  ? fput+0x130/0x1a0
[  305.669858]  ? __bpf_prog_get+0x9b/0x290
[  305.673922]  ? bpf_test_finish.isra.8+0x1f0/0x1f0
[  305.678766]  ? bpf_prog_test_run+0x130/0x1a0
[  305.683181]  ? __x64_sys_bpf+0x3d8/0x510
[  305.687245]  ? bpf_prog_get+0x20/0x20
[  305.691070]  ? do_syscall_64+0x1b9/0x820
[  305.695133]  ? entry_SYSCALL_64_after_hwframe+0x3e/0xbe
[  305.700512]  ? syscall_return_slowpath+0x5e0/0x5e0
[  305.705447]  ? trace_hardirqs_on_caller+0x310/0x310
[  305.710464]  ? prepare_exit_to_usermode+0x3b0/0x3b0
[  305.715498]  ? recalc_sigpending_tsk+0x180/0x180
[  305.720264]  ? kasan_check_write+0x14/0x20
[  305.724515]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[  305.729367]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  305.734747] warn_alloc_show_mem: 1 callbacks suppressed
[  305.734759] CPU: 0 PID: 10910 Comm: syz-executor1 Not tainted 4.19.0-rc8+ #67
[  305.734761] Mem-Info:
[  305.734792] active_anon:45824 inactive_anon:725 isolated_anon:0
[  305.734792]  active_file:13 inactive_file:17 isolated_file:0
[  305.734792]  unevictable:0 dirty:0 writeback:0 unstable:0
[  305.734792]  slab_reclaimable:9190 slab_unreclaimable:1477741
[  305.734792]  mapped:49154 shmem:1469 pagetables:662 bounce:0
[  305.734792]  free:13547 free_pcp:33 free_cma:0
[  305.740124] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[  305.747402] Node 0 active_anon:183296kB inactive_anon:2900kB active_file:52kB inactive_file:68kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:196616kB dirty:0kB writeback:0kB shmem:5876kB shmem_thp: 0kB shmem_pmdmapped: 0kB anon_thp: 165888kB writeback_tmp:0kB unstable:0kB all_unreclaimable? no
[  305.749799] Call Trace:
[  305.782680] Node 0
[  305.792026]  <IRQ>
[  305.819637] DMA free:15908kB min:164kB low:204kB high:244kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB writepending:0kB present:15992kB managed:15908kB mlocked:0kB kernel_stack:0kB pagetables:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[  305.822201]  dump_stack+0x1c4/0x2b6
[  305.824403] lowmem_reserve[]:
[  305.826552]  ? dump_stack_print_info.cold.1+0x20/0x20
[  305.852117]  0
[  305.855742]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  305.858815]  2819 6323
[  305.864010]  warn_alloc.cold.119+0xb7/0x1bd
[  305.865780]  6323
[  305.871310]  ? zone_watermark_ok_safe+0x3f0/0x3f0
[  305.878102]  ? lock_downgrade+0x900/0x900
[  305.880136] Node 0
[  305.884978]  ? trace_hardirqs_off+0xb8/0x310
[  305.889123] DMA32 free:24828kB min:30060kB low:37572kB high:45084kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB writepending:0kB present:3129332kB managed:2890736kB mlocked:0kB kernel_stack:0kB pagetables:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[  305.891329]  ? trace_hardirqs_off+0xb8/0x310
[  305.895711] lowmem_reserve[]:
[  305.922272]  __alloc_pages_slowpath+0x265e/0x2d70
[  305.926648]  0
[  305.929773]  ? warn_alloc+0x120/0x120
[  305.934562]  0
[  305.936357]  ? lock_release+0x970/0x970
[  305.940124]  3503 3503
[  305.941927]  ? warn_alloc+0x120/0x120
[  305.948371]  ? print_usage_bug+0xc0/0xc0
[  305.952147] Node 0
[  305.956199]  ? warn_alloc+0x120/0x120
[  305.956230] Normal free:13452kB min:37352kB low:46688kB high:56024kB active_anon:183296kB inactive_anon:2900kB active_file:52kB inactive_file:68kB unevictable:0kB writepending:0kB present:4718592kB managed:3588044kB mlocked:0kB kernel_stack:5440kB pagetables:2648kB bounce:0kB free_pcp:132kB local_pcp:0kB free_cma:0kB
[  305.956237] lowmem_reserve[]:
[  305.958475]  ? print_usage_bug+0xc0/0xc0
[  305.962248]  0 0
[  305.990461]  ? __lock_acquire+0x7ec/0x4ec0
[  305.993541]  0
[  305.997599]  ? __lock_acquire+0x7ec/0x4ec0
[  305.999550]  0
[  306.003779]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.005553] Node 0
[  306.009781]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[  306.011559] DMA:
[  306.017093]  ? should_fail+0x22d/0xd01
[  306.019307] 1*4kB
[  306.024839]  ? fault_create_debugfs_attr+0x1f0/0x1f0
[  306.026923] (U)
[  306.030805]  ? __lock_acquire+0x7ec/0x4ec0
[  306.032928] 0*8kB
[  306.038021]  ? fault_create_debugfs_attr+0x1f0/0x1f0
[  306.039975] 0*16kB
[  306.044201]  ? __lock_acquire+0x7ec/0x4ec0
[  306.046325] 1*32kB
[  306.051417]  ? should_fail+0x22d/0xd01
[  306.053631] (U)
[  306.057866]  ? mark_held_locks+0x130/0x130
[  306.060071] 2*64kB
[  306.063951]  ? mark_held_locks+0x130/0x130
[  306.065913] (U)
[  306.070136]  ? graph_lock+0x170/0x170
[  306.072353] 1*128kB
[  306.076575]  ? print_usage_bug+0xc0/0xc0
[  306.078533] (U)
[  306.082326]  ? graph_lock+0x170/0x170
[  306.084630] 1*256kB
[  306.088680]  ? print_usage_bug+0xc0/0xc0
[  306.090630] (U)
[  306.094423]  ? wq_watchdog_touch+0x9c/0xfe
[  306.096717] 0*512kB 1*1024kB
[  306.100783]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.102733] (U)
[  306.106966]  ? check_preemption_disabled+0x48/0x280
[  306.110045] 1*2048kB (M)
[  306.115590]  ? check_preemption_disabled+0x48/0x280
[  306.117540] 3*4096kB
[  306.122558]  ? __lock_is_held+0xb5/0x140
[  306.125293] (M)
[  306.130304]  __alloc_pages_nodemask+0xa80/0xde0
[  306.132688] = 15908kB
[  306.136737]  ? graph_lock+0x170/0x170
[  306.138692] Node 0
[  306.143355]  ? __alloc_pages_slowpath+0x2d70/0x2d70
[  306.145738] DMA32:
[  306.149533]  ? graph_lock+0x170/0x170
[  306.151745] 5*4kB
[  306.156756]  ? find_held_lock+0x36/0x1c0
[  306.158961] (UM)
[  306.162759]  ? ____cache_alloc_node+0x1c7/0x1e0
[  306.164877] 0*8kB
[  306.168926]  ? lock_downgrade+0x900/0x900
[  306.170964] 2*16kB
[  306.175629]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.177751] (M)
[  306.181898]  cache_grow_begin+0x91/0x8c0
[  306.184109] 2*32kB
[  306.189637]  ? do_raw_spin_unlock+0xa7/0x330
[  306.191583] (M)
[  306.195641]  fallback_alloc+0x203/0x2e0
[  306.197847] 4*64kB
[  306.202250]  ____cache_alloc_node+0x1c7/0x1e0
[  306.204195] (M)
[  306.208166]  kmem_cache_alloc_node+0xe3/0x730
[  306.210374] 3*128kB
[  306.214869]  ? ipv6_get_ifaddr+0x42e/0x620
[  306.216816] (M)
[  306.221313]  __alloc_skb+0x119/0x770
[  306.223606] 3*256kB
[  306.227837]  ? rcu_dynticks_curr_cpu_in_eqs+0x9f/0x160
[  306.229785] (M)
[  306.233500]  ? skb_scrub_packet+0x490/0x490
[  306.235798] 4*512kB
[  306.241065]  ? lock_downgrade+0x900/0x900
[  306.243012] (UM)
[  306.247330]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.249625] 3*1024kB
[  306.253768]  ? refcount_sub_and_test_checked+0x203/0x310
[  306.255812] (UM)
[  306.261345]  ? refcount_inc_not_zero_checked+0x2f0/0x2f0
[  306.263728] 3*2048kB
[  306.269175]  ? addrconf_rs_timer+0x690/0x690
[  306.271211] (M)
[  306.276662]  ndisc_alloc_skb+0x144/0x340
[  306.279044] 3*4096kB
[  306.283449]  ndisc_send_rs+0x331/0x6e0
[  306.285398] (M)
[  306.289455]  addrconf_rs_timer+0x314/0x690
[  306.291835] = 25076kB
[  306.295717]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  306.297663] Node 0
[  306.301899]  call_timer_fn+0x272/0x920
[  306.304276] Normal:
[  306.308517]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  306.310726] 1011*4kB
[  306.314609]  ? process_timeout+0x40/0x40
[  306.316950] (UME)
[  306.321177]  ? find_held_lock+0x36/0x1c0
[  306.323574] 466*8kB
[  306.327634]  ? __run_timers+0x7da/0xc70
[  306.329754] (UME)
[  306.333811]  ? _raw_spin_unlock_irq+0x27/0x80
[  306.336109] 204*16kB
[  306.340075]  ? _raw_spin_unlock_irq+0x27/0x80
[  306.342203] (UME)
[  306.346692]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  306.349077] 71*32kB
[  306.353565]  ? lockdep_hardirqs_on+0x19e/0x5c0
[  306.355684] (ME)
[  306.359910]  ? trace_hardirqs_on+0xbd/0x310
[  306.362209] 5*64kB
[  306.366784]  ? kasan_check_read+0x11/0x20
[  306.368821] (UM)
[  306.373138]  ? __run_timers+0x7da/0xc70
[  306.375352] 1*128kB
[  306.379520]  ? __bpf_trace_preemptirq_template+0x30/0x30
[  306.381554] (U) 0*256kB
[  306.385536]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  306.387826] 0*512kB
[  306.393267]  ? ipv6_get_lladdr+0x5e0/0x5e0
[  306.395909] 0*1024kB
[  306.400135]  __run_timers+0x7e5/0xc70
[  306.402431] 0*2048kB
[  306.406664]  ? __bpf_trace_timer_expire_entry+0x30/0x30
[  306.409042] 0*4096kB
[  306.412837]  ? __sanitizer_cov_trace_cmp8+0x18/0x20
[  306.415224] = 13756kB
[  306.420578]  ? graph_lock+0x170/0x170
[  306.422975] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[  306.427978]  ? enqueue_hrtimer+0x1a5/0x560
[  306.430370] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  306.434161]  ? lock_release+0x970/0x970
[  306.442969] 1499 total pagecache pages
[  306.447196]  ? hrtimer_update_softirq_timer+0xa0/0xa0
[  306.455754] 0 pages in swap cache
[  306.459718]  ? find_held_lock+0x36/0x1c0
[  306.463582] Swap cache stats: add 0, delete 0, find 0/0
[  306.468763]  ? graph_lock+0x170/0x170
[  306.472194] Free swap  = 0kB
[  306.476244]  ? pvclock_read_flags+0x160/0x160
[  306.481611] Total swap = 0kB
[  306.485407]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.488397] 1965979 pages RAM
[  306.492883]  ? check_preemption_disabled+0x48/0x280
[  306.495876] 0 pages HighMem/MovableOnly
[  306.501410]  ? __lock_is_held+0xb5/0x140
[  306.504482] 342307 pages reserved
[  306.509503]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.513463] 0 pages cma reserved
[  306.517533]  ? check_preemption_disabled+0x48/0x280
[  306.521018] ICMPv6: ndisc: ndisc_alloc_skb failed to allocate an skb
[  306.526484]  run_timer_softirq+0x52/0xb0
[  306.526509]  ? rcu_read_lock_sched_held+0x108/0x120
[  306.526532]  __do_softirq+0x30c/0xb03
[  306.529930] syz-executor1: page allocation failure: order:0, mode:0x484020(GFP_ATOMIC|__GFP_COMP), nodemask=(null)
[  306.534891]  ? __irqentry_text_end+0x1f9618/0x1f9618
[  306.541347] syz-executor1 cpuset=
[  306.545402]  ? pvclock_read_flags+0x160/0x160
[  306.550386] syz1
[  306.554179]  ? lapic_next_event+0x5a/0x90
[  306.564642]  mems_allowed=0
[  306.569737]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.592182]  ? check_preemption_disabled+0x48/0x280
[  306.597201]  ? check_preemption_disabled+0x48/0x280
[  306.602222]  ? kvm_clock_read+0x18/0x30
[  306.606206]  ? kvm_sched_clock_read+0x9/0x20
[  306.610622]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.616164]  ? check_preemption_disabled+0x48/0x280
[  306.621192]  irq_exit+0x17f/0x1c0
[  306.624652]  smp_apic_timer_interrupt+0x1cb/0x760
[  306.629501]  ? smp_reschedule_interrupt+0x109/0x650
[  306.634535]  ? smp_call_function_single_interrupt+0x650/0x650
[  306.640418]  ? interrupt_entry+0xb5/0xf0
[  306.644482]  ? trace_hardirqs_off_caller+0xbb/0x310
[  306.649516]  ? trace_hardirqs_off_caller+0xbb/0x310
[  306.654543]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[  306.659882]  ? trace_hardirqs_on_caller+0x310/0x310
[  306.664894]  ? trace_hardirqs_on_caller+0x310/0x310
[  306.669910]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.675451]  ? check_preemption_disabled+0x48/0x280
[  306.680468]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.686516]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[  306.691373]  apic_timer_interrupt+0xf/0x20
[  306.695599]  </IRQ>
[  306.697846] RIP: 0010:kmem_cache_alloc+0x297/0x730
[  306.702776] Code: 7e 0f 85 cf fe ff ff e8 56 be 3e ff e9 c5 fe ff ff e8 5d f8 c2 ff 48 83 3d 8d 32 70 07 00 0f 84 3b 03 00 00 48 8b 7d d0 57 9d <0f> 1f 44 00 00 e9 54 fe ff ff 31 d2 be a5 01 00 00 48 c7 c7 d2 9e
[  306.721677] RSP: 0000:ffff8801960af748 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
[  306.729398] RAX: 0000000000000000 RBX: 0000000000480020 RCX: 0000000000000000
[  306.736664] RDX: 0000000000000000 RSI: ffff8801cbad4c40 RDI: 0000000000000286
[  306.743934] RBP: ffff8801960af7b0 R08: ffff8801cbad43c0 R09: 0000000000000000
[  306.751201] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[  306.758468] R13: ffff8801d9be7680 R14: ffff8801d9be7680 R15: 0000000000480020
[  306.765786]  skb_clone+0x1bb/0x500
[  306.769326]  ? skb_split+0x11e0/0x11e0
[  306.773214]  ? preempt_notifier_register+0x200/0x200
[  306.778312]  ? __switch_to_asm+0x34/0x70
[  306.782369]  ? __switch_to_asm+0x34/0x70
[  306.786429]  ? __switch_to_asm+0x40/0x70
[  306.790532]  ? __switch_to_asm+0x34/0x70
[  306.794590]  ? __switch_to_asm+0x40/0x70
[  306.798650]  ? __switch_to_asm+0x40/0x70
[  306.802710]  ? __switch_to_asm+0x34/0x70
[  306.806772]  ? __switch_to_asm+0x34/0x70
[  306.810831]  ? __switch_to_asm+0x40/0x70
[  306.814891]  ? __switch_to_asm+0x34/0x70
[  306.819064]  bpf_clone_redirect+0xb9/0x490
[  306.823311]  bpf_prog_bebbfe2050753572+0x1fa/0x1000
[  306.828330]  ? __sched_text_start+0x8/0x8
[  306.832483]  ? retint_kernel+0x2d/0x2d
[  306.836392]  ? find_held_lock+0x36/0x1c0
[  306.840461]  ? lock_acquire+0x1ed/0x520
[  306.844442]  ? bpf_test_run+0x32e/0x5a0
[  306.848416]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  306.853958]  ? check_preemption_disabled+0x48/0x280
[  306.858982]  ? kasan_check_read+0x11/0x20
[  306.863130]  ? rcu_dynticks_curr_cpu_in_eqs+0x9f/0x160
[  306.868407]  ? rcu_bh_qs+0xc0/0xc0
[  306.871949]  ? preempt_schedule+0x4d/0x60
[  306.876097]  ? ___preempt_schedule+0x16/0x18
[  306.880519]  ? bpf_test_run+0x1c0/0x5a0
[  306.884527]  ? netlink_diag_dump+0x2a0/0x2a0
[  306.888941]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[  306.894481]  ? bpf_test_init.isra.9+0x70/0x100
[  306.899078]  ? bpf_prog_test_run_skb+0x634/0xb40
[  306.903843]  ? bpf_test_finish.isra.8+0x1f0/0x1f0
[  306.908690]  ? __sanitizer_cov_trace_const_cmp1+0x1a/0x20
[  306.914236]  ? fput+0x130/0x1a0
[  306.917530]  ? __bpf_prog_get+0x9b/0x290
[  306.921599]  ? bpf_test_finish.isra.8+0x1f0/0x1f0
[  306.926445]  ? bpf_prog_test_run+0x130/0x1a0
[  306.930861]  ? __x64_sys_bpf+0x3d8/0x510
[  306.934925]  ? bpf_prog_get+0x20/0x20
[  306.938748]  ? do_syscall_64+0x1b9/0x820
[  306.942808]  ? entry_SYSCALL_64_after_hwframe+0x3e/0xbe
[  306.948175]  ? syscall_return_slowpath+0x5e0/0x5e0
[  306.953106]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[  306.957957]  ? trace_hardirqs_on_caller+0x310/0x310
[  306.962992]  ? prepare_exit_to_usermode+0x3b0/0x3b0
[  306.968012]  ? prepare_exit_to_usermode+0x291/0x3b0
[  306.973039]  ? trace_hardirqs_off_thunk+0x1a/0x1c
[  306.977896]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe

とても汚いですよね?メッセージが混在してしまったことが原因で、問題に関連したメッセージを抽出することができずに捨てられてしまったというレポートが多数存在しています。

till5.0.png

printk() は、1行分のメッセージを複数回の呼び出しに分けて出力する場合、可能であれば、 printk() の内部でバッファリング処理を行うようになっています。バッファリングのために、 cont 構造体というグローバル変数が存在しており、 KERN_CONT プレフィックスを付けた printk() 呼び出しが行われた場合に、1行分の出力をバッファリングすることを試みます。

そのため、 printk() は、1行分のメッセージを1回の呼び出しで出力する場合は問題にならないのですが、1行分のメッセージを複数回の呼び出しに分けて出力する場合は、複数のスレッドが同時に printk() を呼び出すことにより、異なるメッセージが混ざってしまったり、必要以上に改行されてしまったりすることで、解読することが難しくなるという問題があります。また、メッセージによっては、複数行をひとまとめにして扱えないと意味がないというケースもあります。

しかし、 Linux 5.0 以前の printk() には、コンソールに出力するメッセージに対して、「誰が」に相当する「 printk() を呼び出したスレッド」の情報を追加するという機能がありませんでした。 printk() を呼び出すスレッド自身が、自身のスレッドIDなどの情報をメッセージの中に含めるという、自己申告な方法に頼らざるを得なかった訳です。

ユーザランドで動作するプロセスの場合、 stdout というグローバル変数が共有される範囲は当該プロセスに閉じられます。しかし、カーネルの世界では、システム上に存在する全てのスレッドで stdout 相当のグローバル変数を共有しています。そのため、メッセージが混在しないようにするためには、 printk() を呼ぶ可能性のある全ての関数に対して FILE *fp に相当する引数を渡してやる必要がある訳です。あるいは、 printk() を呼ぶ前に snprintf() 相当の処理を行うことにより、1行分のメッセージを1回の printk() 呼び出しで出力できるようにしてやる必要がある訳です。

ソースコードの規模が2000万行を超える Linux カーネルのソースコードに対して、 printf() を全て fprintf(fp) に置き換えるのは大変な修正であることは想像に難くないでしょう。そして、修正が大変である割に得られるメリットが少ないため、 printk() を提供する側が API を提供したとしても、 printk() を利用する側がその API へ移行してもらえる可能性は低いという現実があります。

たとえ FILE *fp に相当する引数を渡してやるという大工事を敢行できたとしても、バッファリングできる量には限界があります。そのため、複数行をひとまとめにして扱えないと意味がないというケースに対処できない可能性が残ります。

そして、1年近くに渡った試行錯誤の結果として、 Linux 5.1 では、 printk() は「いつ」「どんな発言をしたか」だけを記録/出力するものから「いつ」「誰が」「どんな発言をしたか」を記録/出力するものへという、小さいけれども重要な変化を迎えました。

since5.1.png

このパッチが適用された状態で syzbot によるファジングテストが出力したメッセージのサンプルを見てみましょう。

[  431.587790][T11985] list_add corruption. next->prev should be prev (ffff888091d3aa60), but was 0000000000000002. (next=ffff8880984df5f0).
[  431.600938][T11985] ------------[ cut here ]------------
[  431.606407][T11985] kernel BUG at lib/list_debug.c:23!
[  431.611776][T11985] invalid opcode: 0000 [#1] PREEMPT SMP KASAN
[  431.617846][T11985] CPU: 0 PID: 11985 Comm: syz-executor.4 Not tainted 5.1.0-rc1+ #34
[  431.625816][T11985] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[  431.635992][T11985] RIP: 0010:__list_add_valid.cold+0xf/0x3c
[  431.641809][T11985] Code: 77 fe eb d5 4c 89 e7 e8 ba 6a 77 fe eb a3 4c 89 f7 e8 b0 6a 77 fe e9 56 ff ff ff 4c 89 e1 48 c7 c7 00 d5 a1 87 e8 f0 ce 29 fe <0f> 0b 48 89 f2 4c 89 e1 4c 89 ee 48 c7 c7 40 d6 a1 87 e8 d9 ce 29
[  431.661418][T11985] RSP: 0018:ffff888085b3f4b0 EFLAGS: 00010286
[  431.667493][T11985] RAX: 0000000000000075 RBX: ffff888085b3f5d8 RCX: 0000000000000000
[  431.675471][T11985] RDX: 0000000000000000 RSI: ffffffff815ae266 RDI: ffffed1010b67e88
[  431.683454][T11985] RBP: ffff888085b3f4c8 R08: 0000000000000075 R09: ffffed1015d05011
[  431.691687][T11985] R10: ffffed1015d05010 R11: ffff8880ae828087 R12: ffff8880984df5f0
[  431.699662][T11985] R13: ffff888085b3f5f0 R14: ffff888091d3aa40 R15: ffff888091d3aa60
[  431.707645][T11985] FS:  00007f7a35de9700(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
[  431.712900][ T3875] kobject: 'loop5' (00000000b52308e2): kobject_uevent_env
[  431.716594][T11985] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  431.727050][ T3875] kobject: 'loop5' (00000000b52308e2): fill_kobj_path: path = '/devices/virtual/block/loop5'
[  431.730268][T11985] CR2: 0000000020000000 CR3: 00000000a61fa000 CR4: 00000000001406f0
[  431.730277][T11985] Call Trace:
[  431.730371][T11985]  rhashtable_walk_enter+0x1b0/0x390
[  431.730467][T11985]  ila_xlat_nl_cmd_flush+0x244/0x1090
[  431.744246][ T3875] kobject: 'loop0' (00000000f382af94): kobject_uevent_env
[  431.750098][T11985]  ? kasan_check_read+0x11/0x20
[  431.750147][T11985]  ? _raw_spin_unlock_irqrestore+0xa4/0xe0
[  431.753469][ T3875] kobject: 'loop0' (00000000f382af94): fill_kobj_path: path = '/devices/virtual/block/loop0'
[  431.758677][T11985]  ? ila_xlat_nl_cmd_del_mapping+0x22a0/0x22a0
[  431.758764][T11985]  ? __nla_parse+0x12a/0x340
[  431.764562][ T3875] kobject: 'loop5' (00000000b52308e2): kobject_uevent_env
[  431.771226][T11985]  genl_family_rcv_msg+0x6e1/0xd90
[  431.771245][T11985]  ? genl_unregister_family+0x790/0x790
[  431.776163][ T3875] kobject: 'loop5' (00000000b52308e2): fill_kobj_path: path = '/devices/virtual/block/loop5'
[  431.781937][T11985]  ? __local_bh_enable_ip+0x15a/0x270
[  431.782011][T11985]  ? __dev_queue_xmit+0xb8a/0x3060
[  431.792710][ T3875] kobject: 'loop0' (00000000f382af94): kobject_uevent_env
[  431.798383][T11985]  ? __lock_acquire+0x548/0x3fb0
[  431.798441][T11985]  ? radix_tree_lookup+0x22/0x30
[  431.803124][ T3875] kobject: 'loop0' (00000000f382af94): fill_kobj_path: path = '/devices/virtual/block/loop0'
[  431.812077][T11985]  genl_rcv_msg+0xca/0x16c
[  431.812091][T11985]  netlink_rcv_skb+0x17a/0x460
[  431.812102][T11985]  ? genl_family_rcv_msg+0xd90/0xd90
[  431.812113][T11985]  ? netlink_ack+0xb50/0xb50
[  431.812132][T11985]  genl_rcv+0x29/0x40
[  431.819539][ T3875] kobject: 'loop5' (00000000b52308e2): kobject_uevent_env
[  431.824522][T11985]  netlink_unicast+0x536/0x720
[  431.824537][T11985]  ? netlink_attachskb+0x770/0x770
[  431.824558][T11985]  ? _copy_from_iter_full+0x259/0x8f0
[  431.834840][ T3875] kobject: 'loop5' (00000000b52308e2): fill_kobj_path: path = '/devices/virtual/block/loop5'
[  431.840149][T11985]  ? __sanitizer_cov_trace_cmp8+0x18/0x20
[  431.840222][T11985]  ? __check_object_size+0x3d/0x42f
[  431.845802][ T3875] kobject: 'loop0' (00000000f382af94): kobject_uevent_env
[  431.852363][T11985]  netlink_sendmsg+0x8ae/0xd70
[  431.852372][T11985]  ? netlink_unicast+0x720/0x720
[  431.852414][T11985]  ? tomoyo_socket_sendmsg+0x26/0x30
[  431.852424][T11985]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  431.852445][T11985]  ? security_socket_sendmsg+0x93/0xc0
[  431.852452][T11985]  ? netlink_unicast+0x720/0x720
[  431.852477][T11985]  sock_sendmsg+0xdd/0x130
[  431.852498][T11985]  ___sys_sendmsg+0x806/0x930
[  431.852507][T11985]  ? copy_msghdr_from_user+0x430/0x430
[  431.852518][T11985]  ? kasan_check_read+0x11/0x20
[  431.852531][T11985]  ? __fget+0x381/0x550
[  431.852539][T11985]  ? ksys_dup3+0x3e0/0x3e0
[  431.852548][T11985]  ? lock_downgrade+0x880/0x880
[  431.852556][T11985]  ? __fget_light+0x1a9/0x230
[  431.852563][T11985]  ? __fdget+0x1b/0x20
[  431.852570][T11985]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[  431.852578][T11985]  __sys_sendmsg+0x105/0x1d0
[  431.852586][T11985]  ? __ia32_sys_shutdown+0x80/0x80
[  431.852613][T11985]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[  431.852620][T11985]  ? do_syscall_64+0x26/0x610
[  431.852643][T11985]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  431.852650][T11985]  ? do_syscall_64+0x26/0x610
[  431.852659][T11985]  __x64_sys_sendmsg+0x78/0xb0
[  431.852666][T11985]  do_syscall_64+0x103/0x610
[  431.852674][T11985]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  431.852680][T11985] RIP: 0033:0x458209
[  431.852689][T11985] Code: ad b8 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 7b b8 fb ff c3 66 2e 0f 1f 84 00 00 00 00
[  431.852693][T11985] RSP: 002b:00007f7a35de8c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
[  431.852700][T11985] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000458209
[  431.852704][T11985] RDX: 0000000000000000 RSI: 0000000020000000 RDI: 0000000000000003
[  431.852708][T11985] RBP: 000000000073bf00 R08: 0000000000000000 R09: 0000000000000000
[  431.852712][T11985] R10: 0000000000000000 R11: 0000000000000246 R12: 00007f7a35de96d4
[  431.852716][T11985] R13: 00000000004c57c8 R14: 00000000004d96b8 R15: 00000000ffffffff
[  431.852722][T11985] Modules linked in:
[  431.853086][T11985] ---[ end trace 25c5a70a6fa97765 ]---
[  431.863520][ T3875] kobject: 'loop0' (00000000f382af94): fill_kobj_path: path = '/devices/virtual/block/loop0'
[  431.873006][T11985] RIP: 0010:__list_add_valid.cold+0xf/0x3c
[  431.873020][T11985] Code: 77 fe eb d5 4c 89 e7 e8 ba 6a 77 fe eb a3 4c 89 f7 e8 b0 6a 77 fe e9 56 ff ff ff 4c 89 e1 48 c7 c7 00 d5 a1 87 e8 f0 ce 29 fe <0f> 0b 48 89 f2 4c 89 e1 4c 89 ee 48 c7 c7 40 d6 a1 87 e8 d9 ce 29
[  431.873035][T11985] RSP: 0018:ffff888085b3f4b0 EFLAGS: 00010286
[  431.879650][ T3875] kobject: 'loop1' (00000000bc129627): kobject_uevent_env
[  431.882237][T11985] RAX: 0000000000000075 RBX: ffff888085b3f5d8 RCX: 0000000000000000
[  431.887498][ T3875] kobject: 'loop1' (00000000bc129627): fill_kobj_path: path = '/devices/virtual/block/loop1'
[  431.892076][T11985] RDX: 0000000000000000 RSI: ffffffff815ae266 RDI: ffffed1010b67e88
[  431.892084][T11985] RBP: ffff888085b3f4c8 R08: 0000000000000075 R09: ffffed1015d05011
[  431.892093][T11985] R10: ffffed1015d05010 R11: ffff8880ae828087 R12: ffff8880984df5f0
[  431.892101][T11985] R13: ffff888085b3f5f0 R14: ffff888091d3aa40 R15: ffff888091d3aa60
[  431.892118][T11985] FS:  00007f7a35de9700(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
[  431.898369][ T3875] kobject: 'loop0' (00000000f382af94): kobject_uevent_env
[  431.903200][T11985] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  431.907978][ T3875] kobject: 'loop0' (00000000f382af94): fill_kobj_path: path = '/devices/virtual/block/loop0'
[  431.913069][T11985] CR2: 0000000020000000 CR3: 00000000a61fa000 CR4: 00000000001406f0
[  431.913082][T11985] Kernel panic - not syncing: Fatal exception
[  431.919337][T11985] Kernel Offset: disabled
[  432.302441][T11985] Rebooting in 86400 seconds..
[ 2489.914435][    C1] rcu: INFO: rcu_preempt self-detected stall on CPU
[ 2489.914767][    C0] net_ratelimit: 20 callbacks suppressed
[ 2489.914777][    C0] protocol 88fb is buggy, dev hsr_slave_0
[ 2489.921374][    C1] rcu: 	1-...!: (1 ticks this GP) idle=326/1/0x4000000000000002 softirq=191886/191886 fqs=0 
[ 2489.926852][    C0] protocol 88fb is buggy, dev hsr_slave_1
[ 2489.928124][    C0] protocol 88fb is buggy, dev hsr_slave_0
[ 2489.932839][    C1] 	(t=29997 jiffies g=305737 q=2410)
[ 2489.943074][    C0] protocol 88fb is buggy, dev hsr_slave_1
[ 2489.948711][    C1] rcu: rcu_preempt kthread starved for 29997 jiffies! g305737 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x0 ->cpu=0
[ 2489.948717][    C1] rcu: RCU grace-period kthread stack dump:
[ 2489.948724][    C1] rcu_preempt     R  running task    29056    10      2 0x80004000
[ 2489.955142][    C0] protocol 88fb is buggy, dev hsr_slave_0
[ 2489.959721][    C1] Call Trace:
[ 2489.965492][    C0] protocol 88fb is buggy, dev hsr_slave_1
[ 2489.976701][    C1]  __schedule+0x7d1/0x1580
[ 2489.976723][    C1]  ? __sched_text_start+0x8/0x8
[ 2489.982695][    C0] protocol 88fb is buggy, dev hsr_slave_0
[ 2489.990481][    C1]  ? _raw_spin_unlock_irqrestore+0x6b/0xe0
[ 2489.990497][    C1]  ? schedule_timeout+0x47c/0xc50
[ 2489.990518][    C1]  ? lockdep_hardirqs_on+0x418/0x5d0
[ 2489.996334][    C0] protocol 88fb is buggy, dev hsr_slave_1
[ 2489.999524][    C1]  schedule+0xa8/0x260
[ 2490.007914][    C0] protocol 88fb is buggy, dev hsr_slave_0
[ 2490.009679][    C1]  schedule_timeout+0x486/0xc50
[ 2490.014589][    C0] protocol 88fb is buggy, dev hsr_slave_1
[ 2490.020236][    C1]  ? usleep_range+0x170/0x170
[ 2490.037211][    C0] BUG: workqueue lockup - pool cpus=0-1 flags=0x4 nice=0 stuck for 299s!
[ 2490.042031][    C1]  ? trace_hardirqs_on+0x67/0x230
[ 2490.042056][    C1]  ? kasan_check_read+0x11/0x20
[ 2490.046592][    C0] Showing busy workqueues and worker pools:
[ 2490.052344][    C1]  ? __next_timer_interrupt+0x1a0/0x1a0
[ 2490.052408][    C1]  ? prepare_to_swait_exclusive+0x120/0x120
[ 2490.057547][    C0] workqueue events: flags=0x0
[ 2490.063240][    C1]  rcu_gp_kthread+0x9a3/0x1830
[ 2490.068113][    C0]   pwq 0: cpus=0 node=0 flags=0x0 nice=0 active=12/256
[ 2490.076307][    C1]  ? kasan_check_write+0x14/0x20
[ 2490.081320][    C0]     pending: defense_work_handler, defense_work_handler, psi_update_work, psi_update_work, psi_update_work, psi_update_work, psi_update_work, check_corruption, switchdev_deferred_process_work, rht_deferred_worker, vmstat_shepherd, cache_reap
[ 2490.086169][    C1]  ? wait_rcu_exp_gp+0x50/0x50
[ 2490.092036][    C0] 
[ 2490.092042][    C0] ======================================================
[ 2490.092048][    C0] WARNING: possible circular locking dependency detected
[ 2490.092051][    C0] 5.1.0+ #4 Not tainted
[ 2490.092056][    C0] ------------------------------------------------------
[ 2490.092061][    C0] syz-executor.2/5319 is trying to acquire lock:
[ 2490.092064][    C0] 00000000c8d41b4f (console_owner){-.-.}, at: vprintk_emit+0x3d5/0x6d0
[ 2490.092080][    C0] 
[ 2490.092084][    C0] but task is already holding lock:
[ 2490.092087][    C0] 00000000d7d346db (&(&pool->lock)->rlock){-.-.}, at: show_workqueue_state.cold+0x879/0x11dc
[ 2490.092104][    C0] 
[ 2490.092108][    C0] which lock already depends on the new lock.
[ 2490.092111][    C0] 
[ 2490.092114][    C0] 
[ 2490.092119][    C0] the existing dependency chain (in reverse order) is:
[ 2490.092121][    C0] 
[ 2490.092124][    C0] -> #4 (&(&pool->lock)->rlock){-.-.}:
[ 2490.092139][    C0]        _raw_spin_lock+0x2f/0x40
[ 2490.092144][    C0]        __queue_work+0x23d/0x10e0
[ 2490.092148][    C0]        queue_work_on+0x192/0x200
[ 2490.092151][    C0]        put_pwq+0x178/0x1d0
[ 2490.092156][    C0]        put_pwq_unlocked.part.0+0x34/0x70
[ 2490.092160][    C0]        destroy_workqueue+0x623/0x700
[ 2490.092164][    C0]        floppy_async_init+0x2058/0x21aa
[ 2490.092168][    C0]        async_run_entry_fn+0x126/0x570
[ 2490.092172][    C0]        process_one_work+0x98e/0x1790
[ 2490.092176][    C0]        worker_thread+0x98/0xe40
[ 2490.092180][    C0]        kthread+0x357/0x430
[ 2490.092184][    C0]        ret_from_fork+0x3a/0x50
[ 2490.092187][    C0] 
[ 2490.092189][    C0] -> #3 (&pool->lock/1){..-.}:
[ 2490.092207][    C0]        _raw_spin_lock+0x2f/0x40
[ 2490.092211][    C0]        __queue_work+0x23d/0x10e0
[ 2490.092227][    C0]        queue_work_on+0x192/0x200
[ 2490.092231][    C0]        tty_flip_buffer_push+0xc5/0x100
[ 2490.092235][    C0]        pty_write+0x1a6/0x200
[ 2490.092239][    C0]        n_tty_write+0xb18/0x1150
[ 2490.092243][    C0]        tty_write+0x45b/0x7a0
[ 2490.092247][    C0]        __vfs_write+0x8d/0x110
[ 2490.092264][    C0]        vfs_write+0x20c/0x580
[ 2490.092268][    C0]        ksys_write+0x14f/0x290
[ 2490.092272][    C0]        __x64_sys_write+0x73/0xb0
[ 2490.092276][    C0]        do_syscall_64+0x103/0x670
[ 2490.092281][    C0]        entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 2490.092293][    C0] 
[ 2490.092296][    C0] -> #2 (&(&port->lock)->rlock){-.-.}:
[ 2490.092311][    C0]        _raw_spin_lock_irqsave+0x95/0xcd
[ 2490.092316][    C0]        tty_port_tty_get+0x22/0x80
[ 2490.092320][    C0]        tty_port_default_wakeup+0x16/0x40
[ 2490.092324][    C0]        tty_port_tty_wakeup+0x5d/0x70
[ 2490.092328][    C0]        uart_write_wakeup+0x46/0x70
[ 2490.092333][    C0]        serial8250_tx_chars+0x4a4/0xb20
[ 2490.092338][    C0]        serial8250_handle_irq.part.0+0x1be/0x2e0
[ 2490.092343][    C0]        serial8250_default_handle_irq+0xc5/0x150
[ 2490.092347][    C0]        serial8250_interrupt+0xfb/0x1a0
[ 2490.092351][    C0]        __handle_irq_event_percpu+0x146/0x900
[ 2490.092356][    C0]        handle_irq_event_percpu+0x74/0x160
[ 2490.092360][    C0]        handle_irq_event+0xa7/0x134
[ 2490.092364][    C0]        handle_edge_irq+0x264/0x8e0
[ 2490.092368][    C0]        handle_irq+0x41/0x60
[ 2490.092371][    C0]        do_IRQ+0x99/0x1d0
[ 2490.092375][    C0]        ret_from_intr+0x0/0x1e
[ 2490.092379][    C0]        native_safe_halt+0x2/0x10
[ 2490.092383][    C0]        arch_cpu_idle+0x10/0x20
[ 2490.092387][    C0]        default_idle_call+0x36/0x90
[ 2490.092391][    C0]        do_idle+0x377/0x560
[ 2490.092395][    C0]        cpu_startup_entry+0x1b/0x20
[ 2490.092399][    C0]        start_secondary+0x360/0x4d0
[ 2490.092404][    C0]        secondary_startup_64+0xa4/0xb0
[ 2490.092406][    C0] 
[ 2490.092409][    C0] -> #1 (&port_lock_key){-.-.}:
[ 2490.092425][    C0]        _raw_spin_lock_irqsave+0x95/0xcd
[ 2490.092429][    C0]        serial8250_console_write+0x253/0x9c0
[ 2490.092434][    C0]        univ8250_console_write+0x5f/0x70
[ 2490.092438][    C0]        console_unlock+0xb44/0xed0
[ 2490.092442][    C0]        vprintk_emit+0x280/0x6d0
[ 2490.092446][    C0]        vprintk_default+0x28/0x30
[ 2490.092450][    C0]        vprintk_func+0x7e/0x189
[ 2490.092453][    C0]        printk+0xba/0xed
[ 2490.092457][    C0]        register_console+0x74d/0xb50
[ 2490.092462][    C0]        univ8250_console_init+0x3e/0x4b
[ 2490.092465][    C0]        console_init+0x4f7/0x761
[ 2490.092470][    C0]        start_kernel+0x5b7/0x896
[ 2490.092474][    C0]        x86_64_start_reservations+0x29/0x2b
[ 2490.092478][    C0]        x86_64_start_kernel+0x77/0x7b
[ 2490.092483][    C0]        secondary_startup_64+0xa4/0xb0
[ 2490.092485][    C0] 
[ 2490.092488][    C0] -> #0 (console_owner){-.-.}:
[ 2490.092503][    C0]        lock_acquire+0x16f/0x3f0
[ 2490.092507][    C0]        vprintk_emit+0x412/0x6d0
[ 2490.092511][    C0]        vprintk_default+0x28/0x30
[ 2490.092515][    C0]        vprintk_func+0x7e/0x189
[ 2490.092518][    C0]        printk+0xba/0xed
[ 2490.092523][    C0]        show_workqueue_state.cold+0x9e4/0x11dc
[ 2490.092527][    C0]        wq_watchdog_timer_fn+0x516/0x5a0
[ 2490.092531][    C0]        call_timer_fn+0x196/0x720
[ 2490.092536][    C0]        run_timer_softirq+0xd3d/0x1740
[ 2490.092540][    C0]        __do_softirq+0x266/0x95a
[ 2490.092543][    C0]        irq_exit+0x180/0x1d0
[ 2490.092548][    C0]        smp_apic_timer_interrupt+0x14a/0x570
[ 2490.092552][    C0]        apic_timer_interrupt+0xf/0x20
[ 2490.092556][    C0]        lock_acquire+0x1ea/0x3f0
[ 2490.092566][    C0]        __mutex_lock+0xf7/0x1310
[ 2490.092571][    C0]        mutex_lock_interruptible_nested+0x16/0x20
[ 2490.092575][    C0]        __x64_sys_delete_module+0x188/0x4a0
[ 2490.092579][    C0]        do_syscall_64+0x103/0x670
[ 2490.092584][    C0]        entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 2490.092587][    C0] 
[ 2490.092591][    C0] other info that might help us debug this:
[ 2490.092594][    C0] 
[ 2490.092597][    C0] Chain exists of:
[ 2490.092600][    C0]   console_owner --> &pool->lock/1 --> &(&pool->lock)->rlock
[ 2490.092622][    C0] 
[ 2490.092626][    C0]  Possible unsafe locking scenario:
[ 2490.092628][    C0] 
[ 2490.092633][    C0]        CPU0                    CPU1
[ 2490.092637][    C0]        ----                    ----
[ 2490.092639][    C0]   lock(&(&pool->lock)->rlock);
[ 2490.092649][    C0]                                lock(&pool->lock/1);
[ 2490.092662][    C0]                                lock(&(&pool->lock)->rlock);
[ 2490.092671][    C0]   lock(console_owner);
[ 2490.092679][    C0] 
[ 2490.092683][    C0]  *** DEADLOCK ***
[ 2490.092685][    C0] 
[ 2490.092689][    C0] 4 locks held by syz-executor.2/5319:
[ 2490.092692][    C0]  #0: 000000003f5d811f (module_mutex){+.+.}, at: __x64_sys_delete_module+0x188/0x4a0
[ 2490.092710][    C0]  #1: 0000000027eb2b3a ((&wq_watchdog_timer)){+.-.}, at: call_timer_fn+0xe0/0x720
[ 2490.092728][    C0]  #2: 00000000a4fbec0f (rcu_read_lock_sched){....}, at: show_workqueue_state+0x0/0x120
[ 2490.092747][    C0]  #3: 00000000d7d346db (&(&pool->lock)->rlock){-.-.}, at: show_workqueue_state.cold+0x879/0x11dc
[ 2490.092766][    C0] 
[ 2490.092769][    C0] stack backtrace:
[ 2490.092775][    C0] CPU: 0 PID: 5319 Comm: syz-executor.2 Not tainted 5.1.0+ #4
[ 2490.092781][    C0] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[ 2490.092796][    C0] Call Trace:
[ 2490.092799][    C0]  <IRQ>
[ 2490.092803][    C0]  dump_stack+0x172/0x1f0
[ 2490.092807][    C0]  print_circular_bug.cold+0x1cc/0x28f
[ 2490.092811][    C0]  __lock_acquire+0x3755/0x5490
[ 2490.092815][    C0]  ? mark_held_locks+0xf0/0xf0
[ 2490.092820][    C0]  ? perf_trace_lock_acquire+0xf5/0x530
[ 2490.092824][    C0]  ? kasan_check_write+0x14/0x20
[ 2490.092828][    C0]  lock_acquire+0x16f/0x3f0
[ 2490.092831][    C0]  ? vprintk_emit+0x3d5/0x6d0
[ 2490.092835][    C0]  vprintk_emit+0x412/0x6d0
[ 2490.092839][    C0]  ? vprintk_emit+0x3d5/0x6d0
[ 2490.092843][    C0]  vprintk_default+0x28/0x30
[ 2490.092847][    C0]  vprintk_func+0x7e/0x189
[ 2490.092851][    C0]  ? printk+0xba/0xed
[ 2490.092854][    C0]  printk+0xba/0xed
[ 2490.092858][    C0]  ? kmsg_dump_rewind_nolock+0xe4/0xe4
[ 2490.092863][    C0]  ? show_workqueue_state.cold+0x879/0x11dc
[ 2490.092868][    C0]  show_workqueue_state.cold+0x9e4/0x11dc
[ 2490.092872][    C0]  ? wq_watchdog_timer_fn+0x3f9/0x5a0
[ 2490.092876][    C0]  ? idr_get_next+0x1a6/0x230
[ 2490.092880][    C0]  ? print_worker_info+0x280/0x280
[ 2490.092885][    C0]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[ 2490.092892][    C0]  ? kasan_check_read+0x11/0x20
[ 2490.092900][    C0]  wq_watchdog_timer_fn+0x516/0x5a0
[ 2490.092907][    C0]  ? show_workqueue_state+0x120/0x120
[ 2490.092913][    C0]  call_timer_fn+0x196/0x720
[ 2490.092921][    C0]  ? show_workqueue_state+0x120/0x120
[ 2490.092928][    C0]  ? process_timeout+0x40/0x40
[ 2490.092935][    C0]  ? run_timer_softirq+0xd2b/0x1740
[ 2490.092942][    C0]  ? trace_hardirqs_on+0x67/0x230
[ 2490.092950][    C0]  ? kasan_check_read+0x11/0x20
[ 2490.092954][    C0]  ? show_workqueue_state+0x120/0x120
[ 2490.092961][    C0]  run_timer_softirq+0xd3d/0x1740
[ 2490.092965][    C0]  ? add_timer+0x930/0x930
[ 2490.092969][    C0]  __do_softirq+0x266/0x95a
[ 2490.092973][    C0]  ? sched_clock_cpu+0x1b/0x1b0
[ 2490.092977][    C0]  irq_exit+0x180/0x1d0
[ 2490.092981][    C0]  smp_apic_timer_interrupt+0x14a/0x570
[ 2490.092989][    C0]  apic_timer_interrupt+0xf/0x20
[ 2490.092992][    C0]  </IRQ>
[ 2490.093002][    C0] RIP: 0010:lock_acquire+0x1ea/0x3f0
[ 2490.093017][    C0] Code: 7c 08 00 00 00 00 00 00 48 c1 e8 03 80 3c 10 00 0f 85 c7 01 00 00 48 83 3d 82 da 3a 07 00 0f 84 3b 01 00 00 48 8b 7d c8 57 9d <0f> 1f 44 00 00 48 8d 65 d8 5b 41 5c 41 5d 41 5e 41 5f 5d c3 65 8b
[ 2490.093021][    C0] RSP: 0018:ffff8880899d7c20 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
[ 2490.093032][    C0] RAX: 1ffffffff1124e16 RBX: ffff88805dab2500 RCX: 000000000000578b
[ 2490.093038][    C0] RDX: dffffc0000000000 RSI: 0000000000000001 RDI: 0000000000000286
[ 2490.093044][    C0] RBP: ffff8880899d7c68 R08: 000000005bf34abb R09: ffff88805dab2da0
[ 2490.093049][    C0] R10: ffff88805dab2d80 R11: ffff88805dab2500 R12: ffffffff889bac00
[ 2490.093055][    C0] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 2490.093060][    C0]  ? __x64_sys_delete_module+0x188/0x4a0
[ 2490.093063][    C0]  __mutex_lock+0xf7/0x1310
[ 2490.093068][    C0]  ? __x64_sys_delete_module+0x188/0x4a0
[ 2490.093072][    C0]  ? __x64_sys_delete_module+0x188/0x4a0
[ 2490.093077][    C0]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[ 2490.093082][    C0]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[ 2490.093086][    C0]  ? mutex_trylock+0x1e0/0x1e0
[ 2490.093090][    C0]  ? __phys_addr_symbol+0x30/0x70
[ 2490.093094][    C0]  ? __sanitizer_cov_trace_cmp8+0x18/0x20
[ 2490.093099][    C0]  ? __check_object_size+0x3d/0x42f
[ 2490.093103][    C0]  ? check_stack_object+0x114/0x160
[ 2490.093108][    C0]  ? __sanitizer_cov_trace_switch+0x49/0x80
[ 2490.093112][    C0]  ? __check_object_size+0x3d/0x42f
[ 2490.093116][    C0]  ? security_capable+0x9b/0xd0
[ 2490.093120][    C0]  mutex_lock_interruptible_nested+0x16/0x20
[ 2490.093129][    C0]  ? mutex_lock_interruptible_nested+0x16/0x20
[ 2490.093133][    C0]  __x64_sys_delete_module+0x188/0x4a0
[ 2490.093138][    C0]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[ 2490.093143][    C0]  ? __ia32_sys_delete_module+0x4a0/0x4a0
[ 2490.093147][    C0]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[ 2490.093151][    C0]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[ 2490.093155][    C0]  ? do_syscall_64+0x26/0x670
[ 2490.093159][    C0]  ? do_syscall_64+0x26/0x670
[ 2490.093164][    C0]  ? lockdep_hardirqs_on+0x418/0x5d0
[ 2490.093168][    C0]  ? trace_hardirqs_on+0x67/0x230
[ 2490.093172][    C0]  do_syscall_64+0x103/0x670
[ 2490.093176][    C0]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 2490.093192][    C0] RIP: 0033:0x20000509
[ 2490.093204][    C0] Code: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 99 4a 2a e9 2c c0 4c 0f 05 <bf> 00 03 00 20 c4 a3 7b f0 c5 bf 41 e2 e9 c4 22 e9 aa bb 3c 00 00
[ 2490.093208][    C0] RSP: 002b:00007f3a3269dbd8 EFLAGS: 00000a83 ORIG_RAX: 00000000000000b0
[ 2490.093218][    C0] RAX: ffffffffffffffda RBX: 0000000000000009 RCX: 0000000020000509
[ 2490.093223][    C0] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000020000300
[ 2490.093229][    C0] RBP: 0000000000000030 R08: 0000000000000005 R09: 0000000000000006
[ 2490.093234][    C0] R10: 0000000000000007 R11: 0000000000000a83 R12: 000000000000000b
[ 2490.093239][    C0] R13: 000000000000000c R14: 000000000000000d R15: 00000000ffffff
[ 2490.093308][    C0] workqueue events_long: flags=0x0
[ 2490.097570][    C1]  ? trace_hardirqs_on+0x67/0x230
[ 2490.097584][    C1]  ? kasan_check_read+0x11/0x20
[ 2490.097603][    C1]  ? _raw_spin_unlock_irqrestore+0xa4/0xe0
[ 2490.103477][    C0]   pwq 0: cpus=0 node=0 flags=0x0 nice=0 active=4/256
[ 2490.108147][    C1]  ? __sanitizer_cov_trace_const_cmp1+0x1a/0x20
[ 2490.112880][    C0]     pending: br_fdb_cleanup, br_fdb_cleanup, br_fdb_cleanup, br_fdb_cleanup
[ 2490.119814][    C1]  ? __kthread_parkme+0xfb/0x1b0
[ 2490.124748][    C0] workqueue events_power_efficient: flags=0x80
[ 2490.147964][    C1]  kthread+0x357/0x430
[ 2490.147986][    C1]  ? wait_rcu_exp_gp+0x50/0x50
[ 2490.152726][    C0]   pwq 0: cpus=0 node=0 flags=0x0 nice=0 active=1/256
[ 2490.155056][    C1]  ? kthread_cancel_delayed_work_sync+0x20/0x20
[ 2490.162045][    C0]     pending: neigh_periodic_work
[ 2490.169153][    C1]  ret_from_fork+0x3a/0x50
[ 2490.173309][    C0] workqueue rcu_gp: flags=0x8
[ 2490.180316][    C1] NMI backtrace for cpu 1
[ 2490.180333][    C1] CPU: 1 PID: 14558 Comm: kworker/1:5 Not tainted 5.1.0+ #4
[ 2490.180348][    C1] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[ 2490.186682][    C0]   pwq 2: cpus=1 node=0 flags=0x0 nice=0 active=1/256
[ 2490.194892][    C1] Workqueue: rcu_gp process_srcu
[ 2490.197202][    C0]     in-flight: 14558:process_srcu
[ 2490.202383][    C1] Call Trace:
[ 2490.212532][    C0] workqueue mm_percpu_wq: flags=0x8
[ 2490.214830][    C1]  <IRQ>
[ 2490.214848][    C1]  dump_stack+0x172/0x1f0
[ 2490.214868][    C1]  nmi_cpu_backtrace.cold+0x63/0xa4
[ 2490.220910][    C0]   pwq 0: cpus=0 node=0 flags=0x0 nice=0 active=1/256
[ 2490.223257][    C1]  ? lapic_can_unplug_cpu.cold+0x38/0x38
[ 2490.225558][    C0]     pending: vmstat_update
[ 2490.232415][    C1]  nmi_trigger_cpumask_backtrace+0x1be/0x236
[ 2490.234736][    C0] workqueue writeback: flags=0x4e
[ 2490.240176][    C1]  arch_trigger_cpumask_backtrace+0x14/0x20
[ 2490.245185][    C0]   pwq 4: cpus=0-1 flags=0x4 nice=0 active=2/256
[ 2490.250310][    C1]  rcu_dump_cpu_stacks+0x183/0x1cf
[ 2490.255396][    C0]     pending: wb_workfn, wb_workfn
[ 2490.259998][    C1]  rcu_sched_clock_irq.cold+0x4d1/0xbfd
[ 2490.265791][    C0] workqueue kblockd: flags=0x18
[ 2490.271224][    C1]  ? raise_softirq+0x11f/0x310
[ 2490.276840][    C0]   pwq 1: cpus=0 node=0 flags=0x0 nice=-20 active=1/256
[ 2490.282372][    C1]  update_process_times+0x32/0x80
[ 2490.287801][    C0]     pending: blk_mq_timeout_work
[ 2490.292850][    C1]  tick_sched_handle+0xa2/0x190
[ 2490.297438][    C0] workqueue krxrpcd: flags=0x0
[ 2490.302320][    C1]  tick_sched_timer+0x47/0x130
[ 2490.304655][    C0]   pwq 0: cpus=0 node=0 flags=0x0 nice=0 active=1/1
[ 2490.309396][    C1]  __hrtimer_run_queues+0x33e/0xde0
[ 2490.314392][    C0]     pending: rxrpc_peer_keepalive_worker
[ 2490.319526][    C1]  ? tick_sched_do_timer+0x1b0/0x1b0
[ 2490.324662][    C0]     delayed: rxrpc_peer_keepalive_worker, rxrpc_peer_keepalive_worker
[ 2490.330293][    C1]  ? hrtimer_start_range_ns+0xc80/0xc80
[ 2490.335059][    C0] workqueue bat_events: flags=0xe000a
[ 2490.340059][    C1]  ? __sanitizer_cov_trace_cmp4+0x16/0x20
[ 2490.340082][    C1]  ? ktime_get_update_offsets_now+0x2d9/0x440
[ 2490.344847][    C0]   pwq 4: cpus=0-1 flags=0x4 nice=0 active=1/1
[ 2490.349686][    C1]  hrtimer_interrupt+0x314/0x770
[ 2490.354420][    C0]     pending: batadv_nc_worker
[ 2490.359271][    C1]  smp_apic_timer_interrupt+0x120/0x570
[ 2490.364358][    C0]     delayed: batadv_nc_worker, batadv_nc_worker, batadv_nc_worker, batadv_nc_worker, batadv_nc_worker, batadv_tt_purge, batadv_bla_periodic_work, batadv_dat_purge, batadv_tt_purge, batadv_dat_purge, batadv_bla_periodic_work, batadv_dat_purge, batadv_bla_periodic_work, batadv_dat_purge, batadv_bla_periodic_work
[ 2490.369473][    C1]  apic_timer_interrupt+0xf/0x20
[ 2490.375898][    C0] pool 2: cpus=1 node=0 flags=0x0 nice=0 hung=299s workers=6 idle: 12566 12567 29830 25159 2991
[ 2490.378172][    C1]  </IRQ>
[ 2491.704393][    C1] RIP: 0010:preempt_count_add+0x0/0x1b0
[ 2491.709934][    C1] Code: f5 48 c7 c2 60 cf 6a 87 be 54 02 00 00 48 c7 c7 e0 c5 6a 87 c6 05 5b 05 0e 08 01 e8 b5 05 0a 00 c9 c3 0f 1f 84 00 00 00 00 00 <48> b8 00 00 00 00 00 fc ff df 55 48 89 e5 41 54 41 89 fc 53 48 c7
[ 2491.729529][    C1] RSP: 0018:ffff888092ea7ba8 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
[ 2491.737935][    C1] RAX: 0000000080000000 RBX: 000005377ba747a6 RCX: 0000000000000000
[ 2491.745899][    C1] RDX: 0000000000000004 RSI: ffffffff8334662c RDI: 0000000000000001
[ 2491.753862][    C1] RBP: ffff888092ea7bd0 R08: ffff8880a0c4e080 R09: 0000000000000040
[ 2491.761822][    C1] R10: 0000000000000040 R11: ffffffff88a42a67 R12: 000005377ba72c70
[ 2491.769786][    C1] R13: 0000000000000001 R14: 0000000000002ced R15: 0000000000000abd
[ 2491.777827][    C1]  ? debug_smp_processor_id+0x3c/0x280
[ 2491.783292][    C1]  ? delay_tsc+0x3d/0xc0
[ 2491.787543][    C1]  __const_udelay+0x5f/0x80
[ 2491.792044][    C1]  try_check_zero+0x201/0x330
[ 2491.796724][    C1]  process_srcu+0x329/0xe20
[ 2491.801237][    C1]  process_one_work+0x98e/0x1790
[ 2491.806200][    C1]  ? pwq_dec_nr_in_flight+0x320/0x320
[ 2491.811570][    C1]  ? lock_acquire+0x16f/0x3f0
[ 2491.816258][    C1]  worker_thread+0x98/0xe40
2033/05/18 04:02:34 Manager.Poll call failed: connection is shut down
[ 2491.820767][    C1]  ? trace_hardirqs_on+0x67/0x230
[ 2491.825797][    C1]  kthread+0x357/0x430
[ 2491.829865][    C1]  ? process_one_work+0x1790/0x1790
[ 2491.835067][    C1]  ? kthread_cancel_delayed_work_sync+0x20/0x20
[ 2491.841310][    C1]  ret_from_fork+0x3a/0x50

修正量としては僅かなのですが、効果は絶大で、メッセージが混在することにより問題に関連したメッセージを抽出することができずに捨てられてしまうというケースが激減しました。(1日平均180件だったのが、1日1件未満になりました。)

たったこれだけの改善なのですが、そこに至るまでの試行錯誤を見てみましょう。


2.1 printk() に求められているものとは?

通常の状態であれば、 printk() により出力されたメッセージは、ユーザランドで動作している syslog デーモンによって読み出され、 /var/log/messages などのログファイルに保存されます。

しかし、ロックアップやクラッシュなどの問題が発生した場合、ユーザランドで動作しているプロセスが printk() により出力されたメッセージを読みだしてくれることを期待することはできません。

そのため、 printk() に1番求められていることは、問題が発生した時に、問題に関連したカーネルメッセージを確実にコンソールに出力できるという「信頼性」です。信頼性を確保するために、 printk() による出力は「同期処理」(コンソールへの出力が完了するのを待つ)であることが原則です。(デッドロックを回避するために、やむを得ず「非同期処理」にするケースがありますが、それについては第3章で紹介します。)

printk() に2番目に求められていることは、システムをロックアップさせないことです。 printk() の処理は重たいため、無暗に呼び出すと、システムをロックアップさせてしまうことがあります。ロックアップを回避するために、 printk() による出力処理を原則として「非同期処理」にする試みもされてきましたが、「信頼性」との両立ができないため、採用されていません。(これについての詳細は、第3章で紹介します。)

printk() に3番目に求められていることは、出力されたカーネルメッセージが読めることです。 printk() が同時に呼び出された場合、(カーネルがクラッシュしないように作られているという点ではスレッドセーフなのですが、メッセージの出力が混在してしまうことが避けられないという点では)スレッドセーフではないため、サンプルで示したように、とても汚くなってしまうことがあります。


2.2 複数行分のメッセージをバッファリングする試み(2017年4月~)

printk() がスレッドセーフではないことに起因してメッセージが混在してしまうという問題を緩和するために、 FILE *fp に相当するバッファの配列を用意して、コンテキストを自動的に判断しながら各バッファの使用中/未使用を切り替えることにより、 printk() を呼ぶ可能性のある全ての関数に対して FILE *fp に相当する引数を渡さずに済ませるという方法が提案されました。

しかし、この提案に対して、 Linus Torvalds さんは「様々な理由によりネストが発生するため、コンテキストを自動的に判断して切り替えるという方法は期待通りに動かない」と反対しました。そして、代わりに、「カーネルスタックから80バイト(=1行分)のバッファを割り当てて、バッファリングを行ってから、 printk() を呼んでみてはどうか」という提案がされました。

しかし、この方法では、1行分しかバッファリングできないため、 OOM killer のように長いメッセージを複数行に渡ってバッファリングすることができません。そして、この案は立ち消えになりました。


2.3 メッセージ本文中にコンテキスト情報を埋め込む試み(2018年4月~)

syzbot によるテストが本格的に行われるようになり、メッセージが混在してしまうという問題について「何とかしたい」という状況が発生しました。そして、今度は、バッファを切り替える方法ではなく、メッセージ本文中に「誰が」という情報を埋め込む方法が提案されました。

この提案に対しては、「(コンテキストを)メッセージ本文中に埋め込む方法」「 printk_log 構造体を拡張して(コンテキストを)保持する方法」「(コンテキストを出力するための) printf() 向けの書式文字列を追加する方法」の3通りの実現方法が示されました。また、コンテキストとしてどのような情報を埋め込むべきかという議論もなされました。

コンテキストとして埋め込む情報の候補としては、「 printk() を呼び出したCPUの番号」「現在の割り込みコンテキスト (SoftIRQ or HardIRQ or NMI) 」「プリエンプションや割り込みが有効かどうか」「コンテキストスイッチされた回数」「スレッドの状態」「未処理のシグナルの状態」「メモリの使用状況」「 cgroup の情報」などが挙げられました。しかし、これらは特定の状況下でのみ役に立つ情報であり、混在してしまったメッセージを分離するための情報とは区別すべきと判断しました。

printk_log 構造体に変更を加えて保持する方法は、 printk_log 構造体にアクセスする必要のあるユーザランドのプログラム( crash コマンドなど、カーネルのデバッグのために用いられるツール)が正常に動作しなくなる可能性があります。そのため、ユーザランドのプログラムが動作しなくなることを忌み嫌う Linux の文化からは受け入れてもらうことが難しいと考えました。

しかし、むしろ、メッセージ本文中に埋め込む方がおこがましいという反応が返ってきました。そして、他の方法として、コンテキスト情報を拡張レコードデータに保存することについても議論されました。 printk() は、コンソールに出力されるメッセージ本文とは別に、拡張レコードデータとして「名前=値」という形式の付加情報も扱えるようになっています。しかし、拡張レコードデータに対応しているのが netconsole のみであったため、クラッシュが発生する瞬間のメッセージを syzbot が取得するために netconsole や syslog デーモンなどに頼ることはできないという結論になり、立ち消えになりました。

人間にとっては、多くの場合、1行より長いメッセージ(あるいは、同時に呼び出された printk() により複数行に分割されてしまった1行分のメッセージ)でも、ある程度の内容を読み取ることができます。しかし、それを自動で行いたい syzbot にとっては、行頭にコンテキスト情報を埋め込むことにより識別できるようになっていないと、まったく内容を読み取ることができない訳です。


2.4 1行分のメッセージをバッファリングする試み(2018年6月~)

メッセージが混在してしまうという問題について「何とかしたい」けれども「何もできていない」という状況が続く中、今度は、1行分のメッセージをバッファリングする方法についての議論が起こりました。

複数回に分けて出力される1行分のメッセージをバッファリングしてから出力しようとする printk(KERN_CONT) は、バッファリングできなかった場合に単語単位で改行されてしまうため、自動でパース処理を行いたい syzbot にとっては最悪の敵です。そのため、重要な出力を行う個所から printk(KERN_CONT) を除去できないかという提案がされました。

その提案に対しては「いいね」という反応でした。

しかし、実際のところ、 printk(KERN_CONT) は OOM killer を含めて様々な箇所で使われているため、この問題への影響度合いを判断することは難しいという現実がありました。

そこで、改行文字を見つけるかバッファが満杯になったら自動的にフラッシュする方法でバッファリングを行うパッチと、その機能を利用する個所のサンプルを提案してみました。

すると、 show_opcodes() 関数に関しては、そのような機能を利用せずとも printk(KERN_CONT) を除去できることが判明し、 show_opcodes() 関数に関しては Linux 4.19-rc1 で修正されました。


2.5 再び1行分のメッセージをバッファリングする試み(2018年9月~)

printk() のメンテナである Sergey Senozhatsky さんが一段落(?)して戻ってきたことにより、議論が再開されました。今度は、80バイトのバッファをカーネルスタックから割り当てて、バッファが満杯になったらフラッシュせずに切り詰めるという方法でバッファリングを行うパッチが提案されました。

すると、「これは(既に存在している) seq_buf 構造体と同じなのでは?」という反応がありました。

しかし、熊猫としては、 OOM killer のように80バイトよりも長いメッセージを出力する個所もあることから、メッセージが切り詰められないように必要十分なバッファサイズを計算してもらうのは非現実的であると考えました。そして、 FILE *fp に相当するバッファの配列を用意して、呼び出し側が明示的に各バッファの使用中/未使用を切り替えることにより、 printk(KERN_CONT) を呼ぶ可能性のある全ての関数に対して FILE *fp に相当する引数を渡せるようにするという方法を提案しました。

それに対して、80バイトでは足りない場合に備えて、1024バイトも選べるようにするという提案が行われました。また、バッファの配列を静的に割り当てる方法は、いくつ割り当てるのが妥当かを判断できないのではというコメントがありました。

しかし、CPUの数が多くても、同時に処理できる量には限りがあるので、CPUの数に比例した数のバッファを割り当てずとも、16個で十分なのではないかと考えました。また、 printk(KERN_CONT) では複数回に分けて1024バイト以上を出力できるため、切り詰められるのは困ると考えました。

その後、メーリングリストを使わないやり取りが少しありました。その中で、コンテキスト情報を拡張レコードデータとして保存する方法で実現するために、拡張レコードデータを通常のコンソールに出力することができないかという話がありました。しかし、通常のコンソールに出力されたメッセージにはレコードの境界を示すマーカーが存在しないことにより、レコード単位ではなく行単位でしかパースできないため、全ての行にコンテキスト情報を埋め込む必要があります。そのため、コンテキスト情報を拡張レコードデータとして通常のコンソールに出力することは現実的ではないという結論になりました。

また、メーリングリストを使わないやり取りの中で、複数個の cont 構造体を用意して切り替えるという方法が提案されました。しかし、クラッシュ発生時にバッファリング途中のデータをフラッシュできないことにより重要な手がかりを失う(問題を解決する機会を逃してしまう)可能性について判断することができませんでした。「バッファリングを行うことで、クラッシュ発生時のバッファの内容に重要な手がかりが含まれているかどうかは五分五分で判断できない」という懸念に対し、「(1行分のバッファリングであれば)改行文字が出現次第フラッシュされるので、重要な手がかりがフラッシュされない可能性は低い筈だ」と考えました。そして、結論としては、現時点では

という「最小限の変更」に留めておくのが妥当なのではないかということになりました。そして、1行分のバッファリングを行うための API の導入を目指すことになりました。


2.6 再挑戦(2018年10月~)

今までに明らかになった制約事項と、メーリングリストを使わないやり取りで得られた結論とをまとめて、 Linus Torvalds さんの「コンテキスト情報をコンソールの出力に埋め込むことは避けるべきだ」というコメントに反してでも、コンテキスト情報をコンソールの出力に埋め込むための準備を進めようとしました。

すると、今度は、呼び出し側が明示的に各バッファの使用中/未使用を切り替える方法では、使い終わった後に未使用状態に戻すための呼び出しを忘れてしまうることで、全てのバッファが使用中になってしまうのではないかという懸念が Petr Mladek さんから示されました。そのため、バッファの数を指定できるようにしたり、誰がバッファを使用しているのかを追跡できるようにしたりすることが検討されました。

そして、次のバージョンでは、誰がバッファを使用しているのかを追跡するためのカーネルコンフィグが追加されました。

すると、実装に関する細かなチェックが行われました。しかし、あまりにもデバッグのための機能についてのコメントが多くなってしまったため、一旦デバッグ機能を削除することにしました。

そして、次のバージョンでは、 API の実際の利用例として、メモリの空き状況を示すための show_free_areas() 関数の出力と、 lockdep のメッセージ出力をバッファリングするためのパッチを一緒に提案しました。

すると、コメントが大爆発してしまいました。

そして、結論としては、「 printk() の呼び出し側の修正を強制する方法は避けるべきである(つまり、バッファリングをしてもらうように printk() の呼び出し側に頼むべきではない)」ということになりました。


2.7 最小限のコンテキスト情報の埋め込みへ(2018年11月~)

syzbot にとっての最悪の敵と考えられた printk(KERN_CONT) を巡って、思いっきり寄り道をしてしまいましたが、やっと結論が出たので、コンテキスト情報を埋め込むパッチに到達することができました。埋め込む情報は、「誰が」を識別するのに必要最小限の内容に絞りました。

割り込みコンテキストの種類 (SoftIRQ or HardIRQ or NMI) も埋め込むことが有用かどうかは判断できないため、とりあえずはプロセスコンテキストと割り込みコンテキストだけを区別し、前者にはスレッドIDを、後者にはCPU番号のみを埋め込むようにしました。これは、プロセスコンテキストでは、必要に応じて他のCPUへ制御を移行できるのに対して、割り込みコンテキストでは、その割り込み処理が発生したCPU上でのみ処理が行われるという性質があるからです。

そして、埋め込む際の書式についての議論を行い、クリーンアップやバグの修正を経て、遂に、コンテキスト情報を埋め込むためのパッチが Linux 5.1-rc1 でマージされたのでした。


第3章 カーネルメッセージ出力によるロックアップを回避するための試行錯誤について


3.1 コンソールへの出力処理は非常に遅いことについて

printk() はコストが高い(コンソールへの出力処理によりストールの原因になることもある)ので、いかにして必要十分な情報を取得できるかが重要になります。

世の中には400Gbps(50,000,000バイト/秒)の処理速度を持つイーサネット( https://lwn.net/Articles/787754/ )なんていう話も聞こえますが、 printk() がメッセージを出力する先であるコンソールの中には、9,600bps(1,200バイト/秒)( https://lkml.kernel.org/r/eb3d9058-a623-3c10-68e2-f11498a7c174@arista.com )とか、ひどい場合には1,200bps(150バイト/秒)とかいう処理速度でしか正常に動作しないという環境も存在しています。そのような環境では、コンソールに出力されたメッセージをネットワーク経由で取得するための netconsole を使用することもあります。しかし、 syzbot の場合、ネットワーク関連の処理もテストの対象であり、場合によってはネットワークインタフェースが利用不可能な状況でメッセージが出力されることもあります。また、自動化する上で、カーネルメッセージを送信する側の仮想マシンとは別に、カーネルメッセージを受信する側の仮想マシンも用意する必要があるというのでは、扱いにくくて仕方がありません。 syzbot の場合、 netconsole などの外部のデバイスに頼ることなく、仮想マシンに備わっているコンソールからカーネルメッセージを取得できることが必要になります。

カーネルがコンソールに出力するメッセージには、ダイイングメッセージのような、これが無いと何が起きたのかが手がかりが残らないという重要なメッセージが含まれる可能性があるため、 printk() を呼び出す側は、重要ではないメッセージの洪水によりバッファが満杯になって重要なメッセージが失われることが無いように十分に配慮することが求められます。

syzbot により報告されたレポートのいくつかは、 printk() を頻繁に呼び出しすぎたことが原因と考えられます。

もし、 printk() の呼び出しを間引くことが有効な対処法である場合、 ratelimit という方法が使われます。なお、 ratelimit という方法がうまく機能しないケースについては、ここで触れるには長すぎるため、第4章で扱います。


3.2 printk() が依存するロックの問題について

第1章で、問題を検知したことを示すカーネルメッセージのサンプルを紹介しましたが、実は、メッセージを表示できることが当たり前という訳ではありません。デッドロックやロックアップなど、問題が発生した時に、問題の影響を避けながらメッセージを表示する必要があります。いついかなる状態でもメッセージを出力できるようにすることを目標に、複雑な綱渡りをしています。

例えば、何かのメッセージを出力するために printk() を呼び出した際に、 printk() の処理の中で問題が発生することで、再帰的に printk() が呼ばれてしまうケースがあります。そのようなコンテキストでは、 printk-safe という、通常の printk() が使うためにシステム全体で共有するバッファ領域ではなく、CPU毎に割り当てられるテンポラリなバッファに一時保存し、後でシステム全体で共有するバッファ領域にコピーされるタイミングで出力することで問題を回避しています。同様に、NMIというのは「マスク不可能な割り込み処理」であることから、 printk() が依存するロックを保持しているタイミングで発生してしまう可能性があります。そのようなコンテキストでも、 printk-nmi という、CPU毎に割り当てられるテンポラリなバッファに一時保存し、後でシステム全体で共有するバッファ領域にコピーされるタイミングで出力することで問題を回避しています。

しかし、そのような綱渡りをしていても、 printk() が依存するロックによりデッドロックが発生してしまう可能性が残っており、実際に syzbot の行っているファジングテストにより、デッドロックの可能性が報告されています。

なお、現実にどれくらいデッドロックが発生しているのかは判りません。なぜなら、カーネルメッセージを出力するために使われる printk() の処理で問題が発生しても、カーネルメッセージを出力することができないので、メモリダンプを取得して解析してみる以外に、確認する方法が無いからです。


3.3 コンソールの出力処理を原則として「非同期処理」にする試みについて

上述した2つの問題を解決するために、出力処理を専用のカーネルスレッドに任せてしまうという試みがされてきました。しかし、スケジューリング可能な状態で動作するカーネルスレッドがスケジューリングされなくなる状態(割り込みコンテキスト内でのロックアップなど)に陥ってしまった場合、「いざというときにきちんと機能するように」することができず、まだ採用されていません。

最初は、(カーネルスレッドの一種である)ワークキューを用いて出力処理を行う方法が提案されました。しかし、必要に応じて動的に生成されるワークキューは、メモリが枯渇していたり、ストール状態が発生したりすると動作しないという制約があるため、ワークキューではなく専用のカーネルスレッドを使うほうが良いというコメントがありました。

ワークキューを使うことにより依存関係や処理が複雑になってしまうのは「いざというときにきちんと機能するように」することが求められる printk() にとって望ましくないという結論になり、ワークキューではなく専用のカーネルスレッドを用いる方法が提案されました。

そして、細かな変更を重ねて、マージへ向けた実質的な提案が始まりました。

最後のスレッドである v12 は2016年7月13日まで続きましたが、結局、採用されませんでした。最後まで、ストールやデッドロックの懸念が残ってしまったようです。

2016年のカーネルサミットで、どんな議論が交わされたのでしょうね?熊猫は、メモリ管理の闇を巡る戦いで忙しく、 printk() の話まで追いかけている余裕がありませんでした。

2017年のカーネルサミットでの議論を経て、 printk() の出力が同期処理であることに起因したストールへの対処法についての議論が行われました。 printk() を呼び出したスレッドがコンソールへの出力を行っている間に、別のスレッドが printk() を呼び出した場合、そのタイミングでコンソールへの出力を行っていたスレッドが、別のスレッドが生成したメッセージについても出力するという挙動になっていることにより、特定のスレッドが長時間に渡って printk() の呼び出しから復帰できなくなるという問題があったためです。

この問題への対処方法として、 printk() を呼び出したスレッドがコンソールへの出力を行っている間に、別のスレッドが printk() を呼び出した場合、コンソールへの出力を行っていたスレッドは、 printk() を呼び出した別のスレッドへコンソールへの出力処理を移譲するという変更が提案されました。そして、

というパッチが Linux 4.16-rc1 にマージされたことにより、多数のスレッドが同時に printk() を呼び出し続けたとしても、その中の1個のスレッドだけが printk() の呼び出しから復帰できなくなるという状況を回避できるようになりました。

現在は、デッドロックを回避するために、 printk() およびコンソールの処理を全面的に書き直そうという提案がされています。

また、ストールを回避するために、コンソール毎に、出力対象とするログレベルを設定できるようにしようという提案もされています。

また、明示的に指定された場合だけ非同期に出力されるようにする提案もされています。この提案は、第4章で説明する問題を緩和するためのものです。


第4章 メモリ不足と問題報告メッセージとの狭間で・・・


セキュリティ・キャンプ2016の講義資料では、メモリ管理の闇( OOM killer )を巡る体験談について扱いました。2017年11月末時点までの出来事を振り返った動画にあるように、 OOM killer を巡る戦いは現在も続いています。

syzbot といえども全ての処理パターンをテストできる訳ではありません。競合状態に起因した問題を見つけるためには、同じ処理を様々なタイミングで繰り返しテストする必要があります。そのため、 OOM killer のように、テストのためのプロセスが強制終了させられてしまう事象を試すのは難しいという制約があります。

しかし、 OOM killer と printk() との間には、「空きメモリに関する状況が悪くなればなるほど、より多くのカーネルメッセージを printk() を用いて出力しなければならなくなる」という、避けて通れない繋がりがあります。

OOM killer が発動すると、メモリを要求したプロセスの情報、空きメモリの状況、強制終了の対象となりうるプロセスの一覧、実際に強制終了させられたプロセスの情報など、大量のカーネルメッセージが出力されます。強制終了の対象として表示されうるプロセスの一覧の最大値は、その時点で動作していた全てのユーザモードプロセス数となるので、例えば3万個のユーザモードプロセスが動作していたら、3万行を出力してしまう訳です。強制終了の対象となりうるプロセスを一覧表示する処理はRCUロックを保持した状態で呼ばれるので、RCUストール警告メッセージが出力されることになります。

[  104.979220] sysrq: SysRq : Manual OOM execution
[  104.983729] kworker/4:1 invoked oom-killer: gfp_mask=0x6000c0(GFP_KERNEL), order=-1, oom_score_adj=0
[  104.986193] CPU: 4 PID: 67 Comm: kworker/4:1 Tainted: G    B           T 5.0.0 #1
[  104.988251] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[  104.991013] Workqueue: events moom_callback
[  104.992096] Call Trace:
[  104.992706]  dump_stack+0x9a/0xf0
[  104.993517]  dump_header+0xff/0x9d1
[  104.994369]  ? ___ratelimit+0x1d3/0x3b3
[  104.995374]  oom_kill_process.cold.32+0xb/0x5dc
[  104.996467]  ? oom_badness+0x41a/0x570
[  104.997379]  ? check_flags.part.39+0x400/0x400
[  104.998757]  ? oom_evaluate_task+0x2d1/0x460
[  105.000156]  out_of_memory+0x5d5/0x1020
[  105.001351]  ? debug_object_deactivate.part.5+0x1cb/0x340
[  105.002692]  ? oom_killer_disable+0x1f0/0x1f0
[  105.003744]  ? sched_clock+0x5/0x10
[  105.004732]  moom_callback+0xdf/0x150
[  105.005708]  ? sysrq_handle_term+0x50/0x50
[  105.006813]  ? strscpy+0x8a/0x2f0
[  105.007797]  process_one_work+0xb6a/0x1d10
[  105.008848]  ? pwq_dec_nr_in_flight+0x2d0/0x2d0
[  105.009949]  worker_thread+0x82/0xfa0
[  105.011020]  ? __kthread_parkme+0xb1/0x180
[  105.012012]  ? process_one_work+0x1d10/0x1d10
[  105.013065]  kthread+0x313/0x3d0
[  105.013956]  ? kthread_create_on_node+0xc0/0xc0
[  105.015110]  ret_from_fork+0x24/0x30
[  105.016607] Mem-Info:
[  105.017360] active_anon:145572 inactive_anon:2983 isolated_anon:0
[  105.017360]  active_file:31976 inactive_file:92827 isolated_file:0
[  105.017360]  unevictable:0 dirty:425 writeback:0 unstable:0
[  105.017360]  slab_reclaimable:23192 slab_unreclaimable:59308
[  105.017360]  mapped:51677 shmem:3220 pagetables:9673 bounce:0
[  105.017360]  free:338001 free_pcp:2165 free_cma:0
[  105.027003] Node 0 active_anon:582288kB inactive_anon:11932kB active_file:127904kB inactive_file:371308kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:206708kB dirty:1700kB writeback:0kB shmem:12880kB shmem_thp: 0kB shmem_pmdmapped: 0kB anon_thp: 126976kB writeback_tmp:0kB unstable:0kB all_unreclaimable? yes
[  105.034843] Node 0 DMA free:15872kB min:364kB low:452kB high:540kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB writepending:0kB present:15988kB managed:15904kB mlocked:0kB kernel_stack:0kB pagetables:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[  105.041662] lowmem_reserve[]: 0 2623 2861 2861
[  105.042855] Node 0 DMA32 free:1316368kB min:61636kB low:77044kB high:92452kB active_anon:567524kB inactive_anon:10108kB active_file:108452kB inactive_file:348264kB unevictable:0kB writepending:1696kB present:3129152kB managed:2686648kB mlocked:0kB kernel_stack:15392kB pagetables:36488kB bounce:0kB free_pcp:7740kB local_pcp:584kB free_cma:0kB
[  105.051232] lowmem_reserve[]: 0 0 237 237
[  105.052337] Node 0 Normal free:19484kB min:18116kB low:19508kB high:20900kB active_anon:14764kB inactive_anon:1824kB active_file:19520kB inactive_file:22976kB unevictable:0kB writepending:4kB present:1048576kB managed:243172kB mlocked:0kB kernel_stack:8256kB pagetables:2204kB bounce:0kB free_pcp:924kB local_pcp:84kB free_cma:0kB
[  105.059850] lowmem_reserve[]: 0 0 0 0
[  105.060954] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 2*64kB (U) 1*128kB (U) 1*256kB (U) 0*512kB 1*1024kB (U) 1*2048kB (M) 3*4096kB (M) = 15872kB
[  105.064293] Node 0 DMA32: 920*4kB (UM) 595*8kB (UM) 354*16kB (UME) 223*32kB (UM) 73*64kB (UM) 14*128kB (UME) 3*256kB (UM) 2*512kB (M) 3*1024kB (UM) 1*2048kB (M) 313*4096kB (M) = 1316664kB
[  105.069281] Node 0 Normal: 37*4kB (UM) 15*8kB (UME) 229*16kB (UME) 276*32kB (UME) 53*64kB (UM) 9*128kB (U) 7*256kB (UM) 1*512kB (M) 0*1024kB 0*2048kB 0*4096kB = 19612kB
[  105.073382] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[  105.075718] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  105.077866] 128023 total pagecache pages
[  105.078974] 0 pages in swap cache
[  105.079818] Swap cache stats: add 0, delete 0, find 0/0
[  105.081096] Free swap  = 0kB
[  105.082347] Total swap = 0kB
[  105.083224] 1048429 pages RAM
[  105.083989] 0 pages HighMem/MovableOnly
[  105.085179] 311998 pages reserved
[  105.086077] 0 pages cma reserved
[  105.086902] 0 pages hwpoisoned
[  105.087788] Tasks state (memory values in pages):
[  105.089012] [  pid  ]   uid  tgid total_vm      rss pgtables_bytes swapents oom_score_adj name
[  105.091405] [   4253]     0  4253    10137     1354   122880        0             0 systemd-journal
[  105.093895] [   4270]     0  4270    29159      684   135168        0             0 lvmetad
[  105.096031] [   4281]     0  4281    10946     1036   114688        0         -1000 systemd-udevd
[  105.099012] [   8141]     0  8141    13882      607   131072        0         -1000 auditd
[  105.101736] [   8143]     0  8143    21140      462    77824        0             0 audispd
[  105.104138] [   8146]     0  8146    13909      813   151552        0             0 sedispatch
[  105.106494] [   8168]     0  8168    24920     2557   192512        0             0 VGAuthService
[  105.108796] [   8169]     0  8169     5423      714    90112        0             0 irqbalance
[  105.111112] [   8170]     0  8170   107652     2774   348160        0             0 ModemManager
[  105.113473] [   8171]     0  8171   113334     2535   385024        0             0 udisksd
[  105.116128] [   8172]    32  8172    17318      843   172032        0             0 rpcbind
[  105.118667] [   8173]     0  8173     6610      728    90112        0             0 systemd-logind
[  105.120959] [   8175]     0  8175     6110      973    98304        0             0 smartd
[  105.123181] [   8176]   998  8176     2146      453    65536        0             0 lsmd
[  105.125409] [   8184]     0  8184     5510      577    86016        0             0 systemd-machine
[  105.127808] [   8186]     0  8186    80054     2935   290816        0             0 vmtoolsd
[  105.129948] [   8187]     0  8187    57062     2426   278528        0             0 abrtd
[  105.132562] [   8191]    70  8191    18079     1026   180224        0             0 avahi-daemon
[  105.135368] [   8193]     0  8193    56433     2146   278528        0             0 abrt-watch-log
[  105.138524] [   8196]     0  8196    22627     1394   212992        0             0 rngd
[  105.140736] [   8200]   999  8200   156670     4818   294912        0             0 polkitd
[  105.143291] [   8201]   172  8201    49700      938   159744        0             0 rtkit-daemon
[  105.145853] [   8206]     0  8206    99089     1749   217088        0             0 accounts-daemon
[  105.148396] [   8207]     0  8207    56433     2112   274432        0             0 abrt-watch-log
[  105.150984] [   8208]    70  8208    18079       98   159744        0             0 avahi-daemon
[  105.153758] [   8209]    81  8209    18027     1601   172032        0          -900 dbus-daemon
[  105.156699] [   8219]     0  8219    50329      842   184320        0             0 gssproxy
[  105.159302] [   8268]     0  8268    89575     8746   409600        0             0 firewalld
[  105.161659] [   8289]     0  8289    28827      550    69632        0             0 ksmtuned
[  105.164137] [   8291]     0  8291    26990      185    65536        0             0 sleep
[  105.166553] [   8323]     0  8323   178717     3629   425984        0             0 NetworkManager
[  105.169221] [   8342]     0  8342     5482      621    86016        0             0 systemd-hostnam
[  105.172412] [   8586]     0  8586    26868     2251   249856        0             0 dhclient
[  105.174784] [   8781]     0  8781   143483     6048   430080        0             0 tuned
[  105.177118] [   8782]     0  8782    49498     1830   237568        0             0 cupsd
[  105.179376] [   8784]     0  8784    28218     1923   249856        0         -1000 sshd
[  105.181639] [   8788]     0  8788    54104     1633   184320        0             0 rsyslogd
[  105.184102] [   8796]     0  8796   253503     5952   655360        0             0 libvirtd
[  105.186442] [   8811]     0  8811     6478      507   102400        0             0 atd
[  105.188512] [   8812]     0  8812    27528      527    69632        0             0 agetty
[  105.190751] [   8813]     0  8813   120330     1987   245760        0             0 gdm
[  105.192926] [   8814]     0  8814    31574      798    98304        0             0 crond
[  105.194996] [   8838]     0  8838    95405    12766   532480        0             0 X
[  105.197126] [   9116]     0  9116    22936     1211   212992        0             0 master
[  105.199624] [   9124]    89  9124    25503     1654   212992        0             0 pickup
[  105.202097] [   9126]    89  9126    25520     1628   221184        0             0 qmgr
[  105.204206] [   9205]     0  9205   105517     2234   245760        0             0 upowerd
[  105.206490] [   9245]     0  9245     5485      640    90112        0             0 systemd-localed
[  105.208933] [   9274]     0  9274    99596     1751   221184        0             0 boltd
[  105.211173] [   9280]     0  9280    19668     1347   196608        0             0 wpa_supplicant
[  105.213481] [   9284]     0  9284   103073     2701   249856        0             0 packagekitd
[  105.216015] [   9355]   997  9355   104870     2489   274432        0             0 colord
[  105.218348] [   9379]     0  9379    85291     2302   307200        0             0 realmd
[  105.220597] [   9428]     0  9428   100162     2353   339968        0             0 gdm-session-wor
[  105.222920] [   9435]  1000  9435    79331     1854   184320        0             0 gnome-keyring-d
[  105.225349] [   9442]  1000  9442   186285     3762   458752        0             0 gnome-session-b
[  105.227823] [   9451]  1000  9451    14758      519   155648        0             0 dbus-launch
[  105.230216] [   9452]  1000  9452    17802     1084   159744        0             0 dbus-daemon
[  105.233166] [   9532]  1000  9532    97158     1708   192512        0             0 gvfsd
[  105.235724] [   9615]  1000  9615    18107      194   172032        0             0 ssh-agent
[  105.237894] [   9633]  1000  9633    86703     1565   180224        0             0 at-spi-bus-laun
[  105.240320] [   9638]  1000  9638    17593     1120   172032        0             0 dbus-daemon
[  105.242804] [   9640]  1000  9640    58278     1591   225280        0             0 at-spi2-registr
[  105.245413] [   9669]  1000  9669  1022436    64215  1748992        0             0 gnome-shell
[  105.248068] [   9686]  1000  9686   301219     2082   425984        0             0 pulseaudio
[  105.250834] [   9711]  1000  9711   113254     2522   184320        0             0 ibus-daemon
[  105.253248] [   9715]  1000  9715    93964     2122   176128        0             0 ibus-dconf
[  105.255728] [   9717]  1000  9717   116201     5843   483328        0             0 ibus-x11
[  105.258035] [   9721]  1000  9721    93964     1565   167936        0             0 ibus-portal
[  105.260427] [   9731]  1000  9731    91150     1231   151552        0             0 xdg-permission-
[  105.262783] [   9736]  1000  9736 25455958    12451  1277952        0             0 gnome-shell-cal
[  105.265309] [   9741]  1000  9741 25453066    12520  1347584        0             0 evolution-sourc
[  105.268260] [   9758]  1000  9758   102894     4746   294912        0             0 mission-control
[  105.270760] [   9760]  1000  9760   103919     2002   245760        0             0 gvfs-udisks2-vo
[  105.273274] [   9766]  1000  9766 25390606     8756   724992        0             0 goa-daemon
[  105.275695] [   9772]  1000  9772   100136     1629   221184        0             0 gvfs-gphoto2-vo
[  105.278048] [   9779]  1000  9779    97864     1555   200704        0             0 gvfs-mtp-volume
[  105.280525] [   9786]  1000  9786    92863     1329   163840        0             0 gvfs-goa-volume
[  105.283414] [   9801]  1000  9801   131920     3401   450560        0             0 goa-identity-se
[  105.285863] [   9821]  1000  9821   119602     2058   245760        0             0 gvfs-afc-volume
[  105.288252] [   9846]  1000  9846   157917     6042   536576        0             0 gsd-power
[  105.290505] [   9848]  1000  9848   109769     2538   299008        0             0 gsd-print-notif
[  105.293004] [   9851]  1000  9851   130389     1261   188416        0             0 gsd-rfkill
[  105.295357] [   9856]  1000  9856    93520     1394   172032        0             0 gsd-screensaver
[  105.297734] [   9861]  1000  9861   139694     2093   253952        0             0 gsd-sharing
[  105.300511] [   9863]  1000  9863   113723     2148   323584        0             0 gsd-sound
[  105.302939] [   9864]  1000  9864   153788     6066   491520        0             0 gsd-xsettings
[  105.305269] [   9871]  1000  9871   137306     5901   516096        0             0 gsd-wacom
[  105.307619] [   9875]  1000  9875   118022     2637   225280        0             0 gsd-smartcard
[  105.309945] [   9880]  1000  9880    94095     1529   167936        0             0 gsd-a11y-settin
[  105.312395] [   9884]  1000  9884   116102     5684   491520        0             0 gsd-clipboard
[  105.314822] [   9888]  1000  9888   178505     5982   557056        0             0 gsd-color
[  105.317359] [   9889]  1000  9889   135378     4000   471040        0             0 gsd-datetime
[  105.319823] [   9890]  1000  9890   115817     2227   212992        0             0 gsd-housekeepin
[  105.322165] [   9891]  1000  9891   153546     5719   507904        0             0 gsd-keyboard
[  105.324675] [   9896]  1000  9896   248786     6151   585728        0             0 gsd-media-keys
[  105.327123] [   9898]  1000  9898    94096     1502   172032        0             0 gsd-mouse
[  105.329329] [   9901]  1000  9901   114177     1621   196608        0             0 gsd-account
[  105.331756] [   9921]  1000  9921   152147     3125   458752        0             0 gsd-printer
[  105.334555] [   9963]  1000  9963   202464    10129   688128        0             0 nautilus-deskto
[  105.336965] [   9969]  1000  9969   116165     1771   212992        0             0 gvfsd-trash
[  105.339372] [   9981]  1000  9981   321485    16035   917504        0             0 gnome-software
[  105.341779] [   9987]  1000  9987   141670     9260   638976        0             0 vmtoolsd
[  105.344031] [   9988]  1000  9988    68263     1033   163840        0             0 gsd-disk-utilit
[  105.346500] [   9990]  1000  9990 25490899    13075  1323008        0             0 evolution-calen
[  105.349041] [   9998]  1000  9998   132483     6601   593920        0             0 abrt-applet
[  105.351500] [  10000]  1000 10000 25503729    15105  1339392        0             0 evolution-alarm
[  105.354067] [  10013]  1000 10013   167191     4792   434176        0             0 tracker-extract
[  105.356689] [  10020]  1000 10020   158076     3925   372736        0             0 tracker-miner-a
[  105.359852] [  10033]  1000 10033   143774     4770   393216        0             0 tracker-miner-f
[  105.362644] [  10054]  1000 10054   140451     3929   356352        0             0 tracker-miner-u
[  105.365268] [  10087]  1000 10087   131337     4348   270336        0             0 tracker-store
[  105.368211] [  10134]  1000 10134    75548     1589   167936        0             0 ibus-engine-sim
[  105.370777] [  10177]  1000 10177    46848     1233   131072        0             0 dconf-service
[  105.373112] [  10187]  1000 10187   115564     1695   208896        0             0 gvfsd-burn
[  105.375429] [  10191]  1000 10191 29771476    12843  1335296        0             0 evolution-calen
[  105.377971] [  10233]  1000 10233 29681556    12585  1327104        0             0 evolution-addre
[  105.380324] [  10250]     0 10250   146543     3727   438272        0             0 fwupd
[  105.382929] [  10265]  1000 10265 25556161    13082  1335296        0             0 evolution-addre
[  105.385688] [  10337]  1000 10337   183867     9521   577536        0             0 gnome-terminal-
[  105.388059] [  10344]  1000 10344     2135      411    61440        0             0 gnome-pty-helpe
[  105.390555] [  10345]  1000 10345    29056     1083    81920        0             0 bash
[  105.392920] [  10363]     0 10363    87620     2512   299008        0          -900 abrt-dbus
[  105.395155] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=gnome-shell,pid=9669,uid=1000
[  105.398923] Out of memory: Kill process 9669 (gnome-shell) score 87 or sacrifice child
[  105.401434] Killed process 9711 (ibus-daemon) total-vm:453016kB, anon-rss:4040kB, file-rss:6048kB, shmem-rss:0kB
[  105.405179] oom_reaper: reaped process 9711 (ibus-daemon), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

また、 OOM killer が発動せずにメモリ割り当て要求が失敗した場合も、 __GFP_NOWARN フラグが指定されていない場合、メモリを要求したプロセスの情報や空きメモリの状況などで、多くのカーネルメッセージが出力されます。

[   67.502007] insmod: page allocation failure: order:1, mode:0x484020(GFP_ATOMIC|__GFP_COMP), nodemask=(null),cpuset=/,mems_allowed=0
[   67.505928] CPU: 5 PID: 9669 Comm: insmod Kdump: loaded Tainted: G           O    T 5.0.0 #1
[   67.508414] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/13/2018
[   67.511779] Call Trace:
[   67.512495]  dump_stack+0x9a/0xf0
[   67.513775]  warn_alloc.cold.120+0x8a/0x17f
[   67.515022]  ? zone_watermark_ok_safe+0x260/0x260
[   67.516478]  ? compaction_suitable+0x265/0x310
[   67.517920]  ? wakeup_kcompactd+0x17d/0x460
[   67.519184]  ? __isolate_free_page+0x590/0x590
[   67.520444]  ? wake_all_kswapds+0x14e/0x2d0
[   67.521919]  __alloc_pages_slowpath+0x1e92/0x23f0
[   67.523410]  ? warn_alloc+0x120/0x120
[   67.524535]  ? __kernel_text_address+0x9/0x30
[   67.526027]  ? unwind_get_return_address+0x5a/0xa0
[   67.527901]  ? __save_stack_trace+0x8d/0xf0
[   67.529252]  ? __isolate_free_page+0x590/0x590
[   67.531311]  __alloc_pages_nodemask+0x5e7/0x6f0
[   67.532834]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   67.534727]  ? warn_alloc_test+0x3f/0x1000 [warn_alloc_test]
[   67.536430]  ? __alloc_pages_slowpath+0x23f0/0x23f0
[   67.538071]  ? __do_sys_finit_module+0x11a/0x1b0
[   67.539511]  ? _raw_spin_unlock+0x1f/0x30
[   67.540864]  ? deactivate_slab.isra.70+0x5f9/0x630
[   67.542500]  new_slab+0x408/0x720
[   67.543447]  ___slab_alloc+0x48f/0x750
[   67.544742]  ? warn_alloc_test+0x3f/0x1000 [warn_alloc_test]
[   67.546753]  ? warn_alloc_test+0x3f/0x1000 [warn_alloc_test]
[   67.548598]  ? __slab_alloc+0x43/0x90
[   67.549689]  __slab_alloc+0x43/0x90
[   67.550827]  ? warn_alloc_test+0x3f/0x1000 [warn_alloc_test]
[   67.552870]  kmem_cache_alloc_trace+0x2b2/0x340
[   67.554283]  ? 0xffffffffc0b98000
[   67.555288]  warn_alloc_test+0x3f/0x1000 [warn_alloc_test]
[   67.556991]  do_one_initcall+0xe2/0x553
[   67.558164]  ? trace_event_raw_event_initcall_finish+0x1b0/0x1b0
[   67.559964]  ? kasan_unpoison_shadow+0x30/0x40
[   67.561369]  ? __kasan_kmalloc.constprop.8+0xc1/0xd0
[   67.562925]  ? do_init_module+0x49/0x680
[   67.565369]  ? kmem_cache_alloc_trace+0x14b/0x340
[   67.568743]  ? kasan_unpoison_shadow+0x30/0x40
[   67.571268]  do_init_module+0x1da/0x680
[   67.573533]  load_module+0x43e8/0x56d0
[   67.575818]  ? layout_and_allocate+0x2140/0x2140
[   67.578293]  ? kernel_read+0x8b/0x130
[   67.580874]  ? kernel_read_file+0x225/0x4f0
[   67.584000]  ? __do_sys_finit_module+0x11a/0x1b0
[   67.587107]  __do_sys_finit_module+0x11a/0x1b0
[   67.590156]  ? __ia32_sys_init_module+0xa0/0xa0
[   67.592875]  ? __audit_syscall_exit+0x712/0x990
[   67.595495]  ? rcu_read_lock_sched_held+0x102/0x120
[   67.598825]  ? do_syscall_64+0x1d/0x450
[   67.601399]  do_syscall_64+0x9a/0x450
[   67.603438]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[   67.605926] RIP: 0033:0x7f44b9c0e1c9
[   67.607954] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 97 dc 2c 00 f7 d8 64 89 01 48
[   67.616251] RSP: 002b:00007ffc95acf7f8 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
[   67.619559] RAX: ffffffffffffffda RBX: 000000000157b1e0 RCX: 00007f44b9c0e1c9
[   67.622781] RDX: 0000000000000000 RSI: 000000000041a94e RDI: 0000000000000003
[   67.625924] RBP: 000000000041a94e R08: 0000000000000000 R09: 00007ffc95acf998
[   67.629081] R10: 0000000000000003 R11: 0000000000000202 R12: 0000000000000000
[   67.632887] R13: 000000000157a120 R14: 0000000000000000 R15: 0000000000000000
[   67.636177] Mem-Info:
[   67.637890] active_anon:17800 inactive_anon:2180 isolated_anon:0
[   67.637890]  active_file:10961 inactive_file:19385 isolated_file:0
[   67.637890]  unevictable:0 dirty:6 writeback:0 unstable:0
[   67.637890]  slab_reclaimable:14588 slab_unreclaimable:491776
[   67.637890]  mapped:11952 shmem:2325 pagetables:2323 bounce:0
[   67.637890]  free:20742 free_pcp:2080 free_cma:0
[   67.654596] Node 0 active_anon:71200kB inactive_anon:8720kB active_file:43844kB inactive_file:77540kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:47808kB dirty:24kB writeback:0kB shmem:9300kB shmem_thp: 0kB shmem_pmdmapped: 0kB anon_thp: 16384kB writeback_tmp:0kB unstable:0kB all_unreclaimable? yes
[   67.665897] Node 0 DMA free:9572kB min:440kB low:548kB high:656kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB writepending:0kB present:15960kB managed:15876kB mlocked:0kB kernel_stack:0kB pagetables:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[   67.676348] lowmem_reserve[]: 0 2121 2358 2358
[   67.678942] Node 0 DMA32 free:66284kB min:175068kB low:190160kB high:205252kB active_anon:64400kB inactive_anon:488kB active_file:30260kB inactive_file:61300kB unevictable:0kB writepending:20kB present:3129152kB managed:2172172kB mlocked:0kB kernel_stack:4864kB pagetables:8072kB bounce:0kB free_pcp:7376kB local_pcp:400kB free_cma:0kB
[   67.692470] lowmem_reserve[]: 0 0 237 237
[   67.695196] Node 0 Normal free:6900kB min:19044kB low:20732kB high:22420kB active_anon:6800kB inactive_anon:8232kB active_file:13584kB inactive_file:16116kB unevictable:0kB writepending:4kB present:1048576kB managed:243172kB mlocked:0kB kernel_stack:8576kB pagetables:1220kB bounce:0kB free_pcp:1056kB local_pcp:156kB free_cma:0kB
[   67.713011] lowmem_reserve[]: 0 0 0 0
[   67.715741] Node 0 DMA: 1*4kB (U) 0*8kB 0*16kB 1*32kB (H) 1*64kB (H) 0*128kB 1*256kB (H) 0*512kB 1*1024kB (H) 2*2048kB (UM) 1*4096kB (M) = 9572kB
[   67.721528] Node 0 DMA32: 1149*4kB (UMH) 349*8kB (UMH) 111*16kB (UMH) 2*32kB (UM) 2*64kB (UE) 4*128kB (UME) 4*256kB (UM) 4*512kB (UME) 52*1024kB (M) 0*2048kB 0*4096kB = 66188kB
[   67.729437] Node 0 Normal: 165*4kB (UMH) 146*8kB (UMH) 125*16kB (UMEH) 2*32kB (ME) 7*64kB (UME) 1*128kB (U) 4*256kB (UM) 1*512kB (U) 0*1024kB 0*2048kB 0*4096kB = 6004kB
[   67.738350] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[   67.742785] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   67.747366] 32671 total pagecache pages
[   67.750805] 0 pages in swap cache
[   67.754202] Swap cache stats: add 0, delete 0, find 0/0
[   67.757683] Free swap  = 0kB
[   67.760161] Total swap = 0kB
[   67.762786] 1048422 pages RAM
[   67.765738] 0 pages HighMem/MovableOnly
[   67.768547] 440617 pages reserved
[   67.772855] 0 pages cma reserved
[   67.775874] 0 pages hwpoisoned
[   67.778646] SLUB: Unable to allocate memory on node -1, gfp=0x480020(GFP_ATOMIC)
[   67.783148]   cache: kmalloc-4k, object size: 4096, buffer size: 4448, default order: 3, min order: 1
[   67.788063]   kmalloc-4k debugging increased min order, use slub_debug=O to disable.
[   67.792494]   node 0: slabs: 56643, objs: 396501, free: 0

困ったことに、メモリ管理サブシステムは、 printk() のコストを無視することが大好きなようで、 syzbot のファジングテストに頼らずとも printk() によるロックアップに遭遇することが時々あります。そこで、少し話が脱線してしまいますが、 syzbot を使わずに見つけたものも含めて printk() が関係している OOM killer 関連の不具合について紹介します。


4.1 事例1:無数のスレッドに対して printk() のループを実行することによるストール その1

Linux 4.3 以前のカーネルでは、強制終了させられたプロセスの情報を表示する際に、メモリを共有していたことにより同時に強制終了させられた別のプロセス(セキュリティ・キャンプ2016の講義資料で「ひねくれ者のマルチスレッド」として紹介していたプロセス)についての情報を

pr_err("Kill process %d (%s) sharing same memory\n", task_pid_nr(p), p->comm);

という形で表示するようにしていました。しかし、 printk() は重たい処理であるため、メモリを共有しているプロセスを意図的に多数作成することにより、 RCU というロックを保持したままのロックアップ状態を発生させることができてしまうという問題がありました。この状況は、 Linux 4.4-rc1 にマージされた

によりメッセージを表示しなくなるまで続きました。全てのスレッドに対して printk() を呼ぶ可能性のあるような処理は大抵、ロックアップによるトラブルを招いてしまうものなのです。


4.2 事例2:無数のスレッドが順番に printk() のループを待つことによるハングアップ

「ひねくれ者のマルチスレッド」が異なる oom_score_adj を設定できてしまうことにより、 OOM killer により強制終了させることができるスレッドと強制終了させることができないスレッドが混在する状況は許容すべきではないという理由により、

が Linux 4.8-rc1 にマージされてしまいました。熊猫は当初から反対していたのですが、無視されました。

その後、このパッチに起因した遅延を避けようと試みる開発者が現れました。

その提案内容が安全かどうかをレビューしてみたところ、提案内容を適用するかどうかとは関係なく、 OOM killer により強制終了させることができるスレッドと強制終了させることができないスレッドが混在する状況が発生してしまう競合状態があることが判明しました。(つまり、 Linux 4.8-rc1 にマージされたパッチの説明は不正確であったことが発覚しました。)

そのため、そのパッチを取り消す提案をしたのですが、このパッチによる遅延は問題にならないという主張により、拒否されてしまいました。

またしても printk() のコストを無視する発言であったため、意図的に「ひねくれ者のマルチスレッド」を多数作成することにより、 printk() によるカーネルメッセージを出力し続けてしまうことで、処理が進まなくなるという状況が発生する(例えば 32000 個の場合、1か月半もの間、無意味なメッセージを出力し続けてしまう)ことを実験により示しました。

競合状態を解消するパッチの提案を求めたのですが、「やがて修正される」という逃げ道を使われて、結局、 printk() を削除するだけのパッチ

が Linux 5.0-rc8 にマージされました。「やがて修正される」という主張により問題の先送りが正当化されるというのは、気分の良いものではありません。

printk() に話を戻すと、事例1の繰り返しですが、全てスレッドに対して printk() を呼ぶ可能性のあるような処理は大抵、ロックアップによるトラブルを招いてしまうものなのです。


4.3 事例3:無数のスレッドが同時に printk() を呼び出すことによるハングアップ

Linux 4.8 のリリース後の出来事として、「 __GFP_FS を含まないメモリ割り当て要求が原因でハングアップするのを回避するために、 __GFP_FS を含まないメモリ割り当て要求でも OOM killer を発動できるようにする」という提案を行いましたが、「簡単に OOM killer が発生してしまうので危険である」と却下されました。

代わりに、「 OOM killer を発動できないことでハングアップしている状態を検知できるようにするために、メモリの割り当て要求が10秒以上経過しても完了しない場合、メモリ割り当て要求でストールしていることを知らせるためのメッセージを出力できるようにする」という提案が行われました。

その提案に対しては、当初から「 printk() は遅い処理なので、直列化しないとメッセージが交錯してしまってログが読めなくなる」と懸念を示していたのですが、無視されました。

また、「 __GFP_NOWARN を含むメモリ割り当て要求でも手掛かりが残るように、ストールを知らせる場合には __GFP_NOWARN を無視すべき」と提案していたのですが、(その時点では)無視されました。

そして、懸念事項を無視したまま、 Linux 4.9-rc1 でパッチがマージされてしまいました。

その後、余分な改行を削除するという微修正がありました。

半年後、「 __GFP_NOWARN を含むメモリ割り当て要求でも手掛かりを残せるようにしたほうが有益である」と判断され、 __GFP_NOWARN を無視する変更が行われました。(メンテナである Michal Hocko さんは反対していましたが、メンテナ以外が賛成したことにより、採用されました。)

その後、ストレステストを行った際にシステムがロックアップ(事実上のハングアップ)するという不具合報告が届きました。

当初から懸念していたように、 printk() は遅い処理であるため、同時多発的に呼ばれるとハングアップしてしまうことが確認された訳です。そのため、「ストールを知らせるメッセージを出力する処理を、ロックを用いて直列化する」という提案を行いました。

この提案に対して、 Michal Hocko さんの拒絶反応はひどいものでした。

最初の反応は、最新版の無修正カーネルでの事象ではないことについてでした。

次の反応は、呼び出し側の問題ではないという主張でした。しかも、問題を切り分ける方法を提供せずに、問題の切り分けを要求してきたのです。

printk() の乱用に起因した問題であると説明したのですが、無視されてしまいました。

そんな状況を嘆いていたら、怒られました。

無視された状況を打開するために、別の回避策を提示してみましたが、やはり無視されてしまいました。

その後、別の不具合報告が届いたため、さらに別の回避策を提示してみましたが、やはり無視されてしまいました。

そして、ストレステストではない状況で発生したという不具合報告が届き、現実の問題として対処する必要が生じました。

printk() の仕様上避けられない事象であるということをやっと納得してもらい、「 ratelimit によるチューニングをするよりも、振り出しに戻るほうが良い」という結論になり、当初から懸念されていたパッチは1年がかり( Linux 4.15-rc1 )でやっと削除されました。

多数のスレッドが同時に printk() を呼べるような処理は大抵、ロックアップによるトラブルを招いてしまうものなのです。

このトピックのまとめとしては、

のようになるかと思いますが、ひどい話だと思いませんか?このトピックに関わったのが、セキュリティ・キャンプ2018の講義資料でいうところの「スペシャリスト」側の人だけだったら、誰も着手しようとせずに放置されていたのかもしれません。

上述した printk: Console owner and waiter logic cleanup が Linux 4.16-rc1 でマージされたことにより、 OOM killer を呼び出したスレッドが printk() の中で永遠にループしてしまうという事態は発生しなくなった筈です。しかし、 printk() が現在でも同期処理であることから、多数のスレッドが同時に printk() を呼ぶことが可能な「メモリ割り当て処理」の中からストールを報告させることで予期せぬ遅延に繋がる恐れは残っています。


4.4 事例4: OOM killer が機能していないことを示すメッセージによるストール

syzbot によるテストが本格的に行われるようになり、 OOM killer 関連の不具合も見つかるようになってきた2018年7月のこと、 memcg OOM killer イベントが発生したけれども強制終了させることができるプロセスが見つからないことにより WARN_ON() が呼ばれるという状況が発生しました。

当該 memcg で利用可能なメモリの上限を 0 に設定してしまったことが発生のトリガであり、それ自体は設定ミスの範囲と考えられるのですが、この問題を修正するための方法として、 WARN_ON() を削除して、 printk() によるメッセージを出力するというパッチ

が Linux 4.19-rc3 にマージされてしまいました。その結果、何が起こったでしょう?

syzbot は「問題を検知した場合には、深刻度に関わらずカーネルパニックで停止させる」という設定でテストを行うため、今まで WARN_ON() が呼ばれたらすぐ停止していたのですが、この修正により、テストを打ち切る代わりに printk() が呼ばれ続けるという状況が発生しました。その結果、 memcg OOM killer が呼ばれるたびに大量のカーネルメッセージを出力してしまうことによるストールが発生

してしまった訳です。たとえ1つのスレッドであっても、いつまでも printk() を呼び出すような処理は大抵、ロックアップによるトラブルを招いてしまうものなのです。

そして、この問題を修正するために提案されたのが・・・

・・・なのですが、まだ採用されていません。(つまり、問題はまだ修正されていません。)

その理由は、 ratelimit が機能しないからです。

OOMのように、大量のメッセージを出力する場合、 ratelimit は期待通りに動作しません。それは、 ratelimit の計算ロジックが、 printk() の処理が十分に速いことを前提条件として実装されているからです。


4.5 事例5:無数のスレッドが無意味に OOM killer を呼び出すことによる遅延

これは、事例4の修正方法を検討している際に見つかった問題です。「 OOM unkillable にするには root 権限が必要だから、問題にならない」という主張に対して、一般ユーザでも大量のメッセージを発生させることができることを実験により示しました。

根本原因は、同じプロセスを何度も選択してしまうことにより(プロセスを強制終了させることができずに)ロックアップ状態が発生するのを回避するためのパッチ

が Linux 4.8-rc1 にマージされたことにより、まだ終了していないプロセスが無視されてしまったことにあります。この問題は

が Linux 5.0-rc1 にマージされるまで続きました。

さて、 printk() により不要なメッセージが出力されるのを抑止するという観点からは、上記のパッチの説明は正しいのですが、このパッチに至った経緯はもっと複雑でした。このパッチの説明は、パッチを作成した熊猫の意思に反して改ざんされています。オリジナルの説明は、このパッチに記録されているリンク先から参照することができるようになっています。

わぉ! printk() とは全然関係ないですね。実は、このパッチは、不要なメッセージが出力されるだけでは済まない問題を修正していたのです。

パッチの作者が考えた説明文を、パッチがマージされる際にメンテナが書き換えるということは、どのサブシステムでも時々起こっています。しかし、このパッチのように、作者の意向が完全に無視されたというのは非常に珍しいケースだと思います。

さて、このパッチが採用されるまでの経緯をみてみましょう。

まず、 Michal Hocko さんがパッチを投げたのですが、熊猫しか参加しませんでした。(メモリ枯渇時の挙動についての議論に参加してくれる人が居ないのは、毎度のことなのです。)

話が進まなかったため、パッチを提案したのですが、例によって反応はありませんでした。

そのため、どうやって修正するかを尋ねてみたところ、認識のずれが発覚しました。

不要なメッセージを表示させないようにするという修正の裏側に、細かなところまで気を配っているかどうかを見て取れましたか?


4.6 事例6:無数のスレッドに対して printk() のループを実行することによるストール その2

syzbot が fork bomb 攻撃の方法を見つけ出してしまったことで、 OOM killer が大量のメッセージを出力することによるストールが発生するようになりました。その対策として、強制終了の対象として表示されうるプロセスの一覧の出力処理に時間制限を設けることを提案してみましたが、却下されました。

プロセスを一覧表示するかどうかは /proc/sys/vm/oom_dump_tasks という sysctl インタフェースとしてユーザランドに公開してしまっているため、今更 printk() の呼び出しを削除するという修正は不可能です。また、第3章で紹介したように、コンソールの出力処理を非同期処理にする試みは、まだ採用されていません。そのため、 printk() の呼び出しをRCUセクションの外に移動させることで、最低限RCUによるストールを回避する方法を提案してみました・・・が反応がありませんでした。

その後、 syzbot が見つけたクラッシュがきっかけで、(クラッシュの根本原因は特定できませんでしたが、) dump_tasks() 関数の処理内容が修正されました。

その修正に便乗して、RCUによるストールを回避する方法を再提案したところ、 Andrew Morton さんが拾ってくれたため、現在 linux-next.git にあります。何事もなければ、 Linux 5.4 で、RCUストールを回避できるようになることが期待されます。しかし、 ratelimit が機能しないという問題が解決できるようになる訳ではありません。

現在のところ、 /proc/sys/vm/oom_dump_tasks に 0 を設定することで強制終了の対象として表示されうるプロセスの一覧を出力させないようにする以外の回避策はありません。


第5章 デバッグ支援機構に対する試行錯誤について


クラッシュが発生した時にメモリダンプを取得することが現実的ではないため、クラッシュ発生時のカーネルメッセージを中心に判断することになります。そのため、デバッグ支援機構が有用なメッセージを正確に出力してもらうための試行錯誤が行われてきました。


5.1 ハングアップに関連しそうなプロセスの情報を得る試み

2018年初め頃は、「ハングアップした」と判定されたクラッシュレポートが多く生成されていたため、 khungtaskd がハングアップしたスレッドを報告する際の改善が試みられました。

しかし、第1章で示したように、デッドロックが発生しているのであれば、デッドロックが発生するよりも前に lockdep により報告される筈ですので、これらの不具合の多くは、デッドロック以外の原因によるものと考えられます。ハングアップしたと判定されたレポートでも、実際には、何か他の処理に没頭してしまったことによるストールが原因で、CPU時間が割り当てられない状態が続いていただけと推測されるケースも多くなってきました。そこで、カーネルパニックが発生した時に SysRq を取得できるようにするという試みもされましたが、コミュニティからの反応が無く、立ち消えになってしまいました。

なお、 SysRq は概況を把握するのには便利なのですが、 printk() はコストが高いため、大量の情報を出力しようとすると限界があります。そのため、早く自動 kdump 取得+スクリプトによる自動解析へ移行したいというのが本音かもしれません。もし、 syzbot が Google Compute Engine 上ではなく QEMU 上でテストを行っていたら、 PVPANIC ドライバ経由でカーネルパニックイベントの発生を通知することで、 QEMU 側からメモリダンプを取得して解析するという方法が使えたのでしょうけどねぇ・・・。こういうところは、大規模で自動化されたファジングテストならではの制約事項ということになる訳です。

syzbot でテストを実行するために作成されるプロセスは短命である(開始から5秒経過後に SIGKILL シグナルが送信される)ため、 SIGKILL シグナルにより終了しないケースというのも、ある意味ではハングアップしていると考えることができます。そのため、 SIGKILL シグナルを受信しているのに終了しないプロセスを報告するという試みもされました。この試みにより、 SIGKILL シグナルを受け取った後もメモリ割り当て処理のループから抜けないことが原因で終了できない不具合を2ヵ所発見しました。

しかし、この方法では、 SIGKILL シグナルを受けとらない限り無限にリトライしてしまうというタイプの不具合は検知できません。例えば、 memcg OOM killer を発動できないままCPU使用率が100%になってしまうという不具合

は、テストを実行するために作成されるプロセスが短命すぎるため、検知できません。(幸いなことに、報告者が reproducer の作成と原因となったパッチの bisection を済ませた上で報告してくれたため、容易に修正することができました。)


5.2 デバッグ支援機構を修正する試み

デバッグ支援機構にもバグは存在しえます。そのため、デバッグ支援機構が報告した内容を妄信すると、混乱することがあります。

lockdep の偽陽性メッセージ その1

デッドロックの可能性を報告する lockdep が、セマフォのロック状態を排他モードから共有モードに変更するための lock_downgrade() 関数内で、既に排他モードではない状態で呼ばれたことを警告してきました。

しかし、ソースコードを見ても怪しい箇所が無く、お手上げ状態でした。

そのため、セマフォの状態を出力するデバッグ printk() パッチを適用して情報取得を試みた結果、 lockdep が記憶しているロックの状態とセマフォが記憶しているロックの状態との間に不整合があることを突き止めることができました。何らかの問題により、 lockdep が記憶しているロックの状態が正しくないことが確認された訳です。

この警告メッセージは corrupted report (2) 宛に送られた大量のレポートの中にも存在していたため、レポートを比較してみた結果、この警告が出現する場合の規則性を発見し、発生条件を突き止めることができました。

そして、この問題は

というパッチが Linux 5.1-rc1 にマージされて解消しました。

lockdep の偽陽性メッセージ その2

デッドロックの可能性を報告する lockdep が、ロックの使われ方を追跡するための key の登録に関して、登録の方法が間違っていることを警告してきました。

INFO: trying to register non-static key.
the code is fine but needs lockdep annotation.
turning off the locking correctness validator.

このメッセージをそのまま解釈すると、 key の登録方法を修正すればよいように思えます。しかし、 key の登録は、 key を含むオブジェクトの初期化処理時に自動的に行われるものであるため、オブジェクトの利用者は意識する必要のない処理です。そのため、利用者は何をすればよいのかを理解できず、お手上げ状態になってしまいます。

このメッセージが出力された根本原因は、本来は既に登録済みであるべき key が、オブジェクトの初期化処理が呼ばれなかったことにより未登録の状態となっており、その key を使うロックを初めて取得する際に key を登録しようとしたことにありました。さらに、動的に割り当てられるオブジェクトであり、 __GFP_ZERO によりメモリ領域が初期化されていたため、メモリアクセスに関するエラーを検出する KMSAN により「初期化されていないメモリ領域へのアクセス」という形で報告されない状態でした。そのため、このメッセージが出力された原因となった個所を修正するだけでなく、初期化処理が呼ばれていないことを検知するための

というパッチを Linux 5.1-rc1 にマージすることで、同様のケースが起きた時に利用者側の問題であることが判るようにしました。


第6章 テストケースをめぐる試行錯誤について


カーネルが提供している機能の一部は、管理者向けの機能であるため、その機能を呼び出すためには、システム管理者の権限を必要とします。そのため、ファジングテストを行うためのプログラムは root ユーザの権限で実行されます。もし、システム管理者の権限を必要とせずにクラッシュなどの問題を発生させることができた場合は、脆弱性と認定されることがあります。

ファジングテストを行うためには、システムコールの呼び出しに必要な情報(引数の数や型など)を人間が事前に定義しておく必要があります。そして、 fuzzer と呼ばれる機能が、その情報をいろいろ改変(意図的に NULL を渡したり、非常識な値を渡したり)して、呼び出す順序やタイミングもいろいろ改変(初期化処理と終了処理を同時に呼び出したり、意図的に同じ処理を繰り返したり)して、クラッシュなどの問題が発生しないかどうかをテストします。つまり、テストケースとして一捻り加えているというところが、ファジングテストの肝なのです。

ファジングテストでは、テストケースに一捻りを加えるため、システム管理者の視点から考えてみれば「馬鹿げたこと」を試してしまうこともあります。しかし、ファジングテストのためのテストケースを作成するプログラム自身は、テストケースが馬鹿げているかどうかを判断できません。そのため、人間が定義したブラックリストを用いて、特定のテストケースを生成させないようにコントロールすることで対処しています。ここでは、一捻りの方法が不適切であったために、本来は「システム管理者だけが要求することができる操作であり、この結果は問題ではない」と判断すべきところで「問題が発生した」と判断されてしまったというケースについて扱います。


6.1 事例1:フリーズ処理/サスペンド処理によるハングアップ

システム管理者はファイルシステムやプロセスを一時停止させることができるようになっています。しかし、一時停止の状態が長時間続くと、 watchdog によりシステムがハングアップしたと判定されてしまうことがあるため、速やかに元の状態に戻すことが求められます。しかし、ファジングテストを行うためのプログラムが、元の状態に戻す処理を実行してくれるという保証はありません。そのため、テストケースから一時停止させることができる処理を除外する必要があります。

ファイルシステムに対するフリーズ処理

__sb_start_write() という関数の中でハングアップするという不具合を syzbot が発見しましたが、誰も着手しようとしませんでした。

困ったことに、 __sb_start_write() という関数は、ファイルシステムに対して変更を加えるために呼び出されるため、 ハングアップしたスレッドのバックトレースだけを見ても、「ハングアップした」こと以上の情報を得られません。誰が この処理をブロックしているのかを見つける必要があります。

第5章で紹介したパッチがマージされたことにより、ハングアップ状態の全てのスレッドのバックトレースを確認できるようになりました。しかし、それでも、不審なスレッドは見つかりませんでした。

__sb_start_write() という関数の中でハングアップする原因として、誰かが ioctl(FIFREEZE) という処理を呼び出したことが考えられます。しかし、 FIFREEZE は既にブラックリストに載っている処理であるため、ファジングテストを行うためのプログラムは呼んでいない筈です。

そのため、デバッグ printk() パッチを適用して事象を再現できないか試みましたが、再現できませんでした。

syzbot は、既に reproducer が発見されている不具合に関しては、パッチを適用してテストを行うための手段( #syz test: )を提供しています。しかし、情報を取得するために独自のパッチを適用してファジングテストを行う手段は提供していません。これは、パッチを適用するためには、そのパッチを長期間に渡って入手可能な状態を維持することが必要になり、自動化の妨げになるからです。従って、手元の環境で不具合を再現できない場合、情報を取得するためのデバッグ printk() パッチを既存のテスト対象となる git ツリーにマージしてもらった上で、 syzbot 環境で不具合を再現してもらう必要があります。

そのため、 Andrew Morton さんにデバッグ printk() パッチを拾ってもらい、 syzbot 環境で不具合を再現させることになりました。 その結果、カーネルの不具合ではなく、誰かが percpu_down_write() を呼び出していることが原因であることが確認されました。さて、誰が呼び出しているのでしょう・・・?

結局、既にブラックリストに載っていたけれども、ブラックリストの適用後に一捻りしていたため、ブラックリストが機能していなかったというのが原因でした。

ext4 ファイルシステム固有のフリーズ処理によるハングアップ

再び、 __sb_start_write() という関数の中でハングアップするという不具合を syzbot が発見しました。

カーネルが出力したメッセージから、ハングアップする前に ext4_shutdown() という処理が呼ばれていることが判明し、その処理を呼び出している ioctl(EXT4_IOC_SHUTDOWN) という処理をブラックリストに載せることにより対処されました。

サスペンド処理によるハングアップ

最も多く生成されている報告は、「カーネルが無応答状態に陥ったことで、ファジングテストを行うプロセスからの出力が滞った」というものです。この報告は

宛に送られています。未知の不具合を見つけるためには、このような報告も確認して、「何が原因なのか?どうすれば有用な情報を取得できるようになるのか?」を考えていくことが必要になります。

そんな報告の1つに、カーネルが出力するメッセージからプロセスをフリーズするための処理を呼び出しているものを発見したため、その処理を呼び出している ioctl(SNAPSHOT_FREEZE) という処理をブラックリストに載せることにより対処されました。


6.2 事例2:原因不明のコンソールメッセージ非表示 その1

第2章では、 printk() の改善により、メッセージが混在することにより問題に関連したメッセージを抽出することができずに捨てられてしまうというケースが激減したことを紹介しました。しかし、問題に関連したメッセージを抽出できなくなる原因の1つに、コンソールに出力されるメッセージが何故か出力されないというものがあります。 /proc/sys/kernel/printk の最初の値は console loglevel と呼ばれていて、コンソールに出力されるかどうか(言い換えると、 syzkaller がメッセージを取得できるかどうか)に関係しています。 console loglevel が予期せず変更されてしまうと、コンソールに出力されるべきメッセージが出力されないことで、「問題が起きたようだけれども何が起こったのか判定できなかった」という結果に繋がります。

printk() の改善により、捨てられてしまうケースが減った2019年3月のこと、問題を検出してカーネルパニックで停止させる際に、それまでのメッセージがコンソールに出力されていないケースがあることに気づきました。

しかし、 console loglevel を変更するような処理は呼び出していない筈と考えられていたため、 console loglevel が変更されたらすぐに停止するというデバッグ用パッチを作成しました。

結局、 syslog() というシステムコールを呼び出すことで console loglevel を変更してしまっていたことが判明し、ブラックリストに追加することで対処しました。


6.3 事例3:原因不明のコンソールメッセージ非表示 その2

しかし、ブラックリストに追加したことで解決・・・という訳には行きませんでした。再び、それまでのメッセージがコンソールに出力されていないケースがあることに気づきました。

調査のためのデバッグ printk() パッチを提案してみたのですが、もしかすると、バイナリのコードを実行する syz_execute_func() 関数が、ブラックリストにより除外されるべきパラメータを伴ってシステムコールを呼んでしまっているのではないかという疑惑が浮上しました。もし、 syz_execute_func() 関数が犯人であった場合、ブラックリストによる例外指定が無意味になってしまう訳で、「ファジングテスト用にビルドされたカーネルでは馬鹿げたことをさせないようにする」という修正をカーネル側で実装する必要が生じることが予想されます。

結局、デバッグ printk() パッチによる調査は行われないまま、とりあえず syz_execute_func() 関数を無効化するという対処が行われました。


第7章 ファジングテストで使用する基盤機能が動くようにするための試行錯誤について


syzbot がファジングテストを行うために使っている主な基盤機能として、以下のものが挙げられると考えます。(注:主観による判断です。)

問題の原因個所により表面化する事象が異なります。基盤となる機能での不具合は、様々な形で現れます。異なる原因個所でも同じ事象が発生することもあります。

 原因個所が異なるのに同じ事象と判断されてしまうと、対処されなかった原因個所を見落としてしまうことになるため、同じ事象と判断されてしまう前に修正したいのですが、優先度は上がりません。


7.1 事例1: Memory allocation fault injection によるバグの嵐

セキュリティ・キャンプ2016の講義資料の The "too small to fail" memory-allocation rule 事件で述べられているように、メモリ割り当てが失敗した場合の処理は殆どテストされていません。 syzbot はメモリ割り当てが失敗した場合の処理を積極的にテストしており、当然のことながら、メモリ割り当てが失敗した場合に NULL pointer dereference によるクラッシュが発生するというバグをたくさん発見しています。そこで、ここでは、一筋縄では修正できなかったケースを紹介します。

__list_del_entry_valid() という関数の中でクラッシュするという不具合を syzbot が発見しました。

内容を確認したところ、メモリを回収するために使われる shrinker という機能を登録するための関数でメモリ割り当てが失敗していることが原因と判明しました。

しかし、根本原因は、 register_shrinker() という関数でメモリ割り当てを行うという修正をマージする際に、呼び出し元に対してエラーハンドリングを追加しなかったことが原因です。

(いろんな Linux ディストリビューションで使われるカーネルのベースとなる)メインラインカーネルの開発者は、メインラインカーネルに対する修正を加える際に、 その修正によりメインラインカーネルに含まれている他の処理に対して影響を与えないようにするための配慮をする責任があります。例えば、API関数の戻り値の型を 変更するような修正を加える場合、そのAPI関数を呼び出している全ての処理に対して、同時に修正を行うことが求められます。そのため、メインラインカーネルに 含まれている処理は、バージョンアップにより動かなくなるというリグレッションが発生しにくいという特徴があります。しかし、今までエラーが発生する可能性が 無かったために戻り値の型が void であった関数が、エラーが発生する可能性が生じたために戻り値の型が int になったのに、その関数の呼び出し元に対して エラーハンドリングを追加していなかったため、リグレッションが発生していた訳です。そして、メモリ割り当てが失敗した場合の処理は殆どテストされていないため、 syzbot が発見するまで、誰にも気づかれませんでした。

とりあえず、 register_shrinker() 関数でメモリ割り当て処理が失敗した場合には unregister_shrinker() 関数が何もしないようにするというパッチ

が提案され、 Linux 4.15-rc7 でマージされました。

全ての register_shrinker() 関数の呼び出し元の処理に関してスペシャリストであれば、適切なエラーハンドリングを追加することも可能でしょう。しかし、 そんな人は居ませんし、メインラインカーネルに含まれていない処理が register_shrinker() 関数を呼び出している可能性も考えられます。そのため、それぞれの 処理のスペシャリストに協力してもらいながら修正していくというのが、「影響を与えないようにするための配慮」をサボったことにより発生したこの不具合への 妥当な対処方法であると考えました。そして、注意喚起の意味も含めて register_shrinker() 関数の呼び出し元に対して、エラーハンドリングを行っているか どうかを検知できるようにするために __must_check 属性を追加するという提案をしたのですが、受け入れられませんでした。

結局、メインラインカーネルに含まれている処理に関しては、2か所を除いて、エラーハンドリングが追加されました。しかし、サポートセンタで Linux が 関係するシステムの故障解析に携わった経験があり、メインラインカーネルに含まれていない処理の中には、ひどく品質の悪いものが存在していることを 知っている熊猫としては、いまだにエラーハンドリングが追加されていないのではないかと気になっています。

なお、この不具合の発生個所である、 sget_userns() 関数内で register_shrinker() が失敗した場合に対応するためのパッチ

も提案され、 Linux 4.15-rc7 でマージされました。ところが・・・これで終わりではなかったのです。

今度は、 register_shrinker() 関数あるいは sget_userns() 関数がエラーを返した場合に、呼び出し元のエラーハンドリングが正しくないということを syzbot が発見しました。(他にもあったかと思うのですが、メールの海に埋もれてしまって掘り出せませんでした。 )

shrinker の登録時のメモリ割り当てが失敗した場合にそれまでの処理を取り消すというエラーハンドリングを適切に実装することは大変であったため、 呼び出し元を複雑にするよりも、 register_shrinker() の処理を2段階に分割して第1段階で先にメモリ割り当てを行うことで、複雑なエラーハンドリングを 実装しないで済むようにするということで合意しました。そして、

というパッチが Linux 4.17-rc2 にマージされました。

複雑な初期化処理の途中でエラーが発生したことに起因した参照カウントのバグや use-after-free バグを追いかけるのは大変なのです。実際、少量のメモリ割り当てが失敗した際のエラーハンドリングで苦労したために、 __GFP_NOFAIL を使うという修正が採用された事例はあります。 register_shrinker() に関しても、 __GFP_NOFAIL を使うことでエラーを返却しないようにするという提案が採用されていれば、ここまで苦労することは無かったのでしょうけれど・・・。

Memory allocation fault injection で直ちにクラッシュするような不具合なら、 syzbot が様々なテストケースを作ってくれるので、発見するのは簡単です。しかし、現実に起きる不具合はタイミングにも依存するため、発見することが難しいことがあります。例えば

というのは「 GFP フラグの指定を間違えるとデッドロックする、無理ゲーです。」に該当したケースでした。(幸いなことに、 khungtaskd カーネルスレッドが出力したメッセージが保存できていたことで、原因を突き止めることができました。)また、

というのは、メモリ割り当てが失敗しても大丈夫だと思って __GFP_NOWARN フラグを指定していたために、メモリ割り当てが失敗しただけでファイルにゴミデータが書き込まれてしまったというケースでした。どちらのケースも、空きメモリが枯渇したタイミングでしか発生しないため、誰も気が付きませんでした。「カーネルがクラッシュしたら不具合として報告します。」という syzbot 基準でのテストでは、発見できない不具合もあるのです。


7.2 事例2:ブロックレイヤーをめぐる障壁 その1

blk_queue_enter() という関数の中でハングアップするという不具合を syzbot が発見しましたが、誰も着手しようとしませんでした。

不具合が報告された時点で、既に reproducer が存在していたため、手元の環境で事象を再現させようと試みたのですが、再現させることができませんでした。そのため、ハングアップが検出されたタイミングで SysRq-t を取得するためのパッチを追加した状態で syzbot に事象を再現させた結果、犯人の可能性があるスレッドを4つに絞り込むことができました。

その後、 reproducer を改造することで手元の環境で事象を再現させることができるようになりました。そして、犯人の可能性があるスレッドの処理で使われている変数の値が、時間経過に伴い変化しているのかどうかを確認するためのパッチを追加して事象を再現させた結果、どの変数の値が想定外であるのかを突き止めることができました。

そのため、その変数の値が想定外となる理由を調べるパッチを追加して事象を再現させた結果、キューの参照カウントがいつまでも減らないことが原因であることが判明しました。しかし、何故減らないのかまでは突き止めることができませんでした。

その後もソースコードとの睨めっこを続けた結果、参照カウントが減らない理由を発見することができました。

ここまでくれば、あとはメンテナへと引き継ぐだけです。そして、この不具合は

というパッチが Linux 4.18-rc1 にマージされて解決しました。

という幸運が重なった結果とも言えます。


7.3 事例3:ブロックレイヤーをめぐる障壁 その2

wb_workfn() という関数の中でクラッシュするという不具合を syzbot が発見しましたが、誰も着手しようとしませんでした。

また、ほぼ同じタイミングで、 wb_shutdown() という関数の中でハングアップするという不具合を syzbot が発見しました。

そこで、ソースコードとの睨めっこを行った結果、ハングアップの原因を発見することができました。

そして、ハングアップする不具合に関しては、

というパッチが Linux 4.17-rc4 にマージされて解決しました。

また、クラッシュに関しては、 wb_shutdown() という関数が wb_workfn() という関数の処理が完了するのを待っていないという可能性が浮上し、メンテナがそのような処理を発見してくれました。

そして、クラッシュする不具合に関しては、

というパッチが Linux 4.17-rc4 にマージされて解決したと思われました。しかし、そのパッチの適用後も、同じ問題が発生することを syzbot が発見したのです。

どこに問題があるのか見当がつかず、まだ reproducer も見つかっていなかったため、デバッグ printk() パッチを適用した状態で syzbot にテストしてもらうことを提案しました。

多くの台数でテストした方が早く情報が得られることから、全てのテスト対象に共通している linux.git に適用されることが望まれます。しかし、第8章でも触れますが、後で削除することになるデバッグ printk() パッチを linux.git にマージすることは憚られました。

そして、幸いなことに、 linux-next.git が再びテスト対象となる前に、 Dmitry Vyukov さんの環境で事象を再現させることに成功したため、解析を進めることができました。

どう修正するかの議論を経て、この不具合は

というパッチが Linux 4.18-rc2 にマージされて解決しました。

ハングアップを修正するパッチでは clear_and_wake_up_bit() という関数が導入されたのですが、クラッシュを修正するためのパッチで処理を直列化/単純化したことにより、 clear_and_wake_up_bit() という関数は呼ばれなくなってしまいました。

syzbot が容赦なく不具合を発見していくので、それを修正するほうも大変です。


7.4 事例4: loop モジュールをめぐる迷宮 その1

loop モジュールに起因した不具合報告は、すぐに原因が判明して修正されたものから、何か月も原因が判らずに苦労したものまでいろいろあります。ここでは、 loop モジュール用の ioctl() の競合問題について紹介します。

排他制御が不適切であったことにより、 NULL pointer dereference や lockdep 警告が出るという報告がありました。しかし、ロックの依存関係が複雑すぎて、パッチという形になりませんでした。

試行錯誤しながら loop デバイスに対する ioctl() 操作を直列化するという提案を行いましたが、なかなか受け入れられませんでした。それくらい、複雑な問題でした。

どのように修正するかでずいぶんと待たされましたが、この不具合は

を含む一連のパッチが Linux 5.0-rc1 にマージされて解決しました。


7.5 事例5: loop モジュールをめぐる迷宮 その2

事例2で紹介した不具合が修正された後も、原因不明のハングアップ報告は続きました。その中から、 generic_file_write_iter() という関数の中でハングアップするという不具合について紹介します。

その当時は、ハングアップするという未解決の不具合が65件もあり、その内18件で __getblk_gfp() という関数がバックトレースに含まれていたため、 __getblk_gfp() の処理で何か想定外の状況が起きているのではないかと考えました。しかし、まだ reproducer が見つかっていなかったため、デバッグ printk() パッチを適用した状態で syzbot にテストしてもらったり、手元の環境で試行錯誤しながら調査したりするという手法を使えない状況でした。

そのため、変数の値を出力するパッチを linux-next.git に追加してもらうことで、問題が発生した時の状況を把握することを試みました。

その結果、無限ループに陥っており、 loop モジュールが関係しているのではないかということが判明しました。しかし、そこから4か月以上、進展はありませんでした。

事例4で紹介した不具合が修正された後も、この問題がまだ発生し続けていることを伝えたところ、メンテナから仮説が提示されました。

そのため、より多くの変数の値を出力するようにパッチを修正して、仮説が正しいかどうかの確認を行いました。その結果、仮説が正しかったことが判明し、同時に、手動で事象を再現するための手順も発見することができました。

そして、この不具合は

というパッチが Linux 5.0-rc3 にマージされて解決しました。

この不具合が解消されるまでに半年も要してしまったことから、同様の不具合が発生した際に迅速に検知できるように警告を出力するという提案がされました。しかし、それでも、迷宮は事例6へと続くのです。


7.6 事例6: loop モジュールをめぐる迷宮 その3

syzbot が __get_super() という関数の中でハングアップするという不具合を発見しました。しかし、この不具合の発生頻度が低く、誰も対処しようとしませんでした。

不具合が発見されてから1年以上忘れられていたある日のこと、遂に reproducer を syzbot が発見しました。

コンソールに出力されたメッセージからは、 __getblk_gfp() 関数が呼ばれていることから症状としては事例5と似ているが、 loop_ctl_mutex ロックを保持していないことから事例4とは無関係であることが判明しました。

幸いなことに、 reproducer を用いて手元の環境でも事象を再現できたため、事例5で用いたのと同様のデバッグ printk() パッチを適用して、何が起こっているのかを調査しました。その結果、事例5と同様の状況が発生していることが確認されました。

この結果をメンテナに伝えたところ、発生のメカニズムが説明され、パッチが提案されました。

そして、この不具合は

というパッチが Linux 5.2-rc3 にマージされて解決しました。

・・・と思っていたら、このパッチに起因したリグレッション報告が上がってきました。(しかも、迷惑メールフィルタによりゴミ箱へ送られていたため、気づかずに削除してしまっていました。ごめんなさい。)

競合状態を回避するために排他ロックをかけたのですが、それが原因でマウント処理が失敗するようになってしまったようです。この不具合は

というパッチが Linux 5.3-rc3 にマージされて解決しました。

・・・と思っていたら、このパッチに起因した不具合報告が上がってきました。

幸い、単純な見落としだったので、

というパッチが Linux 5.3-rc4 にマージされて解決しました。いやぁ、迷宮攻略は難しいですねぇ・・・。

ちなみに、 loop: Don't change loop device under exclusive opener というパッチの影響は mount(2) がエラーを返却するようになることであったため、 syzbot では発見できませんでした。それに対して、 loop: Fix mount(2) failure due to race with LOOP_SET_FD というパッチの影響は WARN_ON() が呼ばれるようになることであったため、 syzbot でも発見することができました。このように、「この順序で呼ばれたシステムコールが失敗するのは正しくない」という意味まで考えて不具合かどうかを判断することは、「カーネルがクラッシュしたら不具合として報告します。」という syzbot 基準でのテストではできません。しかし、「この順序で呼ばれたシステムコールは成功する筈である」という意味まで考えて行うリグレッションテスト用プログラムは、 syzbot が行うようなマルチスレッドなテストケースを試すようには作られていません。結局、最後は人間が判断せざるを得ないようです。


第8章 syzbot 自身の改善のための試行錯誤について


熊猫自身は go 言語および syzbot の構造に疎いので、 syzbot 自身の改善のための直接的な関与はしていませんが、改善のための提案はしています。OSSの良いところは、誰でも現状を知ってコメントできることです。どんどん参加して意見を述べましょう。

自動化と手作業の組合せについて

2018年3月に syzbot dashboard が公開されるまでは、不具合の修正状況を閲覧する方法が無く、状況を把握することが困難でした。

syzbot dashboard の公開後も、不具合が発見されてから解析されてパッチが作成されるまでの期間が長くなりがちである(不具合の原因を解析して修正することへの優先度が低く、コミュニティによるベストエフォート対応であることから状況共有を徹底できないことに起因した無駄な作業が発生してしまう)ことから、現在の状況をキーワードで入力できるようにするという提案を行いました。しかし、まだ採用されていません。

デバッグ printk() パッチの利用について

早い段階で不具合が発見されるほど望ましいことから、どの git tree に対してファジングテストを行うべきかという議論がありました。

linux-next.git は syzbot によるテストの対象だったのですが、2018年1月に対象から外されていました。その後、デバッグ printk() パッチを用いないと情報を取得できそうにない不具合が出てきたのですが、デバッグ printk() パッチを linux.git にマージすることが憚られたため、 linux-next.git でデバッグ printk() パッチを使えるようにできないかが検討されました。

そして、2018年7月に再び linux-next.git が syzbot のテストの対象に加えられ、デバッグ printk() パッチが linux-next.git 上で使えるようになり、いくつかの不具合の原因を突き止めることができました。

スレッドへの参加/脱退機能について

syzbot が不具合の内容から関係者であろうと判断したり、 syzbot が報告した不具合のスレッドに返信したりすると、自動的にメールの送信先一覧に加えられます。しかし、脱退する方法が無かったため、自分には関係ない/どうすることもできない内容であったとしても、メールを受信しないようにする方法がありませんでした。そのため、送信先一覧に参加/送信先一覧から脱退する機能を実装できないかという提案を行いました。

そして、2019年3月に、送信先一覧から脱退する機能が実装されました。

コンソール出力のフォーマットについて

syzbot で試みられたテストケースは、カーネルが printk() 関数により出力したメッセージと一緒に、コンソール出力の中に含まれています。そして、試みられたテストケースは syzkaller 表記のプログラムとして含まれており、そのプログラムを syz-prog2c というプログラムに渡すことで、C言語のプログラムとして処理内容を確認することができるようになっています。しかし、 printk() 関数により大量のカーネルメッセージが出力されてしまうことから、すべてのコンソール出力を保存しておくことは現実的ではありません。そのため、コンソール出力を保持するファイルにはサイズの上限が設定されています。

しかし、第4章で説明した OOM killer のように、意図しないカーネルメッセージの大量発生により、 syzkaller 表記のプログラム部分が完全に押し流されてしまい、どのようなテストケースが試みられたのかを確認できくなるケースがあります。反対に、 syzkaller 表記のプログラムが大部分を占めてしまうことにより、問題が発生する直前のカーネルメッセージを見つけ出すことが面倒になるというケースもあります。

そのため、コンソール出力を保持するファイルを構造化することで、テストケースの流失防止やカーネルメッセージの検索性向上を図れないかという提案を行いました。しかし、まだ採用されていません。

syzbot が git bisect することについて

syzbot が reproducer を発見したとしても、競合状態に起因した不具合である場合、再現成功率が低くなるケースがあります。そのため、 reproducer の信頼性をチェックできないかという提案がありました。

2019年3月から、 reproducer が見つかった不具合に関して、不具合の原因となったパッチを特定( git bisect )する試みを始めました。しかし、同じ不具合が様々な形で現れることがあるため、クラッシュの有無だけで判定( git bisect good / git bisect bad )する方法では、他の不具合との区別がつかないという問題があります。また、タイミング依存であったり、 reproducer を使っても簡単には再現できないケースもあったりするため、自動で特定するのは難しいという現実があります。完全に解決するのは無理ですが、テストの回数を増やすなど、信頼性を高めるための工夫が行われています。

修正されたパッチを自動検出することについて

不具合を修正するパッチをマージする際に、 syzbot が発見した不具合であることを記さなかったために、いつまでも open 状態のままになってしまう報告が多数発生してしまいました。そのため、一定期間再現しなかった不具合に関して、 reproducer が見つかっていないものについては自動で close するようになりました。また、 reproducer が見つかっているものについては不具合を修正したパッチを検出するために逆方向の git bisection を行うことを提案しました。

その結果、逆方向の git bisection を行う機能が実装されました。しかし、順方向の git bisection を正確に判定することが難しいことからも判るように、逆方向の git bisection も正確に判定することが難しいです。

任意のアドレスをシンボル化するCGIサービスについて

syzbot の dashboard からは、テストに使用したカーネルのコミットやカーネルコンフィグなど、同じ環境を構築するのに必要な情報を得ることができます。しかし、現実には、同じ環境を用意して再現を行うのは大きな負担です。

syzbot は、レポートに含まれるノイズを削減するために、コンソール出力に含まれているバックトレースの内、 ? が含まれる行を除外するようにしています。しかし、時には ? が含まれている行の情報が欲しくなることもあります。そして、 ? が含まれている行のアドレスに対応するソースコード上の位置を計算するために、同じ環境を用意してもらうというのは現実的ではありません。

そのため、 syzbot がテストに使用したカーネルを一定期間保持しておき、利用者からの要求に応じてアドレスに対応するソースコード上の位置を計算するCGIのようなサービスを提供できないかという提案を行いました。


第9章 TOMOYO Linux に関する出来事について


第2章では Linux 5.1 における printk() の改善についての話をしました。 Linux 5.1 には、 TOMOYO と SELinux / Smack / AppArmor の何れかとを同時に利用できるようになったという改善も含まれています。(セキュリティ・キャンプ2017の講義資料の「LSMの歴史について知る。」で紹介されているように、現在は「どのような組み合わせでも正常に動くようにインフラとして整備する」計画が進行中です。)ここでは、 TOMOYO を syzbot のテスト対象に加えてもらったことに関連する出来事について紹介します。

テスト対象が SELinux から AppArmor へ変更された

Linux Security Summit での議論を経て、 syzbot がテストを行うカーネルで有効にするLSMモジュールが SELinux から AppArmor に変更されました。アクセス制御を行うための初期設定が行われて適切なポリシーがロードされない限り、アクセス制御モジュールは素通しまたはブロックしてしまいます。 SELinux のリグレッションによりテストに必要なファイルシステムをマウントできなくなったため、 SELinux から AppArmor への変更が行われたようです。

テスト対象として SELinux が復活し、 Smack も追加された

その後、 SELinux のリグレッションが修正されたことにより、 SELinux 向けのインスタンスが復活しました。

SELinux 向けのインスタンスが復活したことを受けて、 Smack 向けのインスタンスも作成してほしいという要望が上がりました。

その結果、 SELinux 向け/ Smack 向け/ AppArmor 向けのインスタンスが提供されるようになりました。

しかし、熊猫は、 TOMOYO 向けのインスタンスを作成してほしいという要望を出しませんでした。なぜなら、LSMモジュール毎に専用のインスタンスを用意する必要があると、それぞれのLSMモジュールをテストするためのリソースが分散してしまい、不具合や reproducer を発見するペースが遅くなることを懸念したためです。

テスト対象として TOMOYO の追加を依頼した

Linux 5.1 で TOMOYO とそれ以外の同時利用がサポートされることになったため、 TOMOYO を syzbot のテスト対象に加えてもらう要望を上げました。(注:この時点ではまだ Linux 5.1 はリリースされておらず、 Linux 5.1 に向けたテストを行うための linux-next.git が対象でした。)

従来は SELinux / Smack / TOMOYO / AppArmor はお互いに排他的であったため、どのLSMモジュールを有効にするかを security= というカーネルコマンドライン引数を用いて指定していました。それに対して、 TOMOYO と SELinux / Smack / AppArmor の何れかを同時に有効にするために、有効にする全てのLSMモジュールを指定するための lsm= というカーネルコマンドライン引数が追加されました。しかし、 syzbot でテストを行うにあたり、 security= というパラメータと lsm= というパラメータの両方が指定できてしまうと、どのLSMモジュールを有効にするかの解釈で矛盾が発生することが発覚しました。この問題を回避するため、 syzbot がテストを行うためのカーネルをビルドする場合には、 lsm= というパラメータを優先するために security= というパラメータを無視させるという提案を行いました。

しかし、 lsm= パラメータについて説明するために TOMOYO の手順書をアップデートしてみたところ、 syzbot とは関係なく、常に lsm= というパラメータを優先させる方が好都合なのではないかと考えるようになりました。

すると、他の人もこの問題意識を持っていたことが判明し、 lsm= というパラメータが指定された場合には security= というパラメータを無視するという修正が採用されました。これにより、 syzbot は、カーネルのコマンドラインに security= パラメータと lsm= パラメータの両方を指定することにより、 lsm= パラメータに対応済みのカーネルであれば TOMOYO も有効な状態で、 lsm= パラメータに未対応のカーネルであれば TOMOYO が無効な状態でテストを行えるようになりました。

リリースしてしまうと修正ができなくなる「利用者に見える仕様変更」の問題点を、 syzbot が複数の git tree をテストしていてくれたおかげで、リリース前に発見して解決することができた訳です。

ポリシー読み込み前のメモリ割り当て失敗によるカーネルパニック

TOMOYO の場合、ユーザランドを無修正で動かせるようにするために、特定のパス名の実行が要求されたタイミングでポリシーを読み込むためのプログラムを呼び出します。そのため、ポリシーを読み込むまでの間のメモリ割り当て処理の失敗は、カーネルパニックによりシステムを停止させることで、アクセス制御が無効なままシステムが起動しないようにしています。

ポリシーを読み込むまではアクセス制御が無効なままなので、 syzbot によるファジングテストをさせても大丈夫だと考えていました。しかし、ポリシーを読み込む前のメモリ割り当て処理が失敗するとクラッシュするという問題を syzbot は発見しました。

アクセス制御が無効なままシステムが起動しないようにすること自体は問題ないのですが、それによって syzbot によるファジングテストができなくなってしまっては困ります。そのため、 TOMOYO の管理ツールとポリシーをファイルシステムイメージに追加できないかどうかを考えましたが、カーネルだけで動作できるようになっていないと非現実的だということが判明しました。そのため、ファジングテストを行う場合のみ選択すべき CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING というカーネルコンフィグオプションを追加するという修正が行われました。

このカーネルコンフィグオプションを syzbot が有効にすることで、最小限のポリシーをカーネル内に埋め込み、 TOMOYO が学習モードで動作するようになりました。

また、 syzbot は、 WARNING: という文字列が出力されるとクラッシュしたと判断してしまう(深刻度を判断できない)ため、 WARNING: という文字列を出力させない修正が行われました。

間違った判断をしたレポートの例

CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING が Linux 5.2-rc1 に取り込まれて TOMOYO が学習モードで動作できるようになったことで、 TOMOYO の処理が含まれるレポートが上がってくるようになりました。

一見すると tomoyo_realpath_from_path() 関数の不具合に起因した問題のように見えるかもしれませんが、ソースコードをよく読むと、対象のメモリ領域を複数のスレッド間で共有していないため double-free になることは無く、また、ポインタ変数が記憶しているアドレスの変更もしていないため invalid-free になることも無いので、 tomoyo_realpath_from_path() 関数自身の不具合ではないと判断することができます。このような場合、他の不具合の巻き添えを食らったと考えられますので、 reproducer が見つかるのを待つしかありません。

バックトレース内に TOMOYO に関連する処理が含まれておらず、関数ポインタ経由で呼ばれることのない tomoyo_domain_quota_is_ok() 関数の中でクラッシュしています。これも、他の不具合の巻き添えを食らったと考えられます。

TOMOYO は権限のチェックやログ取得のためにメモリの割り当て処理を必要とします。しかし、 Memory allocation fault injection を使用した reproducer であったため、上述した CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING を追加するパッチが bisection の範囲に含まれていたことにより、 bisection に失敗したようです。 https://github.com/google/syzkaller/blob/master/docs/syzbot.md#bisection で説明されているように、 bisection はいろいろな要因により失敗することがあります。

初回のクラッシュ時に出力されたトレースの中に TOMOYO 関連の関数が含まれていたため、 TOMOYO の不具合であると勘違いされたようです。しかし、2回目のクラッシュ時には、そもそもトレースが表示されていない/プロセスIDが異常な数値を示している/スタックオーバーフローが報告されているなど、出力内容を信用できない状況です。

これも、 use-after-free を検出したタイミングが、たまたま TOMOYO 関連の関数を実行中であっただけであると考えられます。コンソールに出力されたログを確認すると、同じタイミングで別の関数でも use-after-free が検出されています。第2章で紹介した修正の成果により不具合が発生したことを見落とさないで済んだのですが、残念ながら被疑個所を自動で判断することはできませんでした。

[  625.441058][    C0] ------------[ cut here ]------------
[  625.441625][ T2063] ==================================================================
[  625.446837][    C0] refcount_t: increment on 0; use-after-free.
[  625.455080][ T2063] BUG: KASAN: use-after-free in tomoyo_socket_sendmsg_permission+0x37e/0x3cb
[  625.455094][ T2063] Read of size 2 at addr ffff8880a066f410 by task syz-executor.3/2063
[  625.455099][ T2063] 
[  625.455115][ T2063] CPU: 1 PID: 2063 Comm: syz-executor.3 Not tainted 5.2.0+ #97
[  625.455131][ T2063] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[  625.461518][    C0] WARNING: CPU: 0 PID: 0 at lib/refcount.c:156 refcount_inc_checked+0x61/0x70
[  625.470304][ T2063] Call Trace:
[  625.479173][    C0] Kernel panic - not syncing: panic_on_warn set ...
[  625.481504][ T2063]  dump_stack+0x172/0x1f0
[  625.523601][ T2063]  ? tomoyo_socket_sendmsg_permission+0x37e/0x3cb
[  625.530019][ T2063]  print_address_description.cold+0xd4/0x306
[  625.536002][ T2063]  ? tomoyo_socket_sendmsg_permission+0x37e/0x3cb
[  625.542420][ T2063]  ? tomoyo_socket_sendmsg_permission+0x37e/0x3cb
[  625.549083][ T2063]  __kasan_report.cold+0x1b/0x36
[  625.554027][ T2063]  ? tomoyo_socket_sendmsg_permission+0x37e/0x3cb
[  625.560452][ T2063]  kasan_report+0x12/0x17
[  625.564789][ T2063]  __asan_report_load2_noabort+0x14/0x20
[  625.570425][ T2063]  tomoyo_socket_sendmsg_permission+0x37e/0x3cb
[  625.576687][ T2063]  ? tomoyo_socket_bind_permission+0x360/0x360
[  625.582977][ T2063]  ? ksys_dup3+0x3e0/0x3e0
[  625.587419][ T2063]  ? mark_lock+0xc0/0x11e0
[  625.591838][ T2063]  ? do_futex+0x17d/0x1dc0
[  625.596369][ T2063]  tomoyo_socket_sendmsg+0x26/0x30
[  625.601560][ T2063]  security_socket_sendmsg+0x77/0xc0
[  625.606851][ T2063]  sock_sendmsg+0x45/0x130
[  625.611755][ T2063]  __sys_sendto+0x262/0x380
[  625.616264][ T2063]  ? __ia32_sys_getpeername+0xb0/0xb0
[  625.621658][ T2063]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[  625.627908][ T2063]  ? put_timespec64+0xda/0x140
[  625.632667][ T2063]  ? nsecs_to_jiffies+0x30/0x30
[  625.637529][ T2063]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[  625.642990][ T2063]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[  625.648451][ T2063]  ? do_syscall_64+0x26/0x6a0
[  625.653229][ T2063]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  625.659388][ T2063]  __x64_sys_sendto+0xe1/0x1a0
[  625.664185][ T2063]  do_syscall_64+0xfd/0x6a0
[  625.668724][ T2063]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  625.674610][ T2063] RIP: 0033:0x459829
[  625.678532][ T2063] Code: fd b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 cb b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00
[  625.698137][ T2063] RSP: 002b:00007f8413a51c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
[  625.706555][ T2063] RAX: ffffffffffffffda RBX: 0000000000000006 RCX: 0000000000459829
[  625.714628][ T2063] RDX: 00000000000000ed RSI: 0000000020000280 RDI: 0000000000000005
[  625.722597][ T2063] RBP: 000000000075bfc8 R08: 0000000000000000 R09: 0000000000000000
[  625.730560][ T2063] R10: 0000000000000000 R11: 0000000000000246 R12: 00007f8413a526d4
[  625.738545][ T2063] R13: 00000000004c77f1 R14: 00000000004dcfc0 R15: 00000000ffffffff
[  625.746543][ T2063] 
[  625.746558][    C0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.2.0+ #97
[  625.746575][    C0] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[  625.748887][ T2063] Allocated by task 0:
[  625.755731][    C0] Call Trace:
[  625.766036][ T2063]  save_stack+0x23/0x90
[  625.770091][    C0]  <IRQ>
[  625.773374][ T2063]  __kasan_kmalloc.constprop.0+0xcf/0xe0
[  625.773393][ T2063]  kasan_kmalloc+0x9/0x10
[  625.777543][    C0]  dump_stack+0x172/0x1f0
[  625.780380][ T2063]  __kmalloc+0x163/0x770
[  625.786005][    C0]  ? refcount_inc_not_zero_checked+0x1f0/0x200
[  625.790511][ T2063]  sk_prot_alloc+0x23a/0x310
[  625.794831][    C0]  panic+0x2dc/0x755
[  625.799054][ T2063]  sk_alloc+0x39/0xf70
[  625.805217][    C0]  ? add_taint.cold+0x16/0x16
[  625.809792][ T2063]  nr_rx_frame+0x733/0x1e73
[  625.813697][    C0]  ? __kasan_check_write+0x14/0x20
[  625.817744][ T2063]  nr_loopback_timer+0x7b/0x170
[  625.817767][ T2063]  call_timer_fn+0x1ac/0x780
[  625.822433][    C0]  ? __warn.cold+0x5/0x4c
[  625.827286][ T2063]  run_timer_softirq+0x697/0x17a0
[  625.832388][    C0]  ? __warn+0xe7/0x1e0
[  625.837219][ T2063]  __do_softirq+0x262/0x98c
[  625.837230][ T2063] 
[  625.841820][    C0]  ? refcount_inc_checked+0x61/0x70
[  625.846114][ T2063] Freed by task 2063:
[  625.846135][ T2063]  save_stack+0x23/0x90
[  625.851148][    C0]  __warn.cold+0x20/0x4c
[  625.855205][ T2063]  __kasan_slab_free+0x102/0x150
[  625.859701][    C0]  ? vprintk_emit+0x1ea/0x700
[  625.862022][ T2063]  kasan_slab_free+0xe/0x10
[  625.867208][    C0]  ? refcount_inc_checked+0x61/0x70
[  625.871251][ T2063]  kfree+0x10a/0x2c0
[  625.871270][ T2063]  __sk_destruct+0x4f7/0x6e0
[  625.875413][    C0]  report_bug+0x263/0x2b0
[  625.879640][ T2063]  sk_destruct+0x86/0xa0
[  625.884580][    C0]  do_error_trap+0x11b/0x200
[  625.889239][ T2063]  __sk_free+0xfb/0x360
[  625.893730][    C0]  do_invalid_op+0x37/0x50
[  625.898940][ T2063]  sk_free+0x42/0x50
[  625.898958][ T2063]  sock_efree+0x61/0x80
[  625.902936][    C0]  ? refcount_inc_checked+0x61/0x70
[  625.907545][ T2063]  skb_release_head_state+0xeb/0x250
[  625.911858][    C0]  invalid_op+0x14/0x20
[  625.916198][ T2063]  skb_release_all+0x16/0x60
[  625.920825][    C0] RIP: 0010:refcount_inc_checked+0x61/0x70
[  625.924988][ T2063]  kfree_skb+0x101/0x3c0
[  625.929407][    C0] Code: 1d 3f 6e 64 06 31 ff 89 de e8 cb d2 35 fe 84 db 75 dd e8 82 d1 35 fe 48 c7 c7 40 09 c6 87 c6 05 1f 6e 64 06 01 e8 77 39 07 fe <0f> 0b eb c1 90 90 90 90 90 90 90 90 90 90 90 55 48 89 e5 41 57 41
[  625.933414][ T2063]  nr_accept+0x56e/0x700
[  625.933437][ T2063]  __sys_accept4+0x34e/0x6a0
[  625.937608][    C0] RSP: 0018:ffff8880ae809bf0 EFLAGS: 00010282
[  625.942815][ T2063]  __x64_sys_accept+0x75/0xb0
[  625.948510][    C0] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[  625.952664][ T2063]  do_syscall_64+0xfd/0x6a0
[  625.957237][    C0] RDX: 0000000000000100 RSI: ffffffff815c3a26 RDI: ffffed1015d01370
[  625.963034][ T2063]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  625.967249][    C0] RBP: ffff8880ae809c00 R08: ffffffff88c7a1c0 R09: fffffbfff14a775b
[  625.987299][ T2063] 
[  625.991542][    C0] R10: fffffbfff14a775a R11: ffffffff8a53bad7 R12: ffff8880a066f480
[  625.996126][ T2063] The buggy address belongs to the object at ffff8880a066f400
[  625.996126][ T2063]  which belongs to the cache kmalloc-2k of size 2048
[  626.002193][    C0] R13: ffff8880a066f468 R14: ffff88808d69ef48 R15: ffff88808d69ef20
[  626.006852][ T2063] The buggy address is located 16 bytes inside of
[  626.006852][ T2063]  2048-byte region [ffff8880a066f400, ffff8880a066fc00)
[  626.006863][ T2063] The buggy address belongs to the page:
[  626.014844][    C0]  ? vprintk_func+0x86/0x189
[  626.019324][ T2063] page:ffffea0002819b80 refcount:1 mapcount:0 mapping:ffff8880aa400e00 index:0x0 compound_mapcount: 0
[  626.027298][    C0]  nr_insert_socket+0x2d/0xe0
[  626.033173][ T2063] flags: 0x1fffc0000010200(slab|head)
[  626.041237][    C0]  nr_rx_frame+0x1605/0x1e73
[  626.043652][ T2063] raw: 01fffc0000010200 ffffea0001849388 ffffea000235a788 ffff8880aa400e00
[  626.051737][    C0]  nr_loopback_timer+0x7b/0x170
[  626.065772][ T2063] raw: 0000000000000000 ffff8880a066e300 0000000100000003 0000000000000000
[  626.073842][    C0]  call_timer_fn+0x1ac/0x780
[  626.087335][ T2063] page dumped because: kasan: bad access detected
[  626.092970][    C0]  ? nr_process_rx_frame+0x1540/0x1540
[  626.097614][ T2063] 
[  626.108552][    C0]  ? msleep_interruptible+0x150/0x150
[  626.113204][ T2063] Memory state around the buggy address:
[  626.118574][    C0]  ? run_timer_softirq+0x685/0x17a0
[  626.123136][ T2063]  ffff8880a066f300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  626.131811][    C0]  ? trace_hardirqs_on+0x67/0x240
[  626.136646][ T2063]  ffff8880a066f380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  626.145424][    C0]  ? __kasan_check_read+0x11/0x20
[  626.149993][ T2063] >ffff8880a066f400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  626.156592][    C0]  ? nr_process_rx_frame+0x1540/0x1540
[  626.162035][ T2063]                          ^
[  626.164362][    C0]  ? nr_process_rx_frame+0x1540/0x1540
[  626.169796][ T2063]  ffff8880a066f480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  626.175423][    C0]  run_timer_softirq+0x697/0x17a0
[  626.180682][ T2063]  ffff8880a066f500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  626.188804][    C0]  ? add_timer+0x930/0x930
[  626.194583][ T2063] ==================================================================
[  626.202652][    C0]  ? kvm_clock_read+0x18/0x30
[  626.207660][ T2063] Disabling lock debugging due to kernel taint
[  626.215813][    C0]  ? kvm_sched_clock_read+0x9/0x20
[  626.227916][ T2063] ------------[ cut here ]------------
[  626.231378][    C0]  ? sched_clock+0x2e/0x50
[  626.231395][    C0]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  626.231408][    C0]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  626.231432][    C0]  __do_softirq+0x262/0x98c
[  626.239548][ T2063] refcount_t: addition on 0; use-after-free.
[  626.244512][    C0]  ? sched_clock_cpu+0x1b/0x1b0
[  626.244531][    C0]  irq_exit+0x19b/0x1e0
[  626.244545][    C0]  smp_apic_timer_interrupt+0x1a3/0x610
[  626.244558][    C0]  apic_timer_interrupt+0xf/0x20
[  626.244563][    C0]  </IRQ>
[  626.244579][    C0] RIP: 0010:native_safe_halt+0xe/0x10
[  626.244606][    C0] Code: b8 94 73 fa eb 8a 90 90 90 90 90 90 e9 07 00 00 00 0f 00 2d 34 25 4f 00 f4 c3 66 90 e9 07 00 00 00 0f 00 2d 24 25 4f 00 fb f4 <c3> 90 55 48 89 e5 41 57 41 56 41 55 41 54 53 e8 0e 56 27 fa e8 c9
[  626.256168][ T2063] WARNING: CPU: 1 PID: 2063 at lib/refcount.c:105 refcount_add_checked+0x6b/0x70
[  626.257081][    C0] RSP: 0018:ffffffff88c07ce8 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
[  626.265143][ T2063] Modules linked in:
[  626.269812][    C0] RAX: 1ffffffff11a5e05 RBX: ffffffff88c7a1c0 RCX: 0000000000000000
[  626.275963][ T2063] CPU: 1 PID: 2063 Comm: syz-executor.3 Tainted: G    B             5.2.0+ #97
[  626.281053][    C0] RDX: dffffc0000000000 RSI: 0000000000000006 RDI: ffffffff88c7aa4c
[  626.286510][ T2063] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
[  626.290913][    C0] RBP: ffffffff88c07d18 R08: ffffffff88c7a1c0 R09: 0000000000000000
[  626.297153][ T2063] RIP: 0010:refcount_add_checked+0x6b/0x70
[  626.303361][    C0] R10: 0000000000000000 R11: 0000000000000000 R12: dffffc0000000000
[  626.308134][ T2063] Code: 1d e7 77 64 06 31 ff 89 de e8 71 dc 35 fe 84 db 75 db e8 28 db 35 fe 48 c7 c7 20 08 c6 87 c6 05 c7 77 64 06 01 e8 1d 43 07 fe <0f> 0b eb bf 90 48 b8 00 00 00 00 00 fc ff df 55 48 89 e5 41 54 49
[  626.314081][    C0] R13: ffffffff89a4f778 R14: 0000000000000000 R15: 0000000000000000
[  626.314116][    C0]  ? default_idle+0x4e/0x360
[  626.318928][ T2063] RSP: 0018:ffff88805d55f9f8 EFLAGS: 00010286
[  626.323075][    C0]  arch_cpu_idle+0xa/0x10
[  626.328606][ T2063] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[  626.333543][    C0]  default_idle_call+0x84/0xb0
[  626.336460][ T2063] RDX: 0000000000040000 RSI: ffffffff815c3a26 RDI: ffffed100baabf31
[  626.341839][    C0]  do_idle+0x413/0x760
[  626.361617][ T2063] RBP: ffff88805d55fa10 R08: ffff888098124480 R09: fffffbfff1349ef0
[  626.370736][    C0]  ? retint_kernel+0x2b/0x2b
[  626.379145][ T2063] R10: fffffbfff1349eef R11: ffffffff89a4f77f R12: 0000000000000500
[  626.383044][    C0]  ? arch_cpu_idle_exit+0x80/0x80
[  626.391005][ T2063] R13: ffff8880a066f644 R14: ffff88808f271e60 R15: 00000000000000ed
[  626.400071][    C0]  ? do_idle+0x387/0x760
[  626.408029][ T2063] FS:  00007f8413a52700(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000
[  626.418085][    C0]  cpu_startup_entry+0x1b/0x20
[  626.426030][ T2063] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  626.431835][    C0]  rest_init+0x245/0x37b
[  626.439804][ T2063] CR2: 000000000075c000 CR3: 0000000097173000 CR4: 00000000001406e0
[  626.459420][    C0]  arch_call_rest_init+0xe/0x1b
[  626.467383][ T2063] Call Trace:
[  626.471993][    C0]  start_kernel+0x912/0x951
[  626.478069][ T2063]  skb_set_owner_w+0x216/0x320
[  626.482387][    C0]  ? mem_encrypt_init+0xb/0xb
[  626.490354][ T2063]  sock_alloc_send_pskb+0x7c9/0x920
[  626.495105][    C0]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  626.503078][ T2063]  ? mark_held_locks+0xf0/0xf0
[  626.507125][    C0]  ? x86_family+0x41/0x50
[  626.515109][ T2063]  ? proto_register+0x8f0/0x8f0
[  626.519773][    C0]  ? __sanitizer_cov_trace_const_cmp1+0x1a/0x20
[  626.527830][ T2063]  ? lock_sock_nested+0x9a/0x120
[  626.532837][    C0]  x86_64_start_reservations+0x29/0x2b
[  626.540799][ T2063]  ? trace_hardirqs_on+0x67/0x240
[  626.545019][    C0]  x86_64_start_kernel+0x77/0x7b
[  626.553970][ T2063]  ? lock_sock_nested+0x9a/0x120
[  626.558711][    C0]  secondary_startup_64+0xa4/0xb0
[  626.565296][ T2063]  sock_alloc_send_skb+0x32/0x40
[  626.667023][ T2063]  nr_sendmsg+0x557/0xb00
[  626.671351][ T2063]  ? nr_accept+0x700/0x700
[  626.675765][ T2063]  ? aa_sock_msg_perm.isra.0+0xba/0x170
[  626.681304][ T2063]  ? apparmor_socket_sendmsg+0x2a/0x30
[  626.686766][ T2063]  ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[  626.693006][ T2063]  ? security_socket_sendmsg+0x8d/0xc0
[  626.698467][ T2063]  ? nr_accept+0x700/0x700
[  626.702917][ T2063]  sock_sendmsg+0xd7/0x130
[  626.707341][ T2063]  __sys_sendto+0x262/0x380
[  626.711857][ T2063]  ? __ia32_sys_getpeername+0xb0/0xb0
[  626.717500][ T2063]  ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[  626.724123][ T2063]  ? put_timespec64+0xda/0x140
[  626.728884][ T2063]  ? nsecs_to_jiffies+0x30/0x30
[  626.734222][ T2063]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[  626.740592][ T2063]  ? trace_hardirqs_on_thunk+0x1a/0x1c
[  626.746045][ T2063]  ? do_syscall_64+0x26/0x6a0
[  626.751035][ T2063]  ? entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  626.757532][ T2063]  __x64_sys_sendto+0xe1/0x1a0
[  626.762499][ T2063]  do_syscall_64+0xfd/0x6a0
[  626.767002][ T2063]  entry_SYSCALL_64_after_hwframe+0x49/0xbe
[  626.773183][ T2063] RIP: 0033:0x459829
[  626.777256][ T2063] Code: fd b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 cb b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00
[  626.797748][ T2063] RSP: 002b:00007f8413a51c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
[  626.806565][ T2063] RAX: ffffffffffffffda RBX: 0000000000000006 RCX: 0000000000459829
[  626.815329][ T2063] RDX: 00000000000000ed RSI: 0000000020000280 RDI: 0000000000000005
[  626.823448][ T2063] RBP: 000000000075bfc8 R08: 0000000000000000 R09: 0000000000000000
[  626.831523][ T2063] R10: 0000000000000000 R11: 0000000000000246 R12: 00007f8413a526d4
[  626.839575][ T2063] R13: 00000000004c77f1 R14: 00000000004dcfc0 R15: 00000000ffffffff
[  626.847962][ T2063] irq event stamp: 344
[  626.852036][ T2063] hardirqs last  enabled at (343): [<ffffffff8100a206>] do_syscall_64+0x26/0x6a0
[  626.861680][ T2063] hardirqs last disabled at (344): [<ffffffff87391ddf>] _raw_spin_lock_irqsave+0x6f/0xcd
[  626.872476][ T2063] softirqs last  enabled at (314): [<ffffffff858fb1b6>] release_sock+0x156/0x1c0
[  626.881602][ T2063] softirqs last disabled at (312): [<ffffffff858fb080>] release_sock+0x20/0x1c0
[  626.890614][ T2063] ---[ end trace 2fe47c842e5d598a ]---
[  626.897092][    C0] Kernel Offset: disabled
[  626.901428][    C0] Rebooting in 86400 seconds..

正しい判断をしたレポートの例

もちろん、 TOMOYO の処理に起因した不具合も発見されるようになりました。

これらは、既に報告された不具合を修正するための一連のパッチの内、LSM向けのパッチが Linux 5.2-rc1 までマージされなかったため、 syzbot が報告してくれたというケースでした。

また、想定外の競合状態に起因した不具合を報告してくれたというケースもあります。iノードが存在している間はソケットの情報にアクセスできることを期待していたのですが、実際にはiノードが存在していてもソケットの情報が既に消滅している状況が発生していることが判明しました。この不具合は、タイミングがシビアであるため、 reproducer を発見したものの、 bisection に失敗したようです。

最初はどのように修正すべきか悩みましたが、すぐにファイルシステムのスペシャリストからのレスポンスが来ることを期待できるような不具合ではありません。そのため、ソケットに対する open および getattr パーミッションをチェックしないようにすることが最も実用的だと考えて、パッチを提案しました。

syzbot は、あっという間に不具合を発見してきます。さすがですね。


第10章 まとめ「脱優先度な生き方」


如何でしたでしょうか?この講義では、熊猫の体験談の一部について紹介しました。熊猫も全部の不具合を追いかけている訳ではありませんし、熊猫が関係した不具合でも説明するのが難しすぎて取り上げなかったものもあります。

syzbot では、テストケースの作成と実行にとどまらず、問題を判別しようとしたり、原因となったパッチの特定を試みたりもするなど、可能な限り「自動化」を目指しているようです。ある意味、どこまで自動化できるかの挑戦と呼べるかもしれません。しかし、意外に思われたかもしれませんが、大規模な自動化テストの裏側には、実は、何か想定外の事態が起きていないかを常に注意深く見守り続ける「気配り」という、自動化できない領域がありました。

問題の原因を分析して修正していくのは、現在のところ人間にしかできない作業です。不具合が報告されてから何か月も放置されてしまったり、パッチを提案してもなかなかレビューされなかったりという、「素早く反応してくれることが御馳走」という世界で、地道に対応を続けました。その結果、多数の不具合の修正や printk() の改善を通じて syzbot を軌道に乗せることに協力してくれたことへのお礼として、 Google Open Source Peer Bonus を受賞( https://opensource.googleblog.com/2019/04/google-open-source-peer-bonus-winners.html )してしまいました。

物事に優先度を付けて行動することの重要さを説く話はよく聞きます。しかし、優先度が高い問題から解決していると、「何とかなるものだ」と思われて、それが当たり前になってしまいます。優先度ばかりに縛られていると、どのような問題が存在しているのかさえ見えなくなり、どんどん問題が増えていくものです。優先度を無視して全力で動けるという自由度のある人は少ないと思いますが、どのような問題があるのかを各人が知り、自分の担当でなくてもできる範囲で協力するという姿勢を忘れないでほしいです。