mprotect(2) - wariua/manpages-ko GitHub Wiki
mprotect, pkey_mprotect - λ©λͺ¨λ¦¬ μμμ λ³΄νΈ μ€μ νκΈ°
#include <sys/mman.h>
int mprotect(void *addr, size_t len, int prot);
#define _GNU_SOURCE /* feature_test_macros(7) μ°Έκ³ */
#include <sys/mman.h>
int pkey_mprotect(void *addr, size_t len, int prot, int pkey);
mprotect()
λ [addr
, addr+len-1
] κ΅¬κ° μ£Όμ λ²μλ₯Ό μΌλΆλΌλ λ΄κ³ μλ νΈμΆ νλ‘μΈμ€μ λ©λͺ¨λ¦¬ νμ΄μ§λ€μ λν μ κ·Ό 보νΈλ₯Ό λ³κ²½νλ€. addr
μ΄ νμ΄μ§ κ²½κ³μ λ§κ² μ λ ¬λμ΄ μμ΄μΌ νλ€.
νΈμΆ νλ‘μΈμ€μμ κ·Έ 보νΈλ₯Ό μλ°νλ λ°©μμΌλ‘ λ©λͺ¨λ¦¬μ μ κ·Όνλ € μλνλ©΄ 컀λμ΄ κ·Έ νλ‘μΈμ€μ SIGSEGV
μκ·Έλμ μμ±νλ€.
prot
λ PROT_NONE
μ΄κ±°λ λ€μ λͺ©λ‘μ λ€λ₯Έ κ°λ€μ λΉνΈ OR ν κ²μ΄λ€.
PROT_NONE
- λ©λͺ¨λ¦¬μ μ ν μ κ·Όν μ μλ€.
PROT_READ
- λ©λͺ¨λ¦¬λ₯Ό μ½μ μ μλ€.
PROT_WRITE
- λ©λͺ¨λ¦¬λ₯Ό λ³κ²½ν μ μλ€.
PROT_EXEC
- λ©λͺ¨λ¦¬λ₯Ό μ€νν μ μλ€.
-
PROT_SEM
(리λ μ€ 2.5.7λΆν°) - λ©λͺ¨λ¦¬λ₯Ό μμ μ°μ°μ μΈ μ μλ€. μ΄ νλκ·Έλ futex(2) ꡬνμ μΌλΆλ‘μ (
FUTEX_WAIT
κ°μ λͺ λ Ήμ νμν μμ μ°μ° μνμ΄ κ°λ₯ν¨μ 보μ₯νκΈ° μν΄) λμ λμλλ° νμ¬λ μ΄λ μν€ν μ²μμλ μ°μ§ μλλ€. -
PROT_SAO
(리λ μ€ 2.6.26λΆν°) - λ©λͺ¨λ¦¬μ κ°ν μ κ·Ό μμ(strong access ordering)κ° μμ΄μΌ νλ€. μ΄ κΈ°λ₯μ PowerPC μν€ν μ²μ νμ λ κ²μ΄λ€. (μν€ν μ² λͺ μΈ 2.06 λ²μ μμ SAO CPU κΈ°λ₯μ μΆκ°νλ©° POWER 7μ΄λ PowerPC A2 λ±μμ μ¬μ© κ°λ₯νλ€.)
μΆκ°λ‘ (리λ
μ€ 2.6.0λΆν°) prot
μ λ€μ νλκ·Έλ€ μ€ νλλ₯Ό μ€μ ν μ μλ€.
PROT_GROWSUP
- μλ‘ μλΌλ λ§€νμ λμ κΉμ§ λ³΄νΈ λͺ¨λλ₯Ό μ μ©νλ€. (μ€νμ΄ μλ‘ μλΌλ, κ°λ Ή HP-PARISC κ°μ μν€ν μ²μμ μ€ν μμμ κ·Έλ° λ§€νμ λ§λ λ€.)
PROT_GROWSDOWN
- μλλ‘ μλΌλ λ§€νμ μμμ κΉμ§ λ³΄νΈ λͺ¨λλ₯Ό μ μ©νλ€. (μ€ν μΈκ·Έλ¨ΌνΈμ΄κ±°λ
MMAP_GROWSDOWN
νλκ·Έλ₯Ό μ€μ ν΄ λ§΅ ν μΈκ·Έλ¨ΌνΈμΌ κ²μ΄λ€.)
mprotect()
μ²λΌ pkey_mprotect()
λ addr
κ³Ό len
μΌλ‘ μ§μ ν νμ΄μ§λ€μ 보νΈλ₯Ό λ³κ²½νλ€. pkey
μΈμλ κ·Έ λ©λͺ¨λ¦¬μ ν λΉν λ³΄νΈ ν€(pkeys(7) μ°Έκ³ )λ₯Ό λνλΈλ€. λ³΄νΈ ν€λ pkey_alloc(2)μΌλ‘ ν λΉν΄μ pkey_mprotect()
μκ² μ λ¬ν΄μΌ νλ€. μ΄ μμ€ν
νΈμΆμ μ¬μ©λ‘λ pkeys(7)λ₯Ό 보λΌ.
μ±κ³΅ μ mprotect()
μ pkey_mprotect()
λ 0μ λ°ννλ€. μ€λ₯ μ μ΄ μμ€ν
νΈμΆλ€μ -1μ λ°ννλ©° errno
λ₯Ό μ μ ν μ€μ νλ€.
EACCES
- μ§μ ν μ κ·ΌκΆμ λ©λͺ¨λ¦¬μ μ€ μ μλ€. μλ₯Ό λ€μ΄ μ½κΈ° μ μ©μΌλ‘λ§ μ κ·Όν μ μλ νμΌμ mmap(2) νκ³ μ
mprotect()
μκ²PROT_WRITE
νμλ₯Ό νλΌκ³ νλ κ²½μ°μ λ°μν μ μλ€. EINVAL
-
addr
μ΄ μ ν¨ν ν¬μΈν°κ° μλκ±°λ μμ€ν νμ΄μ§ ν¬κΈ°μ λ°°μκ° μλλ€. EINVAL
- (
pkey_mprotect()
)pkey
κ° pkey_alloc(2)μΌλ‘ ν λΉλ κ²μ΄ μλλ€. EINVAL
-
prot
μPROT_GROWSUP
κ³ΌPROT_GROWSDOWN
μ λͺ¨λ μ§μ νλ€. EINVAL
-
prot
μ μ ν¨νμ§ μμ νλκ·Έλ₯Ό μ§μ νλ€. EINVAL
- (PowerPC μν€ν
μ²)
prot
μPROT_SAO
λ₯Ό μ§μ νμ§λ§ SAO νλμ¨μ΄ κΈ°λ₯μ΄ μ¬μ© κ°λ₯νμ§ μλ€. ENOMEM
- λ΄λΆ 컀λ ꡬ쑰체λ₯Ό ν λΉν μ μλ€.
ENOMEM
- [
addr
,addr+len-1
] κ΅¬κ° λ΄μ μ£Όμκ° νλ‘μΈμ€μ μ£Όμ 곡κ°μμ μ ν¨νμ§ μκ±°λ, ν κ° μ΄μμ λ§΅ λμ§ μμ νμ΄μ§λ₯Ό λνλΈλ€. (컀λ 2.4.19 μ μμλ μ΄ κ²½μ°μ μλͺ»ν΄μEFAULT
μ€λ₯λ₯Ό μμ±νλ€.) ENOMEM
- λ©λͺ¨λ¦¬ μμμ 보νΈλ₯Ό λ³κ²½νλ©΄ μμ΄ν μμ±(κ°λ Ή μ½κΈ° 보νΈμ μ½κΈ°/μ°κΈ° 보νΈ)μ λ§€ν μ΄κ°μκ° νμ© μ΅λμΉλ₯Ό μ΄κ³Όνκ² λλ€. (μλ₯Ό λ€μ΄ νμ¬
PROT_READ|PROT_WRITE
λ‘ λ³΄νΈνλ μμ μ€κ°μ μ΄λ λ²μλ₯ΌPROT_READ
보νΈλ‘ λ§λ€λ©΄ μμͺ½μ μ½κΈ°/μ°κΈ° λ§€νκ³Ό κ°μ΄λ°μ μ½κΈ° μ μ© λ§€νμ ν©μ³μ μΈ κ° λ§€νμ΄ μκΈ΄λ€.)
리λ
μ€ 4.9μμ pkey_mprotect()
κ° μ²μ λ±μ₯νλ€. glibc 2.27μμ λΌμ΄λΈλ¬λ¦¬ μ§μμ΄ μΆκ°λμλ€.
mprotect()
: POSIX.1-2001, POSIX.1-2008, SVr4. POSIXμμλ mmap(2)μ ν΅ν΄ μ»μ κ²μ΄ μλ λ©λͺ¨λ¦¬ μμμ μ μ© μ mprotect()
μ λμ λ°©μμ΄ λͺ
μΈλμ΄ μμ§ μλ€κ³ νλ€.
pkey_mprotect()
λ μ΄μμ± μλ 리λ
μ€ νμ₯μ΄λ€.
리λ
μ€μμλ νλ‘μΈμ€ μ£Όμ κ³΅κ° λ΄μ (컀λ vsyscall μμμ μ μΈν) μ΄λ μ£Όμμλ mprotect()
νΈμΆμ νμ νμ©νλ€. νΉν μ΄λ₯Ό μ΄μ©ν΄ κΈ°μ‘΄μ μ½λ λ§€νμ μ°κΈ° κ°λ₯μΌλ‘ λ°κΏ μ μλ€.
PROT_EXEC
μ PROT_READ
μλ λ€λ₯Έ μ΄λ€ ν¨λ ₯μ΄ μλμ§ μ¬λΆλ νλ‘μΈμ μν€ν
μ², 컀λ λ²μ , νλ‘μΈμ€ μνμ λ°λΌ μ ν΄μ§λ€. νλ‘μΈμ€ μΈκ²© νλκ·Έ(personality(2) μ°Έκ³ )μ READ_IMPLIES_EXEC
κ° μ€μ λΌ μμΌλ©΄ PROT_READ
λ₯Ό μ§μ ν λ PROT_EXEC
κ° μ묡μ μΌλ‘ μΆκ°λλ€.
μΌλΆ νλμ¨μ΄ μν€ν
μ²(κ°λ Ή i386)μμλ PROT_WRITE
κ° PROT_READ
λ₯Ό ν¨μνλ€.
POSIX.1μμλ ꡬνμμ prot
μ μ§μ λ κ² μ΄μΈμ μ κ·Όμ νμ©ν μλ μλ, μ΅μνμΌλ‘λ PROT_WRITE
κ° μ€μ λ κ²½μ°μλ§ μ°κΈ° μ κ·Όμ νμ©ν μ μκ³ PROT_NONE
μ΄ μ€μ λ κ²½μ°μλ μ΄λ€ μ κ·Όλ νμ©ν΄μ μ λλ€κ³ νλ€.
μμ©μμ mprotect()
μ pkey_mprotect()
λ₯Ό μμ΄μ μ¬μ©ν λλ μ£Όμν΄μΌ νλ€. x86μμ prot
λ₯Ό PROT_EXEC
λ‘ μ€μ ν΄μ mprotect()
λ₯Ό μ°λ©΄ 컀λμμ μ묡μ μΌλ‘ pkeyλ₯Ό ν λΉν΄μ λ©λͺ¨λ¦¬μ μ€μ ν μλ μλ€. λ¨ pkeyκ° μμ 0μ΄μμ λλ§ κ·Έλ κ² νλ€.
νλμ¨μ΄μμ λ³΄νΈ ν€λ₯Ό μ§μνμ§ μλ μμ€ν
μμλ pkey_mprotect()
λ₯Ό μΈ μλ μμ§λ§ pkey
λ₯Ό -1λ‘ μ€μ ν΄μΌ νλ€. κ·Έλ κ² νΈμΆν λ pkey_mprotect()
μ λμμ mprotect()
μ λλ±νλ€.
μλ νλ‘κ·Έλ¨μ mprotect()
μ¬μ© λ°©μμ λ³΄μ¬ μ€λ€. νλ‘κ·Έλ¨μμ λ©λͺ¨λ¦¬ νμ΄μ§ 4κ°λ₯Ό ν λΉν΄μ κ·Έ μ€ μΈ λ²μ§Έλ₯Ό μ½κΈ° μ μ©μΌλ‘ λ§λ λ€μ ν λΉ μμμ μλ‘ νμΌλ©΄μ λ°μ΄νΈλ₯Ό λ³κ²½νλ 루νλ₯Ό μ€ννλ€.
λ€μμ νλ‘κ·Έλ¨ μ€ν μ λ³Ό μ μμ μΆλ ₯ μμ΄λ€.
$ ./a.out
Start of region: 0x804c000
Got SIGSEGV at address: 0x804e000
#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()λ₯Ό νΈμΆνλ κ²μ μμ νμ§
μλ€. (λ°λΌμ μ€μ μ¬μ©νλ νλ‘κ·Έλ¨μμλ νμ§ λ§μμΌ
νλ€.) printf()κ° λΉλκΈ° μκ·Έλ μμ μ΄ μλκΈ° λλ¬Έμ΄λ€.
signal-safety(7) μ°Έκ³ . κ·ΈλΌμλ λΆκ΅¬νκ³ νΈλ€λ¬κ° νΈμΆλ
κ²μ κ°λ¨ν λ³΄μ¬ μ£ΌκΈ° μν΄ μ¬κΈ°μ printf()λ₯Ό μ¬μ©νλ€. */
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");
/* νμ΄μ§ κ²½κ³μ λ§κ² μ λ ¬λ λ²νΌ ν λΉ.
μ΄κΈ° λ³΄νΈ λ°©μμ PROT_READ | PROT_WRITE */
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"); /* μ λ μ¬κΈ°κΉμ§ μ€μ§ μμ */
exit(EXIT_SUCCESS);
}
2019-08-02