私が理解したところ、スタックカナリアは次のように動作します。プログラムが起動すると、ランダムな値が生成され、スレッドローカルストア(%fs:0x28
)に格納されます。このランダムな値は各関数呼び出し時にスタックにプッシュされるため、後で確認できます。
TLSエリアの「マスタークッキー」に関しては、2つの質問があります。
このレイアウトでは、スレッドローカルストレージはどこにありますか?
- プロセスが新しいスレッドを作成すると、スレッドローカルストア(したがってスタックカナリア値)は新しいスレッドにコピーされますか?それとも、カーネルはスレッドごとに新しいスタックカナリア値を生成しますか?
答え1
新しいスレッドが作成されると、スレッドスタックにメモリ領域が割り当てられます。スレッドローカル変数のためのスペースがこのゾーンから割り当てられます。厳密に言えば、TLS変数はスタックの一部ではありません。つまり、スタックからプッシュもポップもされませんが、スタック上部の同じ領域に存在します。
この領域がアドレス空間内に位置する位置は、いくつかの要因に依存する。 Create a new thread を使用すると、
pthread_create
プログラマはスレッドのスタックとして使用するメモリにポインタを渡すことができます。このメモリの位置は、メモリの割り当て方法によって異なります。事前に割り当てられたメモリを使用しない場合は、mmap
with引数NULL
を使用してメモリ領域が割り当てられ、addr
カーネルはメモリがマップされる場所を決定できます。 x86_64では、このように割り当てられたメモリはスタックとヒープの間にあります。各スレッドは新しいカナリア値を使用します。回答を見るこの問題。