mprotect(2) System Calls Manual mprotect(2) mprotect, pkey_mprotect - (libc -lc) #include int mprotect(size_t size; void addr[size], size_t size, int prot); #define _GNU_SOURCE /* feature_test_macros(7) */ #include int pkey_mprotect(size_t size; void addr[size], size_t size, int prot, int pkey); mprotect() [addr, addr+size-1]. addr . SIGSEGV . prot : PROT_NONE OR : PROT_NONE . PROT_READ . PROT_WRITE . PROT_EXEC . PROT_SEM ( Linux 2.5.7) . futex(2) ( FUTEX_WAIT) . PROT_SAO ( Linux 2.6.26) . PowerPC ( 2.06 SAO CPU POWER 7 PowerPC A2 ). ( Linux 2.6.0) prot : PROT_GROWSUP . ( -- HP-PARISC-- .) PROT_GROWSDOWN ( MAP_GROWSDOWN). mprotect() pkey_mprotect() addr size. pkey ( pkeys(7)) . pkey_alloc(2) pkey_mprotect(). pkeys(7). mprotect() pkey_mprotect() . -1 errno . EACCES . mmap(2) mprotect() PROT_WRITE . EINVAL addr . EINVAL (pkey_mprotect()) pkey pkey_alloc(2) EINVAL PROT_GROWSUP PROT_GROWSDOWN prot. EINVAL prot. EINVAL ( PowerPC) PROT_SAO prot SAO . ENOMEM . ENOMEM [addr, addr+size-1] . ( Linux 2.4.19 EFAULT .) ENOMEM ( /) . ( PROT_READ PROT_READ|PROT_WRITE : / .) POSIX mprotect() mmap(2). mprotect() ( vsyscall ). . PROT_EXEC PROT_READ . READ_IMPLIES_EXEC ( personality(2)) PROT_READ PROT_EXEC. ( i386) PROT_WRITE PROT_READ. POSIX.1 prot PROT_WRITE PROT_NONE. mprotect() pkey_mprotect(). x86 mprotect() prot PROT_EXEC (pkey) 0 . pkey_mprotect() pkey -1. pkey_mprotect() mprotect(). mprotect() POSIX.1-2024. pkey_mprotect() . mprotect() SVr4, SUSv1, POSIX.1-1996. pkey_mprotect() 4.9 glibc 2.27. mprotect(). . : $ ./a.out Start of region: 0x804c000 Got SIGSEGV at address: 0x804e000 #include #include #include #include #include #include #include static char *buffer; static void handler(int sig, siginfo_t *si, void *unused) { /* Note: calling printf() from a signal handler is not safe (and should not be done in production programs), since printf() is not async-signal-safe; see signal-safety(7). Nevertheless, we use printf() here as a simple way of showing that the handler was called. */ printf("Got SIGSEGV at address: %p\n", si->si_addr); exit(EXIT_FAILURE); } int main(void) { int pagesize; struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = handler; if (sigaction(SIGSEGV, &sa, NULL) == -1) err(EXIT_FAILURE, "sigaction"); pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize == -1) err(EXIT_FAILURE, "sysconf"); /* Allocate a buffer aligned on a page boundary; initial protection is PROT_READ | PROT_WRITE. */ buffer = memalign(pagesize, 4 * pagesize); if (buffer == NULL) err(EXIT_FAILURE, "memalign"); printf("Start of region: %p\n", buffer); if (mprotect(buffer + pagesize * 2, pagesize, PROT_READ) == -1) err(EXIT_FAILURE, "mprotect"); for (char *p = buffer ; ; ) *(p++) = 'a'; printf("Loop completed\n"); /* Should never happen */ exit(EXIT_SUCCESS); } mmap(2), sysconf(3), pkeys(7) 3 . . : . 6.18 11 2026 mprotect(2)