2016年12月31日

Linux 4.9 が封印解除されたけれども・・・

今年はずっと「 Linux カーネルのメモリ管理機構の闇」と戦い続けてきました。

Linux カーネルのメモリ管理機構は「他の誰かが自分のために進捗を出してくれているから自分は余計なことを考えなくていい」という楽観論で動いています。そして、全員が同じ考えで動いたとき、誰も進捗を出せなくなり、システムは静かにハングアップしてしまいます。なんだか、責任の所在が不明な、某市場移転問題みたいですねぇ。

Linux 4.6 で OOM reaper が導入され、 Linux 4.9 では「 OOM killer が発動できる限りは OOM livelock 状態に陥らないことを証明できる」ようになる・・・ことを目指していました。しかし、誰も進捗を出せなくなったことを知らせてくれる仕組みとして、ストールしている間は10秒毎に警告を出力するという楽観的な修正が取り込まれたことにより、 Linux 4.8 までは存在しなかった「ロックを獲得したままバッファが空になるまで永遠に待ち続けるA v.s. ロックを獲得できないことでバッファへの追加を永遠に続けるA以外の全員」という新しい OOM livelock 状態が発生してしまいました。よって、残念ながら「 OOM livelock 状態に陥らないこと」を証明できませんでした。

この問題は printk() がバッファが空になるまで永遠に待ち続けることが原因ということにされたため、バッファを空にする処理を専用のカーネルスレッドにオフロードすることで解消される見込みです。しかし、本当の原因は「ロックを獲得したままスリープしてしまうA v.s. ロックを獲得できないままビジーループをしてしまうA以外の全員」であるため、「ロックを獲得できなかった場合はスリープすることで、ロックを獲得しているAの処理を先へと進める」というのが正しい修正だと思うのですが、そのような修正を加えることにより予期せぬ副作用が発生することを恐れているため、採用される見込みはありません。問題を指摘しても、「 DoS 攻撃を受けていて手遅れだ」という返事。原因がカーネル側にあり、それを修正する方法が存在していても、想定を超える負荷が掛かったら諦めるしかないという、セキュリティとトラブルシューティングをやっている人の視点としては納得いかない世界なのです。こんな調子では、 DirtyCOW のような脆弱性が見つかるのも、当然かもなぁ。

ストールしている間は10秒毎に警告を出力するという楽観的な修正には、全員が同じ考えで動いた場合には機能しないという致命的な欠陥があり、問題が発生しているかもしれないことを知らせるという watchdog としての役割を果たせません。この処理を、専用のカーネルスレッドにオフロードすることで、全員が同じ考えで動いてしまった場合でも機能するようにするという提案を続けています。果たして、採用されるのでしょうか?

posted by 熊猫さくら at 11:34| Comment(0) | TrackBack(0) | Linux