https://marc.info/?l=openbsd-tech&m=152035796722258&w=2
OpenBSDはスタックレジスタチェックを導入
「カーネルによって機会主義的に施行される」->選択肢という意味ですか?
システムコールが発生すると、スタックポインタレジスタがそのページを指していることを確認します。そうしないと、プログラムは終了します。- プログラマーでない人にスタックレジスタについてもっと詳しく説明できる人はいますか?オプションであれば、なぜそれがないすべてのプログラムを終了するのですか?
答え1
スタックポインタレジスタはハードウェアレジスタです。スタックに使用される領域のメモリ位置*を指します。スタックポインタレジスタは、通常、メモリアクセスの前後でポインタ値を増加または減少させてスタックのデータアドレスを指定するために使用される。このチェックはシステムコールが発生したときに実行され、レジスタが有効なスタックアドレスを指しているかどうかを確認します。 「機会主義」は「選択的」を意味しません。
[*]: 一部のアーキテクチャでは、有効なアドレスがスタックページの最後のアドレスの後のアドレスである場合があります。
答え2
すべてのスレッドにスタックがあります。スタックは、スレッドがローカル変数、関数戻りアドレスなどを格納するために使用する特別なメモリ領域です。 CPUがスレッドを実行すると、そのスレッドのレジスタ(SP)はスタックのメモリアドレスを指す必要があります。
ほとんどの場合、カーネルはスレッドスタックを割り当てますが、アプリケーションがスタックを生成することもあります。アプリケーションは、シグナルハンドラ(カーネルがプロセスにシグナルを送信するときに実行されるコード)のカスタムスタックを作成または実装するために実行できます。スレッドライブラリ。
この目的のために、アプリケーションはカーネルにメモリ領域を要求し、それをスタックとしてマークし、カーネルがその領域がスタックであることを知ることができます。ただし、開発者エラーのため、アプリケーションはカーネルにスタックに登録されていないメモリを使用するように要求できます。この場合、何か悪いことが発生する可能性があります。カーネルは便利なデータがスタックに書き込まれたと思いますが、スタックではないので上書きできます!ハッカーはそれを使用してプログラムを破壊する可能性があります。
OpenBSD でメモリを予約する場合 (例: mmap を使用する場合)、以下を明示的に指定する必要があります。
日当たりの良いシーン:
- アプリケーション:カーネル、スタックとして使用するメモリを少し持つことができますか?
- カーネル:もちろん、これはあなたのメモリです
- アプリケーション:良いです。これをシグナルスタックとして使用します。
- カーネル: ok (信号処理時に CPU SP レジスタがこのメモリを指すように内部構造を構成)
雨の日のシーン:
- アプリケーション:カーネル、少しメモリを持つことができますか?
- カーネル:もちろん、これはあなたのメモリです
- アプリケーション:良いです。これをシグナルスタックとして使用します。
- カーネル:しかし、このメモリはスタック用ではありません!あなたは私をだましたい!
- (カーネルがアプリケーションを終了する)
以下は、これらのフラグの追加例です。
PROT_EXEC:コード(CPUが実行できるもの)を格納するためにメモリを予約するようにカーネルに要求するPROT_WRITE:書き込み可能なデータを格納するメモリを予約するようにカーネルに要求する
したがって、データを実行したりコードを書くことはできません(これはW^Xと呼ばれ、OpenBSDの人々はそれを誇りに思います)。
より多くの例を読んで学ぶman mmap
ことができます。map sigaltstack