linuxプログラミングmprotect

2610 ワード

mprotect:メモリアクセス権の設定
mmapの3番目のパラメータはメモリ領域の保護を指定し、タグによる読み取り、書き込み、実行権限のPROT_READ、PROT_WRITEとPROT_EXECはビットと操作で取得するか、アクセス権のないPROTを制限するNONE.プログラムがこれらの権限が許可されていないローカルメモリ上で動作しようとすると、SIGSEGV信号(Segmentation fault、セグメントエラー)によって終了します.
メモリマッピングが完了しても、これらの権限はmprotectシステム呼び出しによって変更できます.mprotectのパラメータはそれぞれメモリ区間のアドレス,区間の大きさ,新しい保護フラグ設定である.指定したメモリ区間には、ページ全体が含まれている必要があります.区間アドレスはシステム全体のページサイズと一致し、区間長はページサイズの整数倍でなければなりません.これらのページの保護タグは、ここで指定した新しい保護モードに置き換えられます.
ページ整列を取得するメモリは、mallocが返すメモリ領域が通常、メモリページと整列していないことに注意してください.メモリのサイズがページサイズの整数倍の場合でも同じです.mallocから取得したメモリを保護するには、より大きなメモリ領域を割り当て、ページに整列した区間を見つけなければなりません.mmapシステム呼び出しを使用してmallocを迂回し、Linuxカーネルからページ整列メモリを直接割り当てることができます.
mmapは、/dev/zeroをマッピングすることによってメモリページを割り当てます.メモリは読み取り可能モードと書き込み可能モードに初期化されます.
int fd = open (“/dev/zero”, O_RDONLY);
char* memory = mmap (NULL, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
close (fd);

次に、mprotectを使用してプログラムを読み取り専用にすることができます.
mprotect (memory, page_size, PROT_READ);

mmapとmprotectを用いてターゲットメモリ区間を保護し、プログラムアクセス時にLinuxシステムから送信されるSIGSEGV信号を受信して処理するメモリアクセスを監視する高度なテクニックがある.コードはこのテクニックを示しています.
コードmprotectを使用してメモリアクセスを検出
#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!
”); mprotect (memory, alloc_size, PROT_READ | PROT_WRITE); } int main () { int fd; struct sigaction sa; /* segv_handler SIGSEGV 。*/ memset (&sa, 0, sizeof (sa)); sa.sa_handler = &segv_handler; sigaction (SIGSEGV, &sa, NULL); /* /dev/zero 。 。*/ alloc_size = getpagesize (); fd = open (“/dev/zero”, O_RDONLY); memory = mmap (NULL, alloc_size, PROT_WRITE, MAP_PRIVATE, fd, 0); close (fd); /* 。 */ memory[0] = 0; /* 。 */ mprotect (memory, alloc_size, PROT_NONE); /* 。 */ memory[0] = 1; /* ;unmap 。 */ printf (“all done
”); munmap (memory, alloc_size); return 0; }

上記の手順は、以下の手順で実行されます.
  • プログラムは、SIGSEGVのための信号処理ハンドルを確立する.
  • プログラムは、マッピング/dev/zeroによってメモリページングを割り当て、データを書き込むことによってプライベートコピーを取得する.
  • プログラムは呼び出しバンドPROT_を介してNONE権限のmprotectはメモリを保護します.
  • プログラムが後続の実行中にメモリを書き込むと、LinuxはプロセスにSIGSEGVを送信し、この信号はsegv_handlerハンドル受信処理.このハンドルはメモリ保護を解除するので、プログラムメモリアクセスは継続されます.
  • 信号ハンドルの実行が完了すると、プログラム制御権はmain関数に戻り、munmapを使用してメモリを解放する.