2

読み取り/書き込みのためにページを保護する必要がある小さなswを実行する必要があり、メモリがアクセスされると、カウンターをインクリメントして読み取り/書き込みを許可する必要があります。その後、メモリを元に戻す必要があります

私はこのコードを持っていますが、無限ループを引き起こしています

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

static int alloc_size;
static char* memory;

void segv_handler (int signal_number) 
{
 printf ("memory accessed!\n");
 /* allow read and write */
 mprotect (memory, alloc_size, PROT_READ | PROT_WRITE);

 /* Protect memory back*/
 mprotect (memory, alloc_size, PROT_NONE);
} 

int main ()
{
 struct sigaction sa;

 /* Install segv_handler as the handler for SIGSEGV. */
 memset (&sa, 0, sizeof (sa));
 sa.sa_handler = &segv_handler;
 sigaction (SIGSEGV, &sa, NULL);

 alloc_size = 4096;
 memory = mmap (0, alloc_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);   /* anonymous mapping doesn't need a file desc */

 /* Write to the page to obtain a private copy. */
 memory[0] = 0;
 memory[1] = 0;

 /* Make the memory unwritable. */
 mprotect (memory, alloc_size, PROT_NONE);
 /* Write to the allocated memory region. */
 memory[0] = 1; //--> this should trigger the SIGSEGV
 memory[1] = 1;

 /* All done; unmap the memory. */
 printf ("all done\n");
 munmap (memory, alloc_size);
 return 0;
}
4

2 に答える 2

0

基本的に(1)無効なメモリアクセスをキャッチし、(2)ページの保護を一時的に解除し、(3)メモリアクセスを許可し、(4)ページを再保護し、(5)通常の実行を再開すると言いました。しかし、それはあなたのコードが行うことではありません。ページのsegv_handler保護を解除し(ステップ2)、すぐに再度保護します(ステップ4)。そのため、segv_handler戻るまでにステップ3には遅すぎます。命令が再び失敗し、無限ループが発生します。

シグナルハンドラーのインストールは、あなたがする必要があることをサポートしていません。あなたがする必要があるのは、いくつかの変更を加え、単一の命令を実行してから、さらにいくつかの変更を加えることです。デバッガーの下でプログラムをシングルステップするだけで、これを行うことができます。

ptraceこれを行うために必要なシステムコールです。SOには、ptraceとシングルステッピングについて多くの 質問がありますが、警告します。ptraceは気弱な人向けではなく、シグナルハンドラーよりもはるかに複雑です。

于 2012-08-12T22:26:24.910 に答える