2014年12月24日

第11回「 strace ノススメ」が掲載されました。

今回は誰かの行動を一つ残らず追いかけるという話です。
知世ちゃんのことを思い出したので、「歓びのキャロル」を聞きながらこちらの補足記事を書いています。

strace は普通に使われていると思うので、特別な内容は無いです。ログを頼りに問題事象の解析を行う調査担当者の立場としては、「事象の再現手順を確立する」「事象の発生時刻が判るようにする」という基本事項の繰り返しです。

今年もいろいろなバグや脆弱性に振り回され続けてきました。熊猫はというと、昨年偶然発見した「 Linux 2.0 (18年前!)から存在している(と考えられる)脆弱性」により引き起こされる様々な問題事象に関して、脆弱性の修正方法を議論して修正内容がバックポートされるまでの間ずっと無防備になることを避けるために、いくつかの問題事象を先に修正してもらえるよう試行錯誤していました。
そして、問題事象の1つである、 OOM killer の発生時に deadlock してしまう事象に関して、脆弱性を使わずに事象を再現させるプログラムを作成して投稿したところ、関係者からのコメントを頂くことができ、衝撃の事実が明らかになりました。
「システムの所有者は Linux から BSD への乗り換えを真剣に検討し始めるだろう」という冗談が飛び出すような、とんでもない相違が存在していたのです。
これじゃあ、システムがロックアップしてしまうのも不思議ではないですねぇ。どうやって修正するのか、これから延々と議論が続くことになりそうです。

ヤマノススメ セカンドシーズン、素敵なアニメでした。サードシーズンはいつ出るのかなぁ?

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

2014年12月09日

第10回「ソースコード閲覧ノススメ」が掲載されました。

今回はディストリビューションに同梱されているプログラムのソースコードの確認手順の話です。各自の環境で試せるように、 CentOS ユーザ向けの手順にしてあります。

何か問題が発生した時に、ちょっとソースコードを確認すれば、どこで問題が起きているのか/起こりそうかが判明することが少なからずあります。また、ソースコードを確認できるようになっていれば、 SystemTap などの解析ツールを使用することで原因を突き止めやすくなります。

商用のウイルス対策ソフトや死活監視プログラムのように、ディストリビューションに同梱されていないプログラムを使用している環境では、普段遭遇しないようなエラーコードが返却されたり、フリーズしたり再起動したりするトラブル事例が多いと感じています。しかし、残念ながらソースコードを確認できないため、原因不明のまま諦めざるを得ません。各種ウイルス対策ソフトが使っている(リアルタイム検索のための)カーネルモジュール部分のソースコードを閲覧できるようになっていれば、だいぶ状況は良くなりそうなのになぁ・・・。

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

2014年11月25日

第9回「アップデートノススメ」が掲載されました。

今回は RHEL におけるソフトウェアの管理の話です。

この連載のタイトルは「ヤマノススメ」に倣っているので、企画段階では今回は rpm パッケージを管理するための yum コマンドの使い方を紹介する「 yum ノススメ」となる予定でした。

しかし、今年も大型脆弱性が続々と発見されているのに、相変わらず「アップデートしないで済む根拠」を確認するための問合せが目立っており、どうも「アップデートすることを必要以上に恐れすぎているのではないか」と思えるのです。「リグレッションに遭遇して動かなくなるのが怖い」のか「個々のプログラムや設定がどこでどのように影響しあっているかを知らないから怖い」のかは判りません。前者なら変更履歴とソースコードとの照合を行うとか、後者なら自分が管理しているシステムについて理解しようと努力するとか、塩漬けにする以外に何かできることはあると思います。オープンソースを使ったシステムがブラックボックスのままだなんて、モッタイナイ。

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

2014年11月11日

第8回「カーネルパラメーターチューニングノススメ」が掲載されました。

今回はカーネルパラメータチューニングです。

予期せぬ再起動や系切り替えが発生する前に何とかして手がかりを得ようと試行錯誤を続けた結果として「エンタープライズ向けサーバのトラブル対応のための情報取得方法について」という資料ができました。そして、その後も試行錯誤を続けた結果、今度は SystemTap が役に立つかもしれないということに気が付きました。

# stap -g -e '
function call_panic() %{ panic("Calling panic() due to machine restart\n"); %}
probe kernel.function("machine_emergency_restart") { call_panic(); }
probe kernel.function("machine_restart") { call_panic(); }' &

SystemTap を用いて行っていることは簡単で、 /sbin/reboot -f であろうと Watchdog のタイムアウトであろうと echo b > /proc/sysrq-trigger であろうと、システムを再起動するための関数呼び出しが発生したらカーネルパニックを発生させます。カーネルパニックを発生させることができれば、 kdump を取得して解析することができる筈ですから。
ただし、残念ながらトリプルフォールトのように SystemTap を仕掛けられないケースもあります。また、熊猫自身は問題事象の発生する環境を持ち合わせていないため、どれくらい効果があるのかは不明です。

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

2014年10月28日

第7回「 sosreport ノススメ」が掲載されました。

今回は sosreport の紹介です。主に、システム構成の把握/ログの確認/リソース使用状況の確認のために取得していただいている訳ですが、いろいろと落とし穴があります。勝手にカーネルモジュールをロードしてしまうとか、大量のCPU時間を消費したりとかディスクI/Oを発生させたりとかの話は本文を参照していただくとして、ここでは調査担当者としての苦労話を書こうかと思います。

リソース使用状況の取得に sysstat ではなく商用の運用監視ツールを使っているために、計算式がどうなっているのかとかグラフをどう見ればよいのかとかが不明というケースがあります。サポート対象外の製品については OSS センタから当該製品のサポート窓口に照会する術を持ち合わせていないため、ログやリソース使用状況の確認ができませんので、お客様のほうから当該製品のサポート窓口に照会していただくことになります。

そうそう、計算式といえば、回収可能なメモリを加味した空きメモリの計算方法というのは長年の課題なんですよね。 RHEL 6.6 カーネルの /proc/meminfo には RHEL 7.0 カーネルに存在している MemAvailable: という項目がバックポートされており、 /proc/sys/vm/meminfo_legacy_layout に 0 を書き込むことで表示されるようになります。この項目があると、空きメモリの監視が格段に楽になるのではないかと思います。

で、話を元に戻しますと、他には、 sysstat を使っているけれども、取得したデータがすぐにログサーバに移動されてしまうために /var/log/sa/ 配下には保存されておらず、せっかく sosreport を取得していただいたのに、リソース使用状況を確認できないというケースもあります。しかし、 sosreport の取得をお願いする時点では、 sysstat の使用有無やログの保存場所がどこに設定されているのかは不明な訳です。そして、お客様のサーバにログインして構成を調査をすることはできませんので、お客様のサーバ向けにカスタマイズしたログの取得手順を提示することもできない訳です。

ですので、今回の記事を読んで、ログファイルがどこに保存されているかをトラブルに遭遇する前に把握して、 sosreport には含まれていない必要なログファイルを一緒に取得していただけると有難いなぁと思っている訳です。

え?ログファイルがどこに保存されているかを知るためのツールは無いのかって?

それなら、緊急コラム「 bash 脆弱性( CVE-2014-6271 )の影響範囲の調査方法について」で紹介した TOMOYO や AKARI の出番ですね。

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

2014年10月14日

第6回「 Bugzilla ノススメ」が掲載されました。

今回は Bugzilla の紹介です。ここでは、「再現手順を確立することの重要さ」の例として、熊猫が先月対応していた不具合事例について紹介したいと思います。

この不具合は以下のような経緯により原因が特定され、修正されました。現在は RHEL 6/7 カーネルにバックポートされるのを待っている状態です。

  1. Red Hat 社がカーネルパニック発生時点での解析結果と矛盾点を公開( https://access.redhat.com/solutions/640843 )していた。
  2. お客様は原因不明のカーネルパニックに悩まされており、( HP 社サーバと一緒に購入した OEM 版の RHEL サブスクリプションを使用していたため)サポート窓口となる HP 社に照会を行い、上記の不具合情報の存在について把握した。
  3. お客様は NTT OSS センタにも照会を行い、再現手順を確立できないと先に進めないことを理解した。そして、お客様自身が cgroup を使用していると発生頻度が高くなることを突き止め、問題事象を再現できる手順を確立した。
  4. OSS センタでは、上記の矛盾点が発生しそうな箇所で整合性検査を行う SystemTap スクリプトを作成し、 SystemTap を用いた調査を提案した。
  5. お客様は SystemTap を用いた情報取得を行い、カーネルパニックに至るシグナルを受信するよりも前に矛盾点が発生していることを突きとめることができた。
  6. SystemTap で取得した情報を基に OSS センタで解析し、 cgroup に含まれるスレッドセーフでは無い処理が問題事象の発生原因であることを突きとめることができた。
  7. コミュニティに報告し、問題が修正( https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=2ad654bc5e2b211e92f66da1d819e47d79a866f0 )された。

この不具合は5年前に公開された Linux 2.6.31 で混入し、不整合状態の発生条件が命令の実行タイミングに強く依存していたことと、不整合状態が発生してからシグナルを受信するまでの処理の流れを kdump の情報から追うことができないケースという特殊さが組み合わさって、不明瞭なカーネルパニックを引き起こしてきたようです。問題事象が発生する環境と同一のハードウェアやシステム構成を持ち合わせていない OSS センタでも問題事象を再現させることができず、お客様自身が問題事象の再現手順を確立する以外に先に進めないという状況にありました。そして、関係各位の連携プレーにより、見事解決することができました。

問題解決までの流れを知っておくと、サポートを利用する側としてどのようなことができるかを考えることができるようになります。スムーズな問題解決のために、ご協力をお願いいたします。

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

2014年10月01日

bash 脆弱性( CVE-2014-6271 )の回避策として LD_PRELOAD 環境変数を使うことの罠について

サポートケースに投げても customerservice 宛に投げても secalert 宛に投げても反応が無いので、ここで説明することにします。( 10/2 追記: secalert の中の人から反応がありました。スパムキューの中に埋もれていて気付いていなかったそうです。 10/7 追記: PassEnv LD_PRELOAD を追加するように記述が修正されました。)

https://access.redhat.com/articles/1212303 には、「 /lib/bash_ld_preload.so による回避策は潜在的に危険であるため、(システム全体に適用されてしまう) /etc/ld.so.preload にではなく(サービス単位での適用が可能な) init スクリプトでの LD_PRELOAD 環境変数の設定を推奨する」という記述があり、一例として httpd サービスに適用する手順が紹介されています。

If you wish to apply this workaround across the entire system:

  • Add the following to /etc/ld.so.preload on a line by itself:
/lib/bash_ld_preload.so
  • Restart all relevant services or reboot the system.

Note that this is potentially very dangerous. It is recommend that you just apply this workaround to specific services that may be exploitable on your system. This can be achieved by adding bash_ld_preload.so to the LD_PRELOAD environment variable in the script that will initialize the service. For example, for httpd on Red Hat Enterprise Linux 6:

  • Add the following two lines at the top of /etc/init.d/httpd, after the shebang line:
LD_PRELOAD=/lib/bash_ld_preload.so
export LD_PRELOAD
  • Then restart httpd:
# service httpd restart

しかし、上記のように LD_PRELOAD 環境変数を設定しても、効果はありません。効果が無いことを確認する手順を以下に説明します。

C言語で作成されたCGIプログラムを使って確かめてみましょう。

---------- Source code of /var/www/cgi-bin/test.cgi start ----------
#include <stdio.h>

int main(int argc, char *argv[], char *environ[]) {
  int i;
  printf("Status: 200\r\n");
  printf("Content-type: text/plain\r\n");
  printf("\r\n");
  for (i = 0; environ[i]; i++)
    printf("%s\n", environ[i]);
  return 0;
}
---------- Source code of /var/www/cgi-bin/test.cgi end ----------

このCGIを叩いてみましょう。

# curl -H 'User-agent: foobar' http://127.0.0.1/cgi-bin/test.cgi

HTTP_USER_AGENT=foobar という行は表示されるのに対して、 LD_PRELOAD=/lib/bash_ld_preload.so という行は表示されないことが確認できます。言い換えると、 LD_PRELOAD 環境変数は /usr/sbin/httpd プロセスには継承されていますが、 /usr/sbin/httpd プロセスから起動されるCGIプログラムには継承されていないことを意味しています。

そのため、 /etc/init.d/httpd の中で LD_PRELOAD 環境変数を設定する方法では、 以下のように /bin/bash を呼び出す可能性のあるCGIプログラムを保護することはできません。

---------- Content of /var/www/cgi-bin/test1.cgi start ----------
#!/bin/sh
echo "Status: 200"
echo "Content-type: text/plain"
echo ""
exec /bin/env
---------- Content of /var/www/cgi-bin/test1.cgi end ----------
---------- Source code of /var/www/cgi-bin/test2.cgi start ----------
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
  printf("Status: 200\r\n");
  printf("Content-type: text/plain\r\n");
  printf("\r\n");
  fflush(stdout);
  system("/bin/env");
  return 0;
}
---------- Source code of /var/www/cgi-bin/test2.cgi end ----------

以下のような叩き方をすれば、 /tmp/file を作成できてしまう訳です。

# curl -H 'User-agent: () { :;}; exec /bin/touch /tmp/file' http://127.0.0.1/cgi-bin/test1.cgi
# curl -H 'User-agent: () { :;}; exec /bin/touch /tmp/file' http://127.0.0.1/cgi-bin/test2.cgi

環境変数が意図した範囲に継承されているかどうかを理解しないまま、 LD_PRELOAD 環境変数による回避策を使おうとするのは危険です。

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

2014年09月30日

緊急コラム「 bash 脆弱性( CVE-2014-6271 )の影響範囲の調査方法について」が掲載されました。

デング熱で騒いでいたと思った世の中が、突然 bash 脆弱性とか御嶽山噴火とかで騒ぎ出しました。今回の bash 脆弱性は、まさに TOMOYO とか AKARI とか CaitSith とかが活躍するケースな訳ですが、 Red Hat 社のサポート対象外な機能であるため、商用サポートを必要とするお客様に紹介することができず、焦りと残念さが募っています。

でも、せっかく連載をしているところですので、思い切って緊急コラムとして掲載しちゃいました。(即日で作成したので詳細までは準備できませんでした。質問などがありましたら遠慮なくどうぞ。)

熊猫がセキュリティキャンプに参加するようになってから今年で4回目になる訳ですが、年々技術的なトピックから離れてきているのを感じています。それは、OSレベルのアクセス制御に興味を持ってくれる人が少ないからという理由もあります。しかし、「プログラムのアイデア出しから保守まで全部を自分で行う」側から「他人が作成したプログラムの不具合調査を行う」側になったことで、「誰かが面倒を見てくれている筈だから、自分は考えなくてよい」という「隅々から全体までを通して見ようとしない」姿勢こそが問題の根底にあるのではないかと思うようになったからという理由もあります。なので、今年のキャンプでは、熊猫が感じている現在のSI業界の問題点を取り上げ、

「自分に関係しないことは気にしない」では済まされない。
システムのトラブル/セキュリティの脅威は、助け合いなしでは対処できない。

という話を含めました。あまりに dis りすぎたため、公開したら怒られそうな内容になってしまいましたが、まさに今回の脆弱性のような「事件」への対応姿勢がそれを問うているように思えます。

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

第5回「 SysRq ノススメ」が掲載されました。

今回は SysRq の紹介です。

全プロセスのバックトレースを取得する方法として SysRq-t と kdump とがあり、 SysRq-t には以下のような利点があります。

  • 動作中のマシンをクラッシュさせることなく情報を取得できる
  • 時間経過に伴い処理が先に進んでいるかどうか(バックトレース内容が変化しているかどうか)を確認できる
  • それに対して、 kdump には以下のような利点があります。

  • バックトレース内にゴミが混入しないので内容を把握しやすい
  • (時間経過を伴わないため)一貫性のある結果が得られる
  • バックトレース以外にも様々な状態を確認できる
  • そのため、より確実な情報取得のためにマシンをクラッシュさせることが許されるのであれば、何回か SysRq-t を実行した後に、 SysRq-c を実行して kdump を取得するというのが好ましいと考えます。

    ちなみに、 libvirt 経由で KVM ゲストを稼働させている場合、 virsh dump コマンドを実行することで「動作中のマシンをクラッシュさせることなく kdump 相当の情報を取得できる」ので、 SysRq-t と kdump の両方の利点を得ることができます。 KVM ホストへのシェルログインを許可していないクラウドサービスでも、故障解析情報取得用に Web CGI インタフェースを使って virsh dump 機能を提供してもらえないものかなぁ?

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

    2014年09月16日

    第4回「 udplogger ノススメ」が掲載されました。

    今回は udplogger の紹介です。前回紹介した netconsole の受信側プログラムとしてはもちろんのこと、情報取得のために仕掛けた SystemTap の出力メッセージを受信させたり、ローカルディスクへの書き込みが遅延する恐れがある場合に数秒間隔で取得している性能データを他のホスト上に保存させたりするという使い方もできます。

    「ローカルディスクへの書き込みが遅れるなんてことあるんかいな?」と思われるかもしれませんが、実際に遅延した事例があります。 rsyslog のデフォルト設定では書き込みの完了を待つようになっているため、 Serial ATA の Native Command Queuing 機能により、業務アプリケーションによる大量のディスク I/O が優先されてしまい、死活監視で使っている /bin/su を実行した際の /var/log/secure への記録が大幅に遅延して、死活監視のタイムアウトエラーが発生してしまいました。結局、 /var/log/secure への書き込みの完了を待たないように rsyslog の設定を変更して対処しました。

    「ヤマノススメ」は風景描写が丁寧ですねぇ。「ARIA」を思い出します。 そういえば、アニメで口笛シーンが登場するのは珍しいことかも。

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