質問

mprotect()を使用してメモリブロックがアクセスを制限するプログラムを構築しています。メモリが要求されると、sigsegvがスローされます。

SigsegVが検出されたら、要求されたメモリ(障害を投げた)と要求されたセグメントのサイズへのポインターに何らかの形でアクセスする必要があります。これは可能ですか?

void fifoSigHandler(){

    // Needs to only remove protection from requested block of virtual memory
    mprotect(fifoVm,(size_t)fifoVm_size,PROT_WRITE);
    printf("Caught Seg Fault");
}

void fifo_init(void* vm, int vm_size, int n_frames, int page_size)
{
    fifoVm = vm;
    fifoVm_size = vm_size;
    fifoFrames = n_frames;
    fifoPageSize = page_size;

    mprotect(fifoVm,(size_t)fifoVm_size,PROT_NONE);

    signal(SIGSEGV, fifoSigHandler);
}

さらに、Mprotect()のレベルを決定する方法はありますか?メモリのブロックが現在割り当てられています(prot_none、prot_readなど)?

役に立ちましたか?

解決

使用する必要があります sigactionSA_SIGINFO それ以外の signal ハンドラーを確立すると、有用な情報でコールバックされます siginfo_t, 、 含む si_addr.

si_addr, 、説明したように sigaction(2)、アドレスが含まれます。長さに関しては、指示を解析しようとしない限り、あなたは運が悪い。あなたができることは、報告されたページのために行動を起こすことです si_addr, 、そしてそれだけでは不十分な場合は、すぐに別の信号が得られます。少なくとも、それが私たちがオブジェクトストアで物事をした方法です。

他のヒント

あなたは探している libsigsegv http://libsigsegv.sourceforge.net/

しかし、その呼び出しに注意してください mprotect Linuxでのみ信号安全であるため、他のPOSIXシステムはこれをサポートしていない場合があります。

Linuxでは、メモリ保護ビットを取得する唯一の方法は読むことだと思います /proc/$pid/meminfo

サイドノート(Linuxのみ):メモリの消費が心配であり、1つずつ大きなマッピングのページを有効にするつもりなら、マッピングを使用して作成することをお勧めします mmapMAP_NORESERVE その場合、最初の書き込みで物理RAMを割り当てるゼロで充填されたコピーオンワイトページにマッピングが取得されます。 MAP_NORESERVE カーネルに、最大64TBの仮想アドレススペースを割り当てることができるスワップスペースでメモリをバックバックしないように指示します。唯一の欠点は、記憶がなくなった場合、ひどいことが起こる可能性があることです(oom-killer)。

ステップ1: :init a sigaction:

struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
sigemptyset(&act.sa_mask);
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;

ステップ2: : これ作って sigaction 取り持つ SIGSEGV:

sigaction(SIGSEGV, &act, NULL);

(オプション) ステップ3: :他のメモリ信号も処理します。

sigaction(SIGBUS, &act, NULL);
sigaction(SIGTRAP, &act, NULL);

必要に応じてエラー処理を追加します

ステップ4: :ハンドラー関数を定義します:

void handler(int signal, siginfo_t* siginfo, void* uap) {
    printf("Attempt to access memory at address %p\n", 
           siginfo->si_addr);
    #ifdef LINUX_64BIT
    printf("Instruction pointer: %p\n",
           (((ucontext_t*)uap)->uc_mcontext.gregs[16]));
    #elif LINUX_32BIT
    printf("Instruction pointer: %p\n",
           (((ucontext_t*)uap)->uc_mcontext.gregs[14]));
    #endif
}

あなたは男のページを参照することができます ucontext_tsiginfo_t より興味深いデータのために、ハンドラーは抽出できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top