Contenu connexe Similaire à Chromeが落ちる問題を 追いかけていたら libgcryptのbugに出会った (20) Plus de Mitsutoshi Nakano (6) Chromeが落ちる問題を 追いかけていたら libgcryptのbugに出会った2. 2
発端 (2012 年 12 月 24 日 )
●
https://productforums.google.com/forum/#!msg/c
●
Xubuntu 12.04 上の Chrome が
http://twtter.com/ItSANgo/ へアクセスする
と SIGABRT で落ちます。
●
その他、あちこちのサイトで落ちます。
●
Linux 版 Chrome 使えねぇ (-"-)
4. Chrome には crash report を出
す機能がある。 (12 月 26 日 )
●
chrome://crashes
●
早速 crash report を提出。
●
https://code.google.com/p/chromium/issue
●
5. Desktop 環境によっては
落ちないよ ?(12 月 30 日 )
Desktop 環境依存 ?
Lubuntu は Chromium が標準ブラウザ
→ 独自に修正が入っている ?
セッション 結果
Ubuntu ×
GNOME ×
LXDE ○
Recovery Console ○
Xubuntu ×
7. 助っ人登場 (1 月 2 日 )
●
font 周りでは ?
●
--password-store=basic では ? ← これ
が大きかった !
9. gnome-keyring の Ver. Up
(1 月 7 日 )
Xubuntu(Ubuntu) Gnome-keyring
12.04 3.2.2-2
12.10 3.6.1-0
●
Xubuntu ごと Upgrade しました。
●
しかし問題は改善しなかった。
10. 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 では問題が発生しない。
11. 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
●
●
こんなことってある? メモリを壊している?
●
パルプンテ! パルプンテ! パルプンテ!
●
13. まーた変な値が入っている
(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
●
パルプンテ!パルプンテ!パルプンテ!
14. ふと思った (1 月 25 日 )
●
浮動小数点数まわりの扱いがおかしいので
はないか ?
●
IA-32 の CPU の仕様の勉強を始めた。
●
「 IA-32 インテル ® アーキテクチャソフト
ウェア・デベロッパーズ・マニュアル」
●
http://www.intel.co.jp/content/www/jp/ja/develo
15. 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
●
…しかし
16. 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
●
何故だ ? --;
●
だが、問題を追いかけるトリガーが出来た。
●
後はただひたすらに処理を追いかけるだけ。
17. 問題個所特定 (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/+source/libgcr
18. さらに問題個所を絞り込む
(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));
●
}
19. マクロでした
●
# define aesni_cleanup()
●
do { asm volatile ("pxor %%xmm0, %%xmm0nt"
●
"pxor %%xmm1, %%xmm1nt" :: );
●
} while (0)
●
●
pxor -
http://softwaretechnique.web.fc2.com/OS_Development/Tips/IA32_MMX_Instruction
●
要するに xmm0 と xmm1 を 0 クリアしているだけ。
●
20. どうしてこうなるのか
●
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/ijkk/jp/ja/documents/developer/
●
●
要するにPXOR の後にEMMS を呼び出すのを忘れている?
21. パッチ書きました
●
# define aesni_cleanup()
●
do { asm volatile ("pxor %%xmm0, %%xmm0nt"
●
"pxor %%xmm1, %%xmm1nt" "emmsn" :: );
●
} while (0)
●
●
make check はすべてクリア、 Chrome も落ちることは無くなっ
た。
●
…全てはこれで解決するかに見えたが
22. そのパッチ間違ってます
●
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.
●
●
23. 正しいパッチが出ました
(1 月 28 日 )
●
開発版 (1.6beta):http://lists.gnupg.org/pipermail/gcrypt-devel/2013-January/002084.html
●
Version 1.5:
http://lists.gnupg.org/pipermail/gcrypt-devel/2013-January/002088.html
●
●
- aesni_cleanup ();
●
+
●
+#ifdef USE_AESNI
●
+ if (ctx->use_aesni)
●
+ aesni_cleanup ();
●
+#endif /*USE_AESNI*/
●
●
要するにpxor を呼び出す箇所は#ifdef で囲いctx->use_aesni でチェック。
28. 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/LinuxDebuggi
ng