スタックオーバーフローはハードウェアまたはソフトウェアによって検出されますか?


26

スタックオーバーフローを検出するのはソフトウェア(オペレーティングシステム)のタスクですか、それともハードウェアでスタックオーバーフローが検出され、CPUで例外が発生しますか?


ほとんどのCPUのMMUフォールトを通じて、ハードウェアと言えます。32ビットモードのx86には、ページングに加えてセグメンテーションがあり、「スタックセグメント」は、ベースアドレスとサイズの両方を持つコード、データ、拡張...セグメントのように関連付けられます。その範囲外にアクセスすると、障害がトリガーされます。
TEMLIB

回答:


25

ソフトウェア、ハードウェア、またはその両方、またはなしのいずれかです。

オーバーフローには2つの種類があります。スタックを成長させるとき(関数を入力するとき)のオーバーフローと、スタック上の配列にアクセスするときのオーバーフローです。スタックの成長時のオーバーフローは、関数のエントリで境界チェックを行い、十分なスペースがあることを確認することで検出できます(エラーがない場合はエラーを通知するか、スタックを成長させます)。スタック上の配列にアクセスする際のオーバーフローは、配列の境界を検証しない低レベル言語の問題にすぎません。解決策は、配列の境界を確認することです。

これらのソフトウェアアプローチには、完全に確実に動作するという利点があります。スタックオーバーフローが確実に検出されます。彼らの欠点は、コードサイズと実行時間が増加することです。ハードウェアは、オーバーフローが発生しない限り、ほとんどのオーバーフローを無料で検出する方法を提供することで役立ちます。MMU¹を備えたアーキテクチャでは、ランタイム環境は次のページがマッピングされないまま、ページ境界にスタックをマップするように調整できます。

+---------------+---------------+---------------+---------------+
| stack                         | unmapped      | other stuff   |
|    ----> direction of growth  |               |               |
+---------------+---------------+---------------+---------------+
^               ^               ^               ^               ^  page boundaries

そのように、ソフトウェアがページ境界を超えてデータにアクセスしようとすると(スタックポインターが境界を超えて移動したか、配列アクセスが境界外で境界を超えたため)、マップされていない領域にアクセスすることでエラーが発生します。これは、オーバーフローが十分に小さい場合にのみ発生します。オーバーフローの量が大きすぎると、プログラムはアドレス空間のギャップの反対側にある他のものにアクセスすることになります。

ハードウェアアプローチの欠点は、大量のオーバーフローが検出されない可能性があるため、完全に信頼できないことと、アドレス可能なスペース内に残る配列オーバーフローを検出しないことです。

配列のオーバーフローを検出するための別のソフトウェア技術はカナリアです。スタックの最上部またはフレーム間に特別な値を設定し、関数の戻り時にカナリア値が変更されていないことを確認します。これは、オーバーフローがカナリアを完全に回避するか、カナリア値がチェックされるまでにカナリア値が復元されているために検出されない可能性があるため、不完全な手法でもあります。それにもかかわらず、セキュリティの脆弱性を悪用するのを難しくすることは有用です。

スタックオーバーフローを回避する最も安全で安価な方法は、静的分析により、プログラムが実行を開始する前に必要なスタックの量を計算することです。ただし、これは常に実用的とは限りません。プログラムが必要とするスタックの量は一般に決定できず、プログラムが操作するデータに依存します。

¹ 同じ原則は、MPUのみに適用することも、既存の物理マッピングの端にスタックがある単一のスレッドがある場合はメモリ保護なしに適用することもできます。


4
配列がスタック上にある場合でも、範囲外の配列アクセスをスタックオーバーフローと呼びません。これは、バッファオーバーフローの特殊なケースです。
CodesInChaos

非スタック/フレームポインターまたは非定数オフセットに関連して参照されるプライマリスタック項目に割り当てないことで、従来のスタックオーバーフローを回避できます。別のリターンアドレススタック(またはItaniumのようなRA /レジスタスピルスタック)を使用すると、少なくともリターン指向のプログラミングの機会が大幅に減ります。
ポールA.クレイトン

範囲外アクセスは、オーバーフローではなく、オーバーランと呼ばれます。
ベンフォークト

3
@ awesomebing1は、すべてのプラットフォームがスタックオーバーフローを検出するわけではありません。スタックの後ろにあるものはすべて上書きされる可能性があります(他のバッファオーバーフローと同様)。
user253751

1
@CodesInChaos、スタックに割り当てられたバッファのバッファオーバーフローは、「スタックオーバーフロー」(略して)と呼ばれることがあります。確かに、その用語は文脈がないと少しわかりにくいかもしれません。
DW
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.