/var/log/hdk.log

2017 年 6 月下旬


20 (火)

%1 かようび

朝は整形外科でリハビリテーション。 牽引こんでなかった。

%2 Ryzen General Protection Exception

やっと噂の一般保護例外が出た。 例によって cc1 だがとても楽しいことになっている。

 GPE  flags 00003202 err 00000000 0033:0101356e *
 RAX 00000001    RCX 00000AED    RDX A656C63796320    RBX 012B7050
 RSP 7FFE731E3668    RBP 00000000    RSI 00000007    RDI 015B7AED
 R8  015B7AED    R9  0000007F    R10 00000005    R11 00000007
 R12 7F146FCAB410    R13 7F146FCC0078    R14 015B7AED    R15 7F146FC8C248

表示しているのは VMM 内に自分で追加したテストプログラムなので表示がいい加減なのはそのせい。 とにかく %rip=0x0101356e で一般保護例外だ。 フラグは IOPL=3, IF=1, bit1=1 以外は 0 だ。

[31] cs 33 ip 0101356e sp 7ffe731e3668 code 04d info1 00000000 info2 00000000 (
00b78900 c3ff5fd0/2be81872 85ff56df) br[00c67aee->01013560] ex[7f146ff13828->7f
146ff13860]

これも自分が追加したプログラムによる出力なので意味がわからないと思うが、code 04d が一般保護例外による #VMEXIT を表す。 謎の 00b78900 は Guest Instruction Bytes を出したもので、一般保護例外は対象でないので記録されておらず、下位 4 ビットは 0 になっている。 その後ろの 2be81872 85ff56df のところは、%rip を同じ論理 CPU 上で VMM から読み出したもので、キャッシュが壊れているわけではないことを確かめるためにやってみたものだ。br のところが LastBranchFromIP と LastBranchToIP である。 最後の分岐が 0x00c67aee から 0x01013560 だと言っている。

%rip のところを gdb で逆アセンブルすると以下のように出た:

=> 0x101356e <_Z22private_is_attribute_pPKcmPK9tree_node+14>:
    jb     0x1013588 <_Z22private_is_attribute_pPKcmPK9tree_node+40>
ここまでなら、「条件ジャンプで一般保護例外が出るなんて!」で終わる。 そのまま再開すれば動くんじゃないのとも言いたくなる。 しかし、そうじゃないんだな。 スタックを見てみよう。
0x7ffe731e3668: 0x0000000000c67af3      0x000000fb00000010

0x0000000000c67af3 は 0x00c67aee+5 であり、call 命令のようである。 そこは正しい。 呼び出しもとの call 命令は以下のようにちゃんとある。

 c67aee:       e8 6d ba 3a 00          callq  1013560

なので、分岐の情報は合っている。 じゃ、その先は?

 1013560:       48 83 ec 08             sub    $0x8,%rsp
 1013564:       8b 42 20                mov    0x20(%rdx),%eax
 1013567:       48 39 f0                cmp    %rsi,%rax
 101356a:       75 1c                   jne    1013588
 101356c:       48 8b 72 18             mov    0x18(%rdx),%rsi

一発目にスタックポインターの減算である。 上のスタックダンプを見ての通り、これは実行されていないとしか思えない。 しかも、%rip が指しているのは 4 バイトの mov 命令の 3 バイト目である。 ますますおかしい。

ここで頭をよぎるのが、何度も見ている 0x40 問題。 まさか、このサブルーチンの 0x40 手前に何かあるのだろうか?

 1013520:       48 8b 57 10             mov    0x10(%rdi),%rdx
 1013524:       b8 01 00 00 00          mov    $0x1,%eax
 1013529:       48 85 d2                test   %rdx,%rdx
 101352c:       74 e9                   je     1013517
 101352e:       48 8b 4a 10             mov    0x10(%rdx),%rcx

それっぽい命令が並んでいる。 順に検証しよう。 最初の mov 命令が読み取るメモリーの内容を確認する。

(gdb) x/xg 0x10+$rdi
0x15b7afd:      0x000a656c63796320
(gdb) p/x $rdx
$5 = 0xa656c63796320

完全に一致。 次の mov 命令がセットするレジスターの内容を確認する。

(gdb) p/x $rax
$6 = 0x1

これも完全に一致。 その次の test は上で確かめた %rdx の値に対してで、これを実行すると必ず CF=0, OF=0 になる。 また、%rdx の下位 8 ビットで立っているビットはひとつだから、PF=0 だ。 値はゼロでないので ZF=0 だ。 つまりフラグレジスターの値にも矛盾はない。 当然その次の条件ジャンプはジャンプせず、その次の mov 命令でアクセスすることになるのが %rdx+0x10 番地。 この番地は 48bit の符号付き整数で表せる範囲を超えているので、そこにアクセスすれば一般保護例外が発生する。 そしてこの命令がある番地 0x101352e は、見事に %rip-0x40 だ。 うわぁぁぁ。

さて、これを再開するとしたら、まず、いくつかのレジスターの値を復旧させなければならない。callq 1013560 の直前を見ると %r12->%rdx, %rax->%rsi だったことがわかるので、そこから %r12->%rdx をもう一度と、%rsi->%rax をすれば復旧完了。 あとは %rip=0x1013560 にして再開だ。 予想通り成功した。

そんなわけでね、ここ数日の印象としては、命令デコーダーか何か、その辺がひどく変な感じがする。 命令関係のキャッシュが原因の可能性もありそう。 番地の違うキャッシュをなぜか使っちゃってる、みたいな? そしてそのキャッシュだかなんだかわからないがたぶん 64 バイト単位なのでは。 でも分岐アドレスがズレて記録されていたのもあったな。 あれは何だ。

2017/06/20 のコメントを読む・書く


21 (水)

%1 久々に

自宅サーバー PC につながらなくなり、自宅電話にもつながらない状態。 だいぶ不安になりながら帰宅し、ルーターの状態を確認。 電話は「auひかり電話サービス利用不可」という表示。WAN 側 IP アドレスは表示されていたが、再起動を行ったところそれも消えてしまった。

ダイナミック DNS の更新のログを見ると 16 時過ぎにはつながらなくなっていた模様。KDDI に電話で聞いてみたところ、建物全体で問題があるようで原因調査中とのこと。 なんだろうねぇ。 だいぶ前に一度あったんだよね、こういうの。

2017/06/21 のコメントを読む・書く


22 (木)

%1 KDDI

au ひかりは、結局、きのうの 16 時 17 分には使えなくなっていたのが、今日の 19 時 17 分も使えなかったようで、そこから 20 時頃までの間に復活したようだ。7 年前にトラブった時は迷惑掛けましたって紙がポストに入っていたと思ったが、今回はそのときより長く 24 時間超えたけど何も無し。

%2 Debian 9

職場のノート PC にむち打って (冷却ファンがとまっていて熱々に...) Debian GNU/Linux 9 へのアップグレードを実行した結果、systemd を消そうとして停止するという被害にあった。

#854041 - systemd: dpkg fails for systemd package when upgrading from jessie to stretch - Debian Bug report logs

おっかしいな、なおってるってことになっているっぽいな。 まあいい、手で何とかした。 これは sysvinit にしてある他の環境では問題にはならないと思う。 他には、console-setup のフォント設定が起動時に反映されない被害に遭っている。

これは不思議なことに自宅の Ryzen PC では問題が起きていないので、UEFI ブートかどうかが関係しているのかも。 まー原因はともかく、最近の高解像度ディスプレイともなればデフォルトのフォントサイズは目つぶしでしかないと思うので、最初からもっと大きくしてていいんでないのかな。1024x768 でテキスト 80x25 が収まるくらいのサイズで十分でしょう。

%3 Ryzen のなぞ

64 バイトズレの問題のきっかけはやはり、先日出た不思議なページフォールトの件だ。 この問題は TLB フラッシュやら分岐の記録やらしなくても何度か再現している。 今日見た 2 回分 (1 秒以内に連続して発生) を下に載せてみる。 前のと表示内容は変えてある。

[31] cs 33 ip 0113f57d sp 7ffeb1823680 code 04e info1 00000006 info2 0000000a pte 00000003be53c025

PF   flags 00003206 err 00000006 cr2 a 0033:0113f57d *
RAX 00002000    RCX 00000007    RDX 00000000    RBX 02867F40
RSP 7FFEB1823680    RBP 7FFEB1823698    RSI 00000001    RDI 7F2E8E9CF000
R8  000009BA    R9  7F2E8E987DD0    R10 7F2E8E983000    R11 000001F2
R12 0289B9D0    R13 0000000A    R14 0000000A    R15 0289D410

[31] cs 33 ip 0113f57d sp 7ffd7de01330 code 04e info1 00000006 info2 0000000a pte 00000003be53c025

PF   flags 00003202 err 00000006 cr2 a 0033:0113f57d *
RAX 0000F680    RCX 00000007    RDX 00000000    RBX 02E15F40
RSP 7FFD7DE01330    RBP 7FFD7DE01348    RSI 0000001F    RDI 7FB0E8021000
R8  00001513    R9  7FB0E7FDF898    R10 7FB0E7FD5000    R11 00000437
R12 02E51DB8    R13 0000000A    R14 0000000A    R15 02E535E0

 113f57d:       45 8b 69 10             mov    0x10(%r9),%r13d

 113f53d:       49 89 55 00             mov    %rdx,0x0(%r13)

これ。 エラーコードが 6 で、書き込み時のページフォールトを表し、アクセス先のアドレスは 0xa。 しかし %rip が指す命令は、全然違うアドレスの読み取り。 そしてちょうど 64 バイト手前にそれっぽい命令があるという形。 この 64 バイトはただの偶然の可能性もあったが、その後も LBR や call 先のズレなどの形で現れたというわけ。 なお、このページフォールトの件ではこの 0x113f57d の直前にジャンプ命令などなく、レジスターの中身を見ても直前までは順番に実行されてきたとしか思えない状態。

美しく説明できるのはこのくらいで、他はいきなりアドレス 0x11 にアクセスとか、アドレス 0x11 にジャンプとか、アドレス 0 にジャンプとか、そんなふうにいまいちわからないものも多い。 ま、たまに以下のようにファイルサイズのことなるイメージが出力されていることもあるしな。 問題が起きてもクラッシュに至らないケースもあるということだろう。

104 -rw-r--r-- 1 root root 7056208 2017-06-22 16:35:45.535340840 +0000 arch/x86/boot/bzImage
105 -rw-r--r-- 1 root root 7056176 2017-06-22 16:37:15.741843546 +0000 arch/x86/boot/bzImage

2017/06/22 のコメントを読む・書く


23 (金)

%1 合掌

『恋のから騒ぎ』の小林麻央出演のところ、YouTube で少し見てみた。 こんな声だったかな、と思ったけど、説教部屋のシーン見てたら思い出してきたよ。 やっぱこの頃は見てたなーこれ。 同学年だし。 番組おもしろいし。

【ノーカット】市川海老蔵、妻・小林麻央さん死去を報告「愛してる」と言って旅立つ - YouTube

あごに転移とか、退院・在宅医療とか、最期が近づきつつあるともとらえられるニュースはちらほらあったけど、ついに。35 歳をむかえる前に。 同年代の人が病気で旅立つというのはやはり寂しい。 合掌。

2017/06/23 のコメントを読む・書く


24 (土)

%1 じゃがいも掘り

きのう、今日と天気が良かったので掘りやすかったけど、今年は小さめのが多かったな。 畑が変わって何か違うのかな。

帰って洗って乾かして段ボール箱に。 一個はスコップを突き刺してしまったので夜には食べた。

%2 株主総会

ブックオフの株主総会には行こうかと思っていたけどやめた。 おみやげ無くなったみたいだしな。

ディーエヌエーの株主総会には行った。 今回は渋谷だから大変行きやすい。 品川より本社に近いし (同じビル)、多摩地域だけでなく埼玉も横浜も新宿・渋谷あたりは行きやすいと思うのだが、なぜ今まで品川でやっていたのか。 キュレーション関係の問題で突っ込む人はそんなにいなかった。 確かに結構中の仕組みを入れ替えて来ている感じがするし。 最後の人は Google やら YouTube やらはいいのにといった感じの擁護意見、それはでも自分は違うような気がするけどな。 お金を払って書かせていたってのがね。

%3 映画

テレビでやってた映画『マーキュリー・ライジング』(原題: Mercury Rising)。1998 年のアメリカ映画。 日本語吹き替え版。 ブルース・ウィリス主演。 自閉症の子供が重要な役割を果たす。 自閉症は病気ではない、など、知的障害者と見なした人に対する反論も映画の中に出てきており、誤解を招かないよう注意深く描写されているような感じ。 前にもそういう障害を持つ人が出てくる映画見たな。 『レインマン』だ。 あれはサヴァン症候群だったけど。

暗号を解けてしまう自閉症の子供とその家族を消そうとするアメリカ国家安全保障局というアホな設定である。 他の自閉症の子供が解けないとでも思ったのだろうかという間抜けな話である。 ま、いいや、それで連邦捜査局に勤める主人公が何とか子供を守ろうとするのだった。

出てくるコンピューターがブラウン管ディスプレイ... なのはいいんだが、1998 年にしては、Windows 95 などの影響を受けていない感じの、昔風のインターフェイスが出てくる。 物語としては電話は盗聴されているしコンピューターを使うのもまずい、なんて話になり、タイプライターにカーボンコピーが使われ、そのカーボン紙が証拠になる。 自分は子供の頃にカーボン紙を触ったことがあって知っているが、今時の、2000 年頃以降に生まれた人達から見れば何がなんだかわからないかも知れない。 あ、一応、携帯電話は出てきたな。 大きくて、しかもそれを人に借りるという...

この映画、ちょっとした銃の撃ち合いがある程度で基本的には静かな映画なのかと思いきや、鉄道は出てくるし、ヘリコプターも出てくるし、派手な銃撃戦が最後に待っていた。 結構どかどかと派手にやってすっきりするタイプの映画だった。

%4 F1 予選

映画を見ていたので裏番組の F1 アゼルバイジャン GP 予選を見ようと思って iMac を起動した。DAZN は Safari に Silverlight プラグインを入れると見られる。Mozilla Firefox でも見られるのかも知れない。iMac のディスプレイは動画向きではなく、残像が残るというかにじんだ感じになるが、画面が大きいのでタイムは見やすいし、映画の横でチラチラ見る分にはさほど気にならない。 というか、それより 25fps なのが気になる。

予選はさすがメルセデス。 ポールポジション獲得回数一覧に未だにアイルトンセナの名前が残っているわけだが、ついにハミルトンが抜いた。 もうちょっとでミハエルシューマッハの記録に到達だ。 このトリッキーな市街地コースでこのタイムだし、本当にすごいなぁ。

2017/06/24 のコメントを読む・書く


25 (日)

%1 ワイパーゴム交換

車のワイパーゴムを初めて自分で交換した。 特に工具もいらない簡単な作業。 ゴムの溝にブレードのつめが引っかけてある形、ゴムの溝の端っこにストッパーのためのふくらみがあり、端っこのつめがそこにはまって取れにくくなっている。 それと、金属製の棒がはまっていて、これがブレードと合わせてバネの効果を出しているみたい。

そんなわけなので、ストッパーを無視して無理やり引っこ抜き、金属棒を新しいゴムに移して、またブレードのつめに引っかかるように差し込み、最後にストッパーに引っかかるように押し込めば完了。 抜くとき、ブレードを外さずに行うと、ワイパーを立てるとガラスに当たって抜けないので、少し浮かせたくらいの角度で引っこ抜き、ブレードがガラスに当たらないようにワイパーを立てておく。 入れる時もまた似たような角度で入れる。

%2 スイッチングハブ

NETGEAR の GS108E を導入。 これで Ryzen PC とバックアップ用 PC をちゃんとつなぐことができた。8 ポートで VLAN にも QoS にも対応、お手頃価格でちょっと PC が増えてきた家庭用にぴったりである。 なお、ルーターとつないでいる LAN ケーブル (自宅にある LAN ケーブルの中では一番長い) が思っていたより 10cm くらい短くて、当初考えたところにスイッチングハブを置けなかったけど、まいっか。

%3 にちようび

よく寝た日。

今回の Formula One アゼルバイジャン GP は本当にぐだぐだだった。 いくら市街地コースとはいえここまでひどいのは久しぶりでは。 セーフティカーが機能していないと言ったらアレだが、タイヤ温度が下がってしまって、再開のたびにアクシデントが起こるという悪循環、結局赤旗。 そもそもはセーフティカーがなかなか入らなかったのも謎だが、その結果、レース序盤では想像もしなかったメンツが表彰台、ルーキーのストロールは初表彰台。 ドライバーズポイントを争うふたりもぐだぐだとは言え 4・5 位完走。 ペレスやライコネンは結局リタイヤ。 まーでも今回の見てても、フェラーリやメルセデスや、フォースインディアもかな、ちょっとホイールが接触した程度ではサスペンションが壊れることはないんだよな。 今年のマクラーレンは何かとすぐ壊れる感じ。

2017/06/25 のコメントを読む・書く


26 (月)

%1 睡眠薬運転の話

そういえば 2 週間ほど前に睡眠薬を飲んで車を運転して単独の物損事故を起こした芸人のニュースがあった。 たいした事故じゃなかったのは良かったが睡眠薬を飲んで運転とは何事かという話であった。

自分は睡眠薬は飲んだことがないが、眠気を催すおそれのある薬というのはいくらでもあり、そういう注意書きがある薬を飲んで車両 (車やバイクや自転車) を運転したことは何度もある。 そういう意味では他人事ではないのだが、明らかに眠くなった経験のある薬を飲んで眠くなる前に運転をしたというのはないと思う。 たぶん。 普通の総合感冒薬にもその手の成分は入っているが、何度も飲んでいてそれで眠くなった経験がないものは自分的には大丈夫なのかなという判断。

もちろん、いつも大丈夫だったからといって次も大丈夫とは限らないといえばそうで、体調次第では変なふうに効き目が現れるおそれもある。 しかし、それを言うなら、薬を飲んでいなければ大丈夫という話ではなくて、睡眠不足とか体調不良とか、そういうところに気をつけなければならない。 まぁでも現実は、旅客運送などのプロドライバーの方を除いて、ちょっと体調が変だからとか、ちょっと睡眠時間が短かったからとか、そんな理由で運転を完全に取りやめることはないものかも。 病院に行くにも車がないとという環境もあるだろうし、そういう時に体調がすぐれない場合は、休み休みいくとか、人通りの少ない道と時間を選んでゆっくりいくとか、万が一のことがあっても被害を最小限に食い止める工夫も必要だろうか。

なお、今処方されている薬の中にモービック錠というのがあり、視力や眠気に関する注意書きが書かれていることに最近気づいた。 薬局でも特に口頭で言われたことはないし、もう 2 週間くらい飲んでいるけど (分量は変わったけど) そういう症状は何も出ていない。 過去に何かですごく眠くなる薬を処方されたことはあった気がする。 でもあのときも毎回だいたい眠くなるタイミングってものがあったような...

あ、この問題って運転に限らないな。 歩いていても、駅や踏切でばったり倒れて線路の中に入ってしまったら一大事だ。

2017/06/26 のコメントを読む・書く


27 (火)

%1 Ryzen gcc core dump

Ryzen PC の gcc (cc1) が吐いた core dump。Segmentation fault と出て、さらに、dmesg を見ると segfault が出ていた。 何か、core dump を吐かせるためにわざとシグナルハンドラーを消して再実行でもしているのかと思っていたが、core dump をよく見るとどうやら違ったみたいだ。

dmesg に残った segfault と core を見ればアドレス 0x11 を読み取ろうとしてクラッシュしており、アドレス以外に不審な点が見当たらない。 何度か見ていたなぜかアドレス 0x11 にジャンプする事象、それと関係はあるのだろうとは思っていたが、バックトレースには internal_error() などの関数名が出ており、よくよく追ってみたところ、全く同じ事象だった。 真相はこうだ。

  1. アドレス 0x11 にジャンプして segmentation fault が発生、gcc のシグナルハンドラーへ
  2. シグナルの無限ループを避けるためシグナルハンドラーの登録解除
  3. Internal error の処理へ遷移、その中で backtrace_full() を呼び出すらしい
  4. バックトレースをたどろうとした結果、壊れたスタックの 0x11 にたどり着き、そのアドレスをスタックとみて読み取ろうとして 2 度目の segfault, これが core を吐き dmesg にログを残した (たぶん)

そんなわけで、シグナルハンドラーらしきところにフレームを戻し p/x *(struct sigcontext *)($sp+0x38) でそれっぽいレジスター状況が確認できた。 プログラム的に $sp には push %rbx の内容、+8 には戻り番地が入っているはずで、その先のオフセットは手探り。IA-32 なら引数はスタックに積まれるのが普通なので、戻り番地の次にシンプルにシグナル番号と struct sigcontext が見えるはずなのだが、AMD64 ではレジスター渡しが普通なので、struct はどうやって渡されるんだったかな。 でもどっか近くにあるだろということで、フラグレジスターや %cs レジスターの値が合うようにずらしたらこの +0x38 で出た。 で、中身を見ていくと見事にアドレス 0x11 へのジャンプ。 なんでそんなところにジャンプしてしまうのかは、まだ特定できていない。

ま、とりあえず、core dump がはかれるケースがある理由が特定できたのは進歩だ。 別にクラッシュ原因を深く追う意味はないんだけど、こういうパズルは楽しいので。

2017/06/27 のコメントを読む・書く


28 (水)

%1 Ryzen 0x11 問題

謎が解けてきたぞ。%rip=0x11 で停止した時のスタックポインター 0x7ffc95e3ed48 の手前を見るとこうだ。

0x7ffc95e3ed28: 0x00007ff14f638dc8      0x00007ff14f638db0
0x7ffc95e3ed38: 0x0000000000d858e0      0x0000000000000011
0x7ffc95e3ed48: 0x0000000000000011      0x0000000000000000

0x11 に ret してしまったらしいこれ、その前にある 0x0000000000d858e0 が、実は 0x40 ズレた位置の戻り番地だ。(以下、シンボル名は長いので削ってある。)

  d8589b:       e8 90 d2 2b 00          callq  1042b30
  d858a0:       8b 54 24 7c             mov    0x7c(%rsp),%edx

%rip が本来の位置とはズレたまま call を呼んだわけだ。 相対番地なので call 先もズレてしまうようだ。

 1042b70:       39 c2                   cmp    %eax,%edx
 1042b72:       0f 47 d0                cmova  %eax,%edx
 1042b75:       83 fa 01                cmp    $0x1,%edx
 1042b78:       0f 85 97 00 00 00       jne    1042c15
 1042b7e:       b8 01 00 00 00          mov    $0x1,%eax
 1042b83:       5b                      pop    %rbx
 1042b84:       c3                      retq

来た来た。push していないのに pop して ret したらそりゃズレる。 レジスターの値をいくつか確認したがそれっぽい。 例えば %rbx は 0x0000000000d858e0 になっている。 だがここでいくつかのレジスターを壊してしまうから追いにくい。 それをもうちょっと調べられるといいなと思ったわけだ。 そこで、call 先がズレた時に int3 が実行されるように cc1 をバイナリーエディターで改造してみた。

2808992,2808993c2808992,2808993
<  1042b26:     66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
<  1042b2d:     00 00 00
---
>  1042b26:     e9 ee 72 89 ff          jmpq   8d9e19
>  1042b2b:     e9 e5 00 00 00          jmpq   1042c15
2809013,2809018c2809013,2809020
<  1042b67:     0f 84 ac 72 89 ff       je     8d9e19
<  1042b6d:     c1 e8 06                shr    $0x6,%eax
<  1042b70:     39 c2                   cmp    %eax,%edx
<  1042b72:     0f 47 d0                cmova  %eax,%edx
<  1042b75:     83 fa 01                cmp    $0x1,%edx
<  1042b78:     0f 85 97 00 00 00       jne    1042c15
---
>  1042b67:     74 bd                   je     1042b26
>  1042b69:     c1 e8 06                shr    $0x6,%eax
>  1042b6c:     0f 1f 44 00 cc          nopl   -0x34(%rax,%rax,1)
>  1042b71:     39 c2                   cmp    %eax,%edx
>  1042b73:     0f 47 d0                cmova  %eax,%edx
>  1042b76:     83 fa 01                cmp    $0x1,%edx
>  1042b79:     75 b0                   jne    1042b2b
>  1042b7b:     0f 1f 00                nopl   (%rax)

ちょうどルーチンの手前にある長い長い nop と、遠距離条件ジャンプがふたつもあったおかげで工夫がきいた。 長い nop のところに遠距離無条件ジャンプをふたつ入れ、遠距離条件ジャンプふたつを近距離条件ジャンプに変えることで 8 バイトを手に入れ、それを 5 バイトと 3 バイトの nop で消費、5 バイトの nop の最後に cc (int3) を仕込んでおいた。 これで通常動作は OK だが、1042b70 に飛び込めば int3 が実行される。int3 は segfault とは異なりシグナルハンドラーが登録されておらず、いきなり落ちるので都合が良い。 再現実験は cc1 の繰り返しで見事成功した。

Program terminated with signal SIGTRAP, Trace/breakpoint trap.
(gdb) info reg
rax            0x1      1
rbx            0x7f39d6851930   139886388910384
rcx            0x40     64
rdx            0x40     64
rsi            0x7f39d6851940   139886388910400
rdi            0x7ffc56f4d870   140721767372912
rbp            0x7ffc56f4d870   0x7ffc56f4d870
rsp            0x7ffc56f4d808   0x7ffc56f4d808
r8             0x0      0
r9             0x1      1
r10            0x40     64
r11            0x7f39d6b080a8   139886391754920
r12            0x0      0
r13            0x7f39d6b080a8   139886391754920
r14            0x11     17
r15            0x0      0
rip            0x1042b71        0x1042b71
eflags         0x202    [ IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) x/40xg $rsp-0x40
0x7ffc56f4d7c8: 0x00007ffc56f4d8a8      0x00007f39d5d32440
0x7ffc56f4d7d8: 0x00007f39d5ff1b40      0x0000000000000000
0x7ffc56f4d7e8: 0x0000000000000003      0x00007f39d6c7a540
0x7ffc56f4d7f8: 0x0000000001ee38d0      0x00007f39d6851930
0x7ffc56f4d808: 0x0000000000d858e0      0x0000000000000011
0x7ffc56f4d818: 0x0000000000000000      0x00007f3900000000
0x7ffc56f4d828: 0x0000000000000000      0x00007f39d5d0e000
0x7ffc56f4d838: 0x0000000000000000      0x0000000000000000
0x7ffc56f4d848: 0x0000000000000000      0x0000000000000000
0x7ffc56f4d858: 0x0000000000000001      0x00007f39d6c66e70
0x7ffc56f4d868: 0x00007f39d5d0e0a8      0x00000000000000d0
0x7ffc56f4d878: 0x0000000000000000      0x00007f39d5d0e0a8
0x7ffc56f4d888: 0x0000000000000001      0x000000000000001a
0x7ffc56f4d898: 0x0000000000da0bcd      0x000000000136874d
0x7ffc56f4d8a8: 0x00007f39d6b08bd0      0x000000000000001a
0x7ffc56f4d8b8: 0x00007f39d6b080a8      0x0000000000000000
0x7ffc56f4d8c8: 0x0000000000000000      0x0000000000000000
0x7ffc56f4d8d8: 0x000000ffffffffff      0xffffffff80000001
0x7ffc56f4d8e8: 0x00007f39d6851930      0x00007f39d5ff1b40
0x7ffc56f4d8f8: 0x0000000000000000      0x00007ffc56f4da00

たぶん、ズレは d858b9 のあたりだ。

  d85873:       48 98                   cltq
  d85875:       0f b6 53 04             movzbl 0x4(%rbx),%edx
  d85879:       44 0f b7 84 00 a0 a6    movzwl 0x12ca6a0(%rax,%rax,1),%r8d
  d85880:       2c 01
  d85882:       48 8d 73 10             lea    0x10(%rbx),%rsi
  d85886:       48 8d 7c 24 60          lea    0x60(%rsp),%rdi
  d8588b:       41 0f b7 4b 34          movzwl 0x34(%r11),%ecx
  d85890:       44 89 44 24 7c          mov    %r8d,0x7c(%rsp)
  d85895:       81 e1 ff 03 00 00       and    $0x3ff,%ecx
  d8589b:       e8 90 d2 2b 00          callq  1042b30
  d858a0:       8b 54 24 7c             mov    0x7c(%rsp),%edx
  d858a4:       41 89 c2                mov    %eax,%r10d
  d858a7:       89 44 24 78             mov    %eax,0x78(%rsp)
  d858ab:       41 c1 e2 06             shl    $0x6,%r10d
  d858af:       41 39 d2                cmp    %edx,%r10d
  d858b2:       77 44                   ja     d858f8
  d858b4:       48 8d 6c 24 60          lea    0x60(%rsp),%rbp
  d858b9:       48 8d bc 24 80 00 00    lea    0x80(%rsp),%rdi
  d858c0:       00

d858b9 が実行されたかどうかは定かでないが、call の後そこまでは正常に実行されていたとおぼしき内容は確認できる。 残念ながらズレた時の d85890 の実行で 0x7c(%rsp) は破壊されているので d858a0 の内容の検証はできないが、今回は int3 のおかげでそのときのレジスターの値は残っている。%r10 に 0x40 (1<<6) が入っていること、0x78(%rsp) (0x7ffc56f4d888) に 1 が入っていること、%r10d と %edx が等しいこと、%rbp に 0x60(%rsp) (0x7ffc56f4d870) のアドレスが入っていることから、d858b4 までは実行されたと考えて矛盾はない。 また、0x4(%rbx) には以下のように 1 が入っているため、ズレた時に d85875 は実行されなかったと考えるのが自然。

(gdb) x/bx $rbx+4
0x7f39d6851934: 0x01

d85879 の 0x12ca6a0(%rax,%rax,1) は以下の内容でレジスターと一致。

(gdb) x/hx 0x12ca6a0+$rax+$rax
0x12ca6a2 <mode_precision+2>:   0x0000

次の d85882 と d85886 もレジスターの内容が一致。その次の d8588b もメモリーの内容が一致。

(gdb) x/hx 0x34+$r11
0x7f39d6b080dc: 0x0040

d85890 による書き込み結果は上にある通り 0x7c(%rsp) (0x7ffc56f4d88c) には 0 が書き込まれているため一致しており、d85895 の and 結果もフラグレジスターの内容も一致するので、たぶん、d858b9 を実行しようとした時になぜか d85879 からの命令列を実行していたということで、これで 0x11 問題は説明できていると思う。

%2 休暇

マルハニチロの株主総会。 今日は土産をもらいに行っただけ。 ここは株主総会のおみやげもちょっと豪華。 鯖水煮缶詰と鮭フレークとゼリーと DHA 何とか、都心の人なら交通費分くらいはあるし、9 時ちょっと過ぎの時点でもう土産持って歩いている人を見たので、近辺に勤めている人なら、朝イチに寄って土産もらってから出勤なんて人もいるかも。

続いて FFRI の株主総会。 初。 来ている株主はそんなに多くはない印象。 報告はシンプル、ナレーションがちゃんと入ってると思ったが、招集ご通知の内容をスライドに貼ってナレーションはそれを読み上げているだけだったw 海外展開始めますよー、ってのが新たなポイントなのか。 まずは北米から。 個人向けは特に Android 等向けは販促費がかかるとのことで、見直していくつもりのよう。 昨今のランサムウェアの被害増大に伴い需要は増えているもよう。 あんまり質問も出ないので、平均勤続年数 2.1 年ってどうなんですかと聞いてみたら、2014 年頃から新卒採用や中途採用をしてきた人数が結構あるらしくて、それで短くなってますーとのことだった。

FFRI は株主総会後に休憩を挟み、代表と取締役もう 1 人が出てきて、今後の展望についての説明があった。 海外向けを伸ばしていきたいもくろみらしい。 まぁあの主力製品をメンテし続けていられるなら技術力的にはそんなに心配はないだろうと思う。 こういう製品があるんだ、とユーザーに認知してもらうところのハードルは確かにあるよなぁ。

%3 移動

朝 6 時台に目覚めてしまったので、テキトーに移動を開始。 すでに雨は降りだしていた。 バスで三鷹まで出て、各駅停車の始発を狙う作戦。 バスは混んでいた。7 時台はこんなに込むものなのか。 府中からなので余裕で座っていたのだけど、前の一人席にいたら、混雑してきて横に立っていた女子高生がだんだん近寄ってきて... 途中からもうバス停スキップしてたな、なんかアナウンスしてたからたぶん後続のバスに乗ってくれということなんだろう。 バス専用レーンのあるところはすいすいだ。 まぁこのあたりはバスの本数が多いから、バス専用レーンの渋滞回避効果は高いだろう。 原付で通ったことはあるが、バスからその景色を見るのは初めてだった。

三鷹の整列乗車はやっぱり意味わかんない。 何がなんだか。 都営三田線の停車駅を調べた結果、地下鉄東西線直通で、大手町まで出ることにした。 これもまぁ席は埋まる程度には混雑するが、ぎゅうぎゅうにはならない。 九段下あたりで降りる人と乗る人が多く、大手町は案外誰も降りなくて人をかき分けることになってしまったが...

やっぱり大手町で見る通勤客の皆さんの足音は怖い。 ざっざっざっ、と、どこぞの軍隊か。 まぁでも端っこをゆっくり歩く分にはみんなスルーだ。 途中で迷ってきょろきょろしてるとちょっと邪魔っぽいけど、こんなところたまにしか来ないから仕方ないだろ!

時間が早かったので三田線の改札前にあったドトールで朝食を取った。 ドトールの中の仕組みも知らなかったよ。 朝は席取りは決済後。 水はセルフサービス。 意外と新聞なんか読んでのんびりしている人は多いように見えた。 んで三田線がまた意外と混雑しているような... 芝公園まで行ってメルパルクホール。

そこから今度は浜松町に出てみることにした。 そしたら山手線遅れてた。 京浜東北線に乗ったが田町で乗り換えるべきだった。 そしたら目の前だったし空いていたはず。 品川まで行ったら階段登っての乗り換えになった上、山手線ホームが遅れの影響で人だらけ。 田町だったらうまくいけば座れていたと思う。 まーそんなこんなで割とぎゅうぎゅうで恵比寿行った。 恵比寿で何度か靴が滑って危なかった。

帰りは渋谷経由で明大前でカレーを食って帰った。

2017/06/28 のコメントを読む・書く


29 (木)

%1 ポケモン GO

レイドバトルだかなんだかそういうのができて、ジムがずいぶん変わったのだが、コマ落ちがひどくてなんだかよくわからず、一度バトルをしようとしたら、カウントダウンが出てきて、始まるぞというところで「ネットワークエラー」。 うーん。 それで、ジムにポケモンをおくというのは一応できて、以前のようにボーナスをもらおうとショップを開いたら、ない。 ボーナスのシステム変わったのか。 帰ってきた後で確認したら増えていた。

ポケストップがジムに化けたところがけっこうあって、アイテムもらえないのかと思えばそうでもなくて、一応ジムでもアイテムをもらえるようになっている。 今までジムだったところもアイテムをもらえるのでむしろアイテムをもらえるところが増えたとも言える。 しかし、ポケモン GO Plus がジムからアイテムを拾ってくれるわけではなさそうだ。 三鷹駅だと南口の通りの商店街にあるたくさんのポケストップは割とそのままで、駅前のケヤキだっけ、主にバス・タクシーのロータリーみたいになっているところがひとつジムになった。 多磨駅でも近くの体育館だったかな、そこがジムに化けた。 人見街道の、新撰組の何とかかんとか、近藤神社だっけ、そこも。 他にもいくつか。

%2 cc1 core dump

cc1 のシグナルハンドラーが正常に機能すると core dump が出てこないので、何とかならないか、と考えていたが、ふと簡単な方法を思いついた。 この前、シグナルハンドラーから internal error が呼ばれている、というのがわかったとき、シグナルハンドラーのアドレスもわかってしまったのだ。 そこに int3 を仕込めば、core dump が出る。 しかも、struct sigcontext が残るので、ページフォールトの詳細などもわかる。 画期的!

632318c632318
<   7d6572:     53                      push   %rbx
---
>   7d6572:     cc                      int3

後はたくさん試行してたくさんの core dump をゲットすれば楽しみが増える。 なお、Debian GNU/Linux 9 のカーネルパッケージのアップデートに伴い、若干挙動が変わったようだが、前と同じ segfault も出ることは出るみたいなので、一晩実行して収集してみよう。

2017/06/29 のコメントを読む・書く


30 (金)

%1 映画

テレビでやってた映画『藁の楯』。2013 年の邦画。 約 2 年ぶり。 相変わらず読めない。

最初のほうはあまり記憶に残っていなかったが、移送を始めたところから記憶がよみがえってきた。 ただし詳細は覚えておらず、何か起こるたびに、ああそうだった、の繰り返し。 藤原竜也の狂った犯人の演技、大沢たかおのガチ SP っぽい演技などが見所だなぁ。 なお、拳銃を撃つシーンはいまいち迫力に欠ける。 反動がわざとらしいというか。

%2 きのうの core dump

いくつか取れたが、試しにそのうちのひとつを調べ始めたらこれがよくわからない。 なぜか %rip=0 になっているので、当然、スタックを見て、戻り番地らしきものがあって、そこにはメモリーからジャンプ先アドレスを取得する call 命令があり、確かにそこから来てしまったもののよう。 さらにさかのぼって見ていったのだが、不審な点が見当たらない...

なお、こないだの int3 ハックを残してあるので、いくつかはその番地でクラッシュしている。 それらは全く同じパターンと見て良いだろう。 あと、クラッシュせずに internal error が出てしまうケースも発生した。

0x40 バイトズレ問題で気になるのは、ズレた時点ではきれいに命令境界にまたがることなくズレている点で、その後の call 等で変なアドレスに飛んでしまうことはあっても、ズレた瞬間に変な命令を実行しているケースはまだ確認できていない。 もしかしたら、変な位置にズレたら Machine Check Exception が出るのかな、なんて想像はしている。 それを検証するには、同じファイルのビルド繰り返しで同じトラブルが発生するパターンを使って、cc1 の一部のバイナリーを書き換えてわざと該当部分の命令をわずかに変えればいいのかな? うまくいくかどうかはわからないが。

2017/06/30 のコメントを読む・書く


Powered by Tomsoft Diary System 1.7.4

/var/log/hdk.log コメント一覧

トップ / 日記索引 / 日記 (2017 年 6 月下旬)

Hideki EIRAKU