Slide 1

Slide 1 text

1 Chrome が落ちる問題を 追いかけていたら libgcrypt の bug に出会った ● ● @ItSANgo ● http://www.facebook.com/profile.php? id=100005833863069 ● http://mixi.jp/show_profile.pl?id=78975 9

Slide 2

Slide 2 text

2 発端 (2012 年 12 月 24 日 ) ● https://productforums.google.com/f orum/#!msg/chrome-ja/w4pP0DQ75Dw/p xm9Qg8YDtsJ ● Xubuntu 12.04 上の Chrome が http://twtter.com/ItSANgo/ へアクセ スすると SIGABRT で落ちます。 ● その他、あちこちのサイトで落ちま す。 ● Linux 版 Chrome 使えねぇ (-"-)

Slide 3

Slide 3 text

3 標準エラー出力 (google-chrome:10581): Pango-CRITICAL **: pango_font_description_set_size: assertion `size >= 0' failed ● chrome --flag-switches-begin --flag- switches-end: /build/buildd/cairo- 1.10.2/src/cairo-surface.c:1287: cairo_surface_set_device_offset: アサーション `status == CAIRO_STATUS_SUCCESS' に失敗し ました。 ● ● なんだこれは ?

Slide 4

Slide 4 text

Chrome には crash report を出 す機能がある。 (12 月 26 日 ) ● chrome://crashes ● 早速 crash report を提出。 ● https://code.google.com/p/chromium/is sues/detail?id=167553 ●

Slide 5

Slide 5 text

Desktop 環境によっては 落ちないよ ?(12 月 30 日 ) Desktop 環境依存 ? Lubuntu は Chromium が標準ブラウザ → 独自に修正が入っている ? セッション 結果 Ubuntu × GNOME × LXDE ○ Recovery Console ○ Xubuntu ×

Slide 6

Slide 6 text

同じエラーを報告している人が いた ● https://code.google.com/p/chromium/is sues/detail?id=124990 ● (chromium:4187): Pango-CRITICAL **: pango_font_description_set_size: assertion `size >= 0' failed は同じメッ セージ。 ● “I think the browser crashes more, when are been loaded sites which asks for username and password .” ● でも本当に同じエラー ?

Slide 7

Slide 7 text

助っ人登場 (1 月 2 日 ) ● font 周りでは ? ● --password-store=basic では ? ← これ が大きかった !

Slide 8

Slide 8 text

password-store と問題の関連性 ● gnome-keyring が怪しい。 password-store 結果 gnome × kwallet ○ basic ○

Slide 9

Slide 9 text

gnome-keyring の Ver. Up (1 月 7 日 ) Xubuntu(Ubuntu) Gnome-keyring 12.04 3.2.2-2 12.10 3.6.1-0 ● Xubuntu ごと Upgrade しました。 ● しかし問題は改善しなかった。

Slide 10

Slide 10 text

Gnome-keyring の make check が通らない ● /wrap-layer/create-credential/ok_password: FAIL ● ● もはや Chrome の問題ではないよ^^; ● ● 自分の手におえそうにないので Ubuntu 日本語フォーラムに助けを求め た。 (1 月 9 日 ) ● https://forums.ubuntulinux.jp/viewtopic.php?id=14643 ● 「 gnome-keyring 3.6.1-0Ubuntu1 のソースの make check が FAIL にな るのを何とかしたい」 ● DELL XPS8300 (core i7-2600) 上の VirtualBox では問題が発生しない。

Slide 11

Slide 11 text

GDB で追いかける (1 月 13 日 ) ● largs[0] = success ? 0 : 1; ● ここを通り過ぎたとき、 largs[0] は 0 になると予想しました が、実際には -nan になっていました。 ● ● (gdb) print largs[0] ● $28 = -nan(0xc000000000000000) ● (gdb) print success ● $29 = 1 ● (gdb) print test_run_success ● $30 = 0 ● ● こんなことってある ? メモリを壊している ? ● パルプンテ ! パルプンテ ! パルプンテ ! ●

Slide 12

Slide 12 text

迷走中:最適化を切ってみた (1 月 20 日) ● 落ちる場所は変わった w ● /gnome2-store/import/pkcs12: FAIL

Slide 13

Slide 13 text

まーた変な値が入っている (1 月 22 日 ) ● guint32 iterations; ● /* 略. */ ● /* Prepare us the iterations */ ● iterations = 1000 + (int) (1000.0 * rand() / (RAND_MAX + 1.0)); /* ←これが 怪しい. */ ● /* 略. */ ● ● if (!create_cipher (login, calgo, halgo, salt, sizeof (salt), iterations, &cipher)) /* ←ここで落ちている. */ ● return FALSE; ● 上記のコードなのですが私が読んだ限りではiterationsには1000から2000の値 が入ると見たのですが、実際には、 ● ● (gdb) print iterations ● $15 = 2147484648 ● パルプンテ!パルプンテ!パルプンテ!

Slide 14

Slide 14 text

ふと思った (1 月 25 日 ) ● 浮動小数点数まわりの扱いがおかしい のではないか ? ● IA-32 の CPU の仕様の勉強を始めた。 ● 「 IA-32 インテル ® アーキテクチャソ フトウェア・デベロッパーズ・マニュ アル」 ● http://www.intel.co.jp/content/www/jp /ja/developer/download.html#ia32

Slide 15

Slide 15 text

GDB で追いかける。 ● Info float ● 普段は Empty (gdb) info float R7: Empty 0x4008ffffff8b0dffffff8030ffffff98000000 R6: Empty 0x00000000000000000000 R5: Empty 0x00000000000000000000 R4: Empty 0x00000000000000000000 R3: Empty 0x00000000000000000000 R2: Empty 0x00000000000000000000 R1: Empty 0x00000000000000000000 =>R0: Empty 0x00000000000000000000 ● しかし…

Slide 16

Slide 16 text

FPU レジスタが… ● FPU レジスタが全て使われてしまって いる。 (gdb) info float =>R7: Special 0xffffffffffffffffffffffc000000000000000 Real Indefinite (QNaN) R6: Zero 0x00000000000000000000 +0 R5: Zero 0x00000000000000000000 +0 R4: Zero 0x00000000000000000000 +0 R3: Zero 0x00000000000000000000 +0 R2: Zero 0x00000000000000000000 +0 R1: Special 0xffffffffffffffff0000000000000000 Unsupported R0: Special 0xffffffffffffffff0000000000000000 Unsupported ● 何故だ ? --; ● だが、問題を追いかけるトリガーが出来た。 ● 後はただひたすらに処理を追いかけるだけ。

Slide 17

Slide 17 text

問題個所特定 (1 月 26 日 ) ● gcry_cipher_encrypt (cipher, dest, input- >len, input->buf, input->len) ● libgcrypt11:i386 1.5.0-3ubuntu1 の関数 ● 再現プログラムを書いた。 ● Bug report: https://bugs.launchpad.net/ubuntu/+so urce/libgcrypt11/+bug/1105758

Slide 18

Slide 18 text

さらに問題個所を絞り込む (1 月 27 日 ) ● /build/buildd/libgcrypt11-1.5.0/cipher/rijndael.cの_gcry_aes_cbc_enc () でaesni_cleanup() を呼び出しているところで、全てのx87 FPUデータレ ジスタが使用されていました。 ● ● void ● _gcry_aes_cbc_enc (void *context, unsigned char *iv, ● void *outbuf_arg, const void *inbuf_arg, ● unsigned int nblocks, int cbc_mac) ● { ● /* 略. */ ● aesni_cleanup (); /* <- ここ. */ ● ● _gcry_burn_stack (48 + 2*sizeof(int)); ● }

Slide 19

Slide 19 text

マクロでした ● # define aesni_cleanup() \ ● do { asm volatile ("pxor %%xmm0, %%xmm0\n\t" \ ● "pxor %%xmm1, %%xmm1\n\t" :: ); \ ● } while (0) ● ● pxor - http://softwaretechnique.web.fc2.com/OS_Development/Tips/I A32_MMX_Instructions/PXOR.html#PXOR ● 要するに xmm0 と xmm1 を 0 クリアしているだけ。 ●

Slide 20

Slide 20 text

どうしてこうなるのか ● 9.5.1. MMXR 命令と x87 FPU タグワードの関係 ● MMXR 命令の実行後は、必ず x87 FPU タグワード 全体が Valid ( 00B )に設定されてい ● る。 ● 。 EMMS 命令( MMX テクノロジ・ステートのクリ ア命令)を実行すると、 x87 FPU タグワード全体 が Empty ( 11B )に設定される。 ● http://www.intel.co.jp/content/dam/www/public/ij kk/jp/ja/documents/developer/IA32_Arh_Dev_Man_Vo l1_Online_i.pdf ● ● 要するに PXOR の後に EMMS を呼び出すのを忘れて いる ?

Slide 21

Slide 21 text

パッチ書きました ● # define aesni_cleanup() \ ● do { asm volatile ("pxor %%xmm0, %%xmm0\n\t" \ ● "pxor %%xmm1, %%xmm1\n\t" "emms\n" :: ); \ ● } while (0) ● ● make check はすべてクリア、 Chrome も落ちることは無くなっ た。 ● 全てはこれで解決するかに見えたが…

Slide 22

Slide 22 text

そのパッチ間違ってます ● http://lists.gnupg.org/pipermail/gcrypt-devel/2013-January/002083.html ● ● Jussi Kivilinna jussi.kivilinna at mbnet.fi ● Mon Jan 28 09:49:33 CET 2013 ● ● Those are SSE2 instructions, not MMX. So it does not touch x87 ● registers at all. ● Your bug report shows that you have Pentium-III. It does not support SSE2. ● ● Since PXOR for MMX is encoded with '0F EF' and for SSE2 with '66 0F ● EF', the SSE2 version runs as MMX version on CPUs without SSE2 ● support. The 0x66 byte at front of SSE2-opcode is operand-size ● override prefix and is being ignored on your CPU. ● ● Bug appears to be in _gcry_aes_cbc_enc(), aesni_cleanup() is called ● outside '#ifdef USE_AESNI' and/or 'if (ctr->use_aesni)'. This works on ● most (modern) CPUs, but not those without SSE2 support. ● ●

Slide 23

Slide 23 text

正しいパッチが出ました (1 月 28 日 ) ● 開発版 (1.6beta): http://lists.gnupg.org/pipermail/gcrypt-devel/2013-January/002084.htm l ● Version 1.5: http://lists.gnupg.org/pipermail/gcrypt-devel/2013-January/002088.htm l ● ● - aesni_cleanup (); ● + ● +#ifdef USE_AESNI ● + if (ctx->use_aesni) ● + aesni_cleanup (); ● +#endif /*USE_AESNI*/ ● ● 要するにpxorを呼び出す箇所は#ifdefで囲いctx->use_aesniでチェッ ク。

Slide 24

Slide 24 text

その後当方でやったこと ● パッチのテスト ● パッチの当て方ドキュメント化 (1 月 30 日 ) – https://forums.ubuntulinux.jp/viewtopic.ph p?pid=96461#p96461 – https://bugs.launchpad.net/ubuntu/ +source/libgcrypt11/+bug/1105758/comme nts/3

Slide 25

Slide 25 text

その後の状況 ● 正式なパッケージが出始めました。 – Debian's 1.5.0-5 ● そのうち Ubuntu にも落ちてくるでしょう。 – Libgcrypt 1.5.1 released http://lists.gnupg.org/pipermail/gcrypt- devel/2013-March/002109.html – Libgcrypt 1.5.2 released …

Slide 26

Slide 26 text

こうして世のポンコツ PC が救 われたのです。 ● Pentium II とか III とか http://www.ill-f.co.jp/blog/cat6/

Slide 27

Slide 27 text

所感とか ● Chrome のデバッグは大変よねぇ。 ● IA-32 って変態さんだ。 ( 歴史を背負っ ててぐちゃまら ) ● マクロを小文字で書く文化は滅びろ w

Slide 28

Slide 28 text

Chrome のプロセスについて ● chrome(2910)-+-chrome(2916) ● |-chrome-sandbox(2917)---chrome(2918)-+-chrome(2925)-+-chrome(2975)-+-{chrome}(2979) ● | | | |-{chrome}(2982) ● | | | `-{chrome}(2992) ● | | |-chrome(2985)-+-{chrome}(2989) ● | | | |-{chrome}(2990) ● | | | `-{chrome}(2993) ● | | `-chrome(2994)-+-{chrome}(2997) ● | | |-{chrome}(2998) ● | | `-{chrome}(2999) ● | `-nacl_helper_boo(2924) ● |-{chrome}(2927) ● |-{chrome}(2928) ● |-{chrome}(2929) ● |-{chrome}(2931) ● |-{chrome}(2932) ● |-{chrome}(2933) ● |-{chrome}(2934) ● |-{chrome}(2935) ● |-{chrome}(2936) ● |-{chrome}(2937) ● |-{chrome}(2938) ● |-{chrome}(2939) ● |-{chrome}(2940) ● |-{chrome}(2941) ● |-{chrome}(2943) ● |-{chrome}(2944) ● |-{chrome}(2945) ● |-{chrome}(2946) ● |-{chrome}(2947) ● |-{chrome}(2948) ● |-{chrome}(2971) ● |-{chrome}(2972) ● |-{chrome}(2973) ● |-{chrome}(2974) ● |-{chrome}(2981) ● |-{chrome}(2983) ● |-{chrome}(2984) ● |-{chrome}(2991) ● |-{chrome}(3002) ● |-{chrome}(3003) ● |-{chrome}(3004) ● |-{chrome}(3005) ● |-{chrome}(3009) ● |-{chrome}(3015) ● |-{chrome}(3018) ● |-{chrome}(3019) ● |-{chrome}(3020) ● |-{chrome}(3022) ● |-{chrome}(3023) ● |-{chrome}(3024) ● |-{chrome}(3025) ● `-{chrome}(3028) ● どうデバッグしろと w https://code.google.com/p/chromium/wiki/LinuxDebuggin g