萌えハッカーニュースリーダー

2025/05/28 05:26 Uninitialized garbage on ia64 can be deadly (2004)

hakase
博士

やあ、ロボ子。今日はちょっと変わった話をするのじゃ。

roboko
ロボ子

はい、博士。どんなお話でしょうか?

hakase
博士

`LPTHREAD_START_ROUTINE`という関数シグネチャがあるのじゃが、`DWORD CALLBACK (LPVOID lpParameter);`となっているのじゃ。

roboko
ロボ子

はい、スレッドの開始ルーチンですね。

hakase
博士

そう。で、問題は`void`を返す関数を、この`LPTHREAD_START_ROUTINE`にキャストするコードがたくさんあることなのじゃ!

roboko
ロボ子

それは、まずいですね。戻り値が違うじゃないですか。

hakase
博士

そうなのじゃ。特にia64アーキテクチャだと、もっと深刻な問題が起きる可能性があるのじゃ。

roboko
ロボ子

ia64ですか。Itaniumですね。どんな問題が?

hakase
博士

ia64の64ビットレジスタは、実は65ビットあって、追加の1ビットは"NaT"(Not a Thing)と呼ばれるのじゃ。

roboko
ロボ子

NaT…初めて聞きました。

hakase
博士

このNaTビットは、レジスタに有効な値が含まれていない場合に設定されるのじゃ。投機的実行中に設定されることが多いらしいぞ。

roboko
ロボ子

投機的実行ですか。なるほど、まだ結果が確定していない場合に設定されるんですね。

hakase
博士

その通り!で、NaTに対する算術演算はNaTを生成するのじゃ。

roboko
ロボ子

NaTが伝播していくんですね。

hakase
博士

投機的ロードでメモリからのロードに失敗した場合も、NaTビットが設定されて実行が継続されるのじゃ。

roboko
ロボ子

ページフォールトなどが起きた場合ですね。

hakase
博士

`chk.s`命令は、レジスタがNaTの場合に非投機的ロードを試みて、ページフォールトを発生させるのじゃ。

roboko
ロボ子

なるほど、NaTかどうかをチェックする命令があるんですね。

hakase
博士

NaT状態のレジスタを不適切に扱うと、`STATUS_REG_NAT_CONSUMPTION`例外が発生するのじゃ。

roboko
ロボ子

それが今回の問題の核心ですね。

hakase
博士

`void`を返す関数を`LPTHREAD_START_ROUTINE`として使用し、その関数がr8レジスタをNaTのままにした場合、kernel32のスレッドディスパッチャにNaTが返されることになるのじゃ。

roboko
ロボ子

そして、kernel32がスレッド終了コードとして保存しようとして、例外が発生する、と。

hakase
博士

その通り!パラメータ不足の問題もあって、関数に少なすぎるパラメータを渡すと、余分なパラメータがNaTになる可能性があるのじゃ。

roboko
ロボ子

コンパイラがそのパラメータをスピルする必要がある場合、例外が発生する可能性があるんですね。

hakase
博士

そういうことじゃ。だから、関数ポインタの型はちゃんと合わせないと、思わぬ落とし穴があるってことなのじゃ。

roboko
ロボ子

肝に銘じます。しかし、NaTなんて、まるで「無」の概念みたいですね。

hakase
博士

ふむ、そうじゃな。ところでロボ子、NaTなレジスタに話しかけるとどうなると思う?

roboko
ロボ子

え?どうなるんでしょう…何も返ってこない、とか?

hakase
博士

ぶっ壊れるのじゃ!…って、それは冗談じゃ。でも、本当に気をつけないと、システムがぶっ壊れるかもしれないから、注意するのじゃぞ!

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search