web-dev-qa-db-ja.com

割り当てられたメモリのチャンクを読み取り専用としてマークする方法はありますか?

malloc()を使用してメモリを割り当てると、読み取り専用としてマークする方法があります。だから誰かがそれに書き込もうとするとmemcpy()は失敗しますか?

これは、ユーザーが大規模なメモリ構造の一部であるメソッドGetValue()によって返されるconstポインターを誤って使用している、不完全なAPI設計に接続されています。メモリの大きなチャンクのコピーを避けたいので、特定の形式の構造化メモリ内にライブポインターを返します。今問題は、一部のユーザーがこのメモリに直接書き込むことで何かを機能させるためのハックを見つけ、割り当てを行い、開発したメモリのバイナリ形式で適切に渡すSetValue()呼び出しを回避することです。ユーザーによって上書きされた制御フラグの誤った解釈が原因で、時々ハッキングはありますが、時にはメモリアクセス違反が発生します。

ユーザーの教育は1つのタスクですが、ここではコードが失敗するようにしたいとします。

ただこの事件から身を守ることができるのだろうか。

類推のために、誰かがsqliteステートメントからblob列を取得してから、それに書き戻すと仮定します。 sqliteの場合は意味がありませんが、これは私たちの場合はややハッピングです。

48
particle

ほとんどのハードウェアアーキテクチャでは、保護属性を変更できるのは メモリページ 全体のみです。ページのフラグメントに読み取り専用のマークを付けることはできません。

関連するAPIは次のとおりです。

メモリページに、読み取り専用にしたくないものが含まれていないことを確認する必要があります。これを行うには、malloc()でオーバーローケートするか、mmap()posix_memalign()VirtualAlloc()などの別の割り当てAPIを使用する必要があります。

60
NPE

プラットフォームによって異なります。 Linuxでは、mprotect()( http://linux.die.net/man/2/mprotect )を使用できます。

Windowsでは、VirtualProtect()( http://msdn.Microsoft.com/en-us/library/windows/desktop/aa366898(v = vs.85).aspx )を試すことができます。私はそれを使ったことがありません。

編集:これはNPEの回答の複製ではありません。 NPEはもともと別の答えを持っていました。それは後で編集され、mprotect()とVirtualProtect()が追加されました。

36
Nikos C.

大規模なメモリ構造の一部であるGetValue()メソッドによって返されるconstポインタをユーザーが誤って使用している不完全なAPI設計。メモリの大きなチャンクのコピーを避けたいので、特定の形式の構造化メモリ内にライブポインタを返します

それは明らかに不完全なAPI設計ではありません。 APIはコントラクトです。クラスが特定の方法で動作することを約束し、クラスのクライアントが適切な方法でAPIを使用することを約束します。 const_castのような汚いトリックは不適切です(一部のケースでは ndefined behaviour )。

const_castを使用するとセキュリティ問題が発生する場合、API設計に欠陥がある可能性があります。その場合、メモリのチャンクをコピーするか、またはAPIを再設計する必要があります。 これはJavaの標準です 、これは const に相当するものはありません(constはJavaの予約語であるにもかかわらず)。

5
Raedwald

ポインタを難読化します。つまり、ポインターとオフセットをクライアントに返します。これで、直接ポインターを使用できなくなります。公式APIを介してポインターがコードに渡される場合は常に、オフセットを減算して、通常どおりポインターを使用します。

0
Jeff McClintock