mprotect - システムコールの説明 - Linux コマンド集 一覧表
名前
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 と設定されているメモリ領域に対して、 prot を PROT_WRITE として mprotect () を呼び出すと、 その領域はもはや読み取り可能ではなくなる。
返り値
成功した場合、 mprotect ()は 0 を返す。エラーの場合は -1 が返り、 errno が適切に設定される。
エラー
- EACCES
- 指定されたアクセスをメモリに設定することができない。 これは、例えば ファイルを読み取り専用で mmap (2) しており、その領域に対して mprotect ()を呼び出して PROT_WRITE に設定しようとした場合に発生する。
- EFAULT
- メモリがアクセス可能でない。
- EINVAL
- addr が有効なポインタでないか、PAGESIZE の倍数でない。
- ENOMEM
- カーネル内部の構造体を割り当てることができなかった。 もしくは、 [ addr , addr + len ]という範囲のアドレスがプロセスのアドレス空間として不正であるか、 その範囲のアドレスがマップされていない 1 つ以上のページを指した。
例
#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(0); }
準拠
SVr4, POSIX.1-2001. POSIX では、 mprotect ()は mmap (2) で獲得したメモリ領域に対してのみ使用できるとしている。
注意
Linux では、(カーネル vsyscall 領域以外の)
任意のプロセスアドレス空間において
mprotect
()を呼び出すことが、常に許されている。
これは特に既存のコードマッピングを書き込み可能にするために使われる。
PROT_EXEC
が
PROT_READ
と異なる影響を持つか否かは、アーキテクチャとカーネルのバージョンに依存する。