名前


mprotect - メモリ領域のアクセス許可を制御する

書式


#include <sys/mman.h>

int mprotect(const void *addr, size_t len, int prot);

説明


mprotect() は区間 [addr,addr+len-1] の一部またはすべてを含む メモリページの所望のアクセス保護を指定する。 指定したアクセス保護で禁止されたアクセスを行なうと、 プログラムは SIGSEGV を受信する。

prot は以下の値のビットごとの論理和 (bitwize-or) である:
PROT_NONE そのメモリには全くアクセスできない。
PROT_READ そのメモリを読み取ることができる。
PROT_WRITE そのメモリに書き込むことができる。
PROT_EXEC そのメモリに実行コードを含むことができる。
新しいアクセス保護はそれまでのアクセス保護を置き換える。 例えば、それまで PROT_READ と設定されているメモリ領域に対して、 protPROT_WRITE として mprotect() を呼び出すと、 その領域はもはや読み取り可能ではなくなる。

返り値


成功した場合、 mprotect() は 0 を返す。エラーの場合は -1 が返り、 errno が適切に設定される。

エラー


EACCES 指定されたアクセスをメモリに設定することができない。 これは、例えば ファイルを読み取り専用で mmap(2) しており、その領域に対して mprotect() を呼び出して PROT_WRITE に設定しようとした場合に発生する。
EFAULT メモリがアクセス可能でない。
EINVAL addr が有効なポインタでないか、PAGESIZE の倍数でない。
ENOMEM カーネル内部の構造体を割り当てることができなかった。 もしくは、 [addr, addr+len] という範囲のアドレスがプロセスのアドレス空間として不正であるか、 その範囲のアドレスがマップされていない 1 つ以上のページを指した。

準拠


SVr4, POSIX.1-2001. POSIX では、 mprotect() は mmap(2) で獲得したメモリ領域に対してのみ使用できるとしている。

注意


Linux では、(カーネル vsyscall 領域以外の) 任意のプロセスアドレス空間において mprotect() を呼び出すことが、常に許されている。 これは特に既存のコードマッピングを書き込み可能にするために使われる。

PROT_EXECPROT_READ と異なる影響を持つか否かは、アーキテクチャとカーネルのバージョンに依存する。


#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/mman.h>

#include <limits.h> /* PAGESIZE を使用するため */ #ifndef PAGESIZE #define PAGESIZE 4096 #endif

int main(void) { char *p; char c;

/* バッファを確保する。デフォルトのアクセス保護 PROT_READ|PROT_WRITE になる。*/ p = malloc(1024+PAGESIZE-1); if (!p) { perror("Couldn’t malloc(1024)"); exit(errno); }

/* PAGESIZE の倍数にアラインメントをそろえる。 PAGESIZE は 2 の累乗であると仮定する。*/ p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));

c = p[666]; /* 読み取り; 成功 */ p[666] = 42; /* 書き込み; 成功 */

/* バッファを読み取り専用に設定する。*/ if (mprotect(p, 1024, PROT_READ)) { perror("Couldn’t mprotect"); exit(errno); }

c = p[666]; /* 読み取り; 成功 */ p[666] = 42; /* 書き込み; プログラムは SIGSEGV で強制終了する */

exit(EXIT_SUCCESS); }

関連項目


mmap(2)

openSUSE Logo

コンテンツ