Spectreドキュメント から、コンパイラが無効な配列インデックスを参照するメモリ読み取り命令を生成するため、攻撃が成功する可能性があることを学びました。また、命令は通常、配列のインデックスをチェックした後にのみ実行されますが、一部のCPUでの投機的実行により、範囲外の要素にアクセスすると望ましくない副作用が生じます。
javascript:
x=array[index];
assembler pseudocode:
MOV reg,index
CMP reg,array[length]
JNC fail
MOV x,array[reg]
...access probe array based on x
無効なアドレスを生成しないようにコンパイラーを変更した場合はどうなりますか?
assembler pseudocode:
MOV reg,index
CMP reg,array[length]
JNC fail
AND reg,array[bit_mask] <---| bit mask of all 1's lower than
MOV x,array[reg] | 2*length (might be an object member)
...access probe array based on x
このように、追加のANDの価格で、投機的読み取りで使用されるアドレスは2 *未満の長さに制限されます。次に、すべての配列バッファーに対して、常に2を割り当てましょうN バイト(N> =ログ2(長さ))と攻撃者は、自身の未使用のメモリのみをプローブできます(または、プローブに使用できるメモリが他のバッファのみになるようにメモリ割り当てを調整します)。
これは良い考えですか?
Spectreの起こり得る影響を軽減するために、他の方法の中でもWebKit開発者が同様のアプローチを採用しました。
参照:"WebKitのスペクターとメルトダウンの意味"、段落 "インデックスマスキング「。
インデックスマスキングは、2を割り当てる必要がないという点で、提案とは異なります。N 各配列のバイト数(最悪の場合、必要な量のほぼ2倍)であるため、情報の(ある程度制限された)部分が攻撃者に公開されますが、攻撃者が全体的に読み取り、一部のメモリを節約できるデータ量は減少します。効果のために。大規模な配列の場合、ASLRにある程度の信頼を置いているため、インデックスマスクの到達可能性内に割り当てが行われる可能性が低くなります。
それにもかかわらず、WebKitでこの方法で攻撃者に実際にさらされる可能性があるのは、そのアーキテクチャとコードベースによって異なります。あなたのものは異なる場合があります。
最悪の場合、要求されたメモリのほぼ2倍の割り当ての有効性に関して、理想的な配列の成長率 1.6に近い と2の成長係数 広く使用されていますが、効果が低い 。
ただし、Linuxを想定すると、投機的な境界外読み取りから依然として安全でありながら、失われるメモリの量を減らすために使用できるトリックが存在する可能性があります。カスタムアロケーターを作成して、少なくとも2 *ページサイズ(後者はほとんどの状況で後者は4Kですが、厳密にはsysconf(SC_PAGE_SIZE)
)の配列に対して、最初に_/proc/self/maps
_を解析して、サイズが2以上のマップされていないメモリ領域を見つけるN バイト、N> =ログ2(array_length)、そしてmmap(MAP_FIXED)
を介して必要なサイズのみをマップします。
以前に割り当てられた配列の2 * length内にメモリがマップされないようにするために、いくつかの後続の作業が必要になりますが、これはまだロケットサイエンスではありません。
割り当てられて返されるメモリページは仮想メモリで連続しますが、物理メモリで連続している必要はないため、このアプローチではphysicalメモリの断片化。後続の仮想メモリの断片化は、64ビットシステムではおそらくすぐには問題にならないでしょう。アドレス可能な合計16エクサバイトのメモリが必要になるためです。誰にとっても十分です。
他のオペレーティングシステムには、おそらくLinuxと同様のツールがあります。
WebKitに関しては、他の緩和策も備えているため、現時点ではSpectre自体の影響を十分に満たすことができるため、インデックスマスキングはそれらに対してかなり過剰な緩和策であり、それらのアプローチは残りの脅威モデルに対しては問題ありません。
ただし、脅威モデルは異なる場合があります。私たちが知っているのはそれだけです。