1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

mprotect(2) に関するメモ

Posted at

概要

straceの結果の常連mprotectをあまり理解してなかったのでメモ

mprotect(2)とは

mprotect(2)とはメモリ領域のアクセス許可を制御するシステムコール。

man mprotect(2)

# include <sys/mman.h>

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

ポインタとサイズとビットの論理和を渡す。

フラグ

現在、以下の OR をとって組み合わせることが可能な保護ビット

フラグ名 概要
PROT_NONE 全く保護しません
PROT_READ ページは読取り可能です
PROT_WRITE ページは書込み可能です
PROT_EXEC ページは実行可能です

エラー

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

errno 概要
EACCES 指定されたアクセスをメモリーに設定することができない
EINVAL addr が有効なポインターでないか、 システムのページサイズの倍数でない
ENOMEM カーネル内部の構造体を割り当てることができなかった
ENOMEM [addr, addr+len-1] という範囲のアドレスがプロセスのアドレス空間として不正であるか、 その範囲のアドレスがマップされていない 1 つ以上のページを指している

使用例

READ_ONLY領域のメモリへ書き込みを行うことでSIGSEGVを発生させるサンプルプログラム。

SIGSEGV自体はsigactionを使ってハンドリングした処理を実行。

mprotect.c
# include <unistd.h>
# include <signal.h>
# include <stdio.h>
# include <malloc.h>
# include <stdlib.h>
# include <errno.h>
# include <sys/mman.h>

# define handle_error(msg) \
    do { perror(msg); exit(EXIT_FAILURE); } while (0)

static char *buffer;

static void handler(int sig, siginfo_t *si, void *unused)
{
    printf("Got SIGSEGV at address: 0x%lx\n",
        (long) si->si_addr);
    exit(EXIT_FAILURE);
}

int main(int argc, char **argv)
{
    char *p;
    int pagesize;
    

    // シグナルの動作の変更
    struct sigaction sa;
    sa.sa_flags = SA_SIGINFO;
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = handler;
    if (sigaction(SIGSEGV, &sa, NULL) == -1)
        handle_error("sigaction");

    pagesize = sysconf(_SC_PAGE_SIZE);
    if (pagesize == -1)
        handle_error("sysconf");

    // アライメントされたメモリを割り当てる
    buffer = memalign(pagesize, 4 * pagesize);
    if (buffer == NULL)
        handle_error("memalign");

    printf("Start of region:        0x%lx\n", (long) buffer);

    // メモリ領域のアクセス許可を制御
    if (mprotect(buffer + pagesize * 2, pagesize, PROT_READ) == -1)
        handle_error("mprotect");

    for (p = buffer ; ; )
        *(p++) = 'a';

    printf("Loop completed\n");     /* Should never happen */
    exit(EXIT_SUCCESS);
}
1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?