pkeys(7) - wariua/manpages-ko GitHub Wiki
pkeys - ๋ฉ๋ชจ๋ฆฌ ๋ณดํธ ํค ๊ฐ์
๋ฉ๋ชจ๋ฆฌ ๋ณดํธ ํค(Memory Protection Key, pkey)๋ ๊ธฐ์กด์ ํ์ด์ง ๊ธฐ๋ฐ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํ๊ฐ์ ๋ํ ํ์ฅ์ด๋ค. ํ์ด์ง ํ ์ด๋ธ์ ์ด์ฉํ ์ผ๋ฐ์ ์ธ ํ์ด์ง ์ ๊ทผ ํ๊ฐ์์๋ ํ๊ฐ ๋ณ๊ฒฝ ์ ๊ฐ๋น์ผ ์์คํ ํธ์ถ๊ณผ TLB ๋ฌดํจํ๊ฐ ํ์ํ๋ค. ๋ฉ๋ชจ๋ฆฌ ๋ณดํธ ํค๋ ํ๊ฐ ๋ณ๊ฒฝ ๋๋ง๋ค ํ์ด์ง ํ ์ด๋ธ์ ๋ณ๊ฒฝํ ํ์ ์์ด ๋ณดํธ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ๋ค.
pkey๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ ์ํํธ์จ์ด์์ ํ์ด์ง ํ ์ด๋ธ ๋ด์ ํ์ด์ง์ pkey "ํ๊ทธ"๋ฅผ ๋ถ์ฌ์ผ ํ๋ค. ๊ทธ ํ์ ์์ฉ์์ ํ๊ทธ ๋ถ์ ํ์ด์ง์ ๋ํ ์ฐ๊ธฐ ์ ๊ทผ๊ถ์ด๋ ์ ์ฒด ์ ๊ทผ๊ถ์ ์ ๊ฑฐํ๋ ค๋ฉด ๋ ์ง์คํฐ์ ๋ด์ฉ๋ง ๋ฐ๊พธ๋ฉด ๋๋ค.
๋ณดํธ ํค๋ mprotect(2)์ mmap(2) ๊ฐ์ ์์คํ
ํธ์ถ์ ์ ๋ฌํ ๊ธฐ์กด์ PROT_READ
/PROT_WRITE
/PROT_EXEC
ํ๊ฐ์ ๊ฒฐํฉ๋ผ์ ๋์ํ๋ค. ์ธ์ ๋ ๊ทธ ์ ํต์ ํ๊ฐ ๋ฉ์ปค๋์ฆ์ ๋ ์ ์ฝํ๋ ๋ฐฉ์์ผ๋ก ๋์ํ๋ค.
์ด๋ ํ๋ก์ธ์ค์์ ํค ์ ์ฝ์ ์๋ฐํ๋ ์ ๊ทผ์ ์ํํ๋ฉด SIGSEGV
์๊ทธ๋์ ๋ฐ๋๋ค. ๊ทธ ์๊ทธ๋์์ ์ป์ ์ ์๋ ์ ๋ณด์ ๋ํ ์์ธํ ๋ด์ฉ์ sigaction(2)์ ์๋ค.
pkey ๊ธฐ๋ฅ์ ์ฐ๋ ค๋ฉด ํ๋ก์ธ์์์ ์ด๋ฅผ ์ง์ํด์ผ ํ๊ณ ํด๋น ํ๋ก์ธ์์์์ ๊ธฐ๋ฅ ์ง์์ด ์ปค๋์ ํฌํจ๋์ด ์์ด์ผ ํ๋ค. 2016๋ ์ด ํ์ฌ ํฅํ์ ์ธํ x86 ํ๋ก์ธ์ค๋ค๋ง ์ง์ํ๋ฉฐ, ๊ทธ ํ๋์จ์ด์์๋ ํ๋ก์ธ์ค๋ณ๋ก 16๊ฐ ๋ณดํธ ํค๋ฅผ ์ง์ํ๋ค. ํ์ง๋ง pkey 0์ ๊ธฐ๋ณธ ํค๋ก ์ฐ์ด๊ธฐ ๋๋ฌธ์ ์ค์ ์์ฉ ์ฉ๋๋ก๋ ์ต๋ 15๊ฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค. pkey_mprotect(2)๋ฅผ ํตํด ๋ช ์์ ์ผ๋ก pkey๋ฅผ ๋ถ์ฌํ์ง ์์ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๊ธฐ๋ณธ ํค๊ฐ ๋ถ์ฌ๋๋ค.
๋ณดํธ ํค์๋ ์์ฉ์ ๋ณด์ ๋ฐ ์ ๋ขฐ์ฑ ๊ณ์ธต์ ๋ํด ์ค ์ ์ฌ๋ ฅ์ด ์๋ค. ํ์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก๋ ๋ณด์ ๊ธฐ๋ฅ์ผ๋ก ์ค๊ณ๋ ๊ฒ์ด ์๋๋ค. ์๋ฅผ ๋ค์ด WRPKRU๋ ์์ ํ ๋นํน๊ถ ์ธ์คํธ๋ญ์ ์ด๊ณ , ๋ฐ๋ผ์ ๊ณต๊ฒฉ์๊ฐ PKRU ๋ ์ง์คํฐ๋ฅผ ํต์ ํ๊ณ ์๊ฑฐ๋ ์์ ์ธ์คํธ๋ญ์ ์ ์คํํ ์ ์๋ ๊ฒฝ์ฐ์๋ pkey๊ฐ ์์ฉ์๋ค.
์์ฉ์์๋ ๋ณดํธ ํค๋ฅผ "๋์ถ"ํ์ง ์๋๋ก ์์ฃผ ์กฐ์ฌํด์ผ ํ๋ค. ์๋ฅผ ๋ค์ด ์์ฉ์์ pkey_free(2) ํธ์ถ ์ ์๋ ์ด๋ค ๋ฉ๋ชจ๋ฆฌ์๋ ๊ทธ pkey๊ฐ ํ ๋น๋์ด ์์ง ์๋๋ก ํด์ผ ํ๋ค. ์์ฉ์์ ํด์ ๋ ๊ทธ pkey๋ฅผ ํ ๋น๋ ์ฑ๋ก ๋๋ฉด ํฅํ ๊ทธ pkey์ ์ฌ์ฉ์๊ฐ ์๋์น ์๊ฒ ์๊ด์๋ ์๋ฃ ๊ตฌ์กฐ์ ์ ๊ทผ ํ๊ฐ๋ฅผ ๋ฐ๊พธ๊ฒ ๋ ์๋ ์์ ํ
๊ณ , ๊ทธ๊ฒ ๋ณด์์ฑ์ด๋ ์์ ์ฑ์ ์ํฅ์ ์ค ์๋ ์๋ค. ์ปค๋์์๋ ํ์ฌ ์ฌ์ฉ ์ค์ธ pkey์ pkey_free(2) ํธ์ถ์ ํ๋ ๊ฒ์ ํ์ฉํ๊ณ ์๋๋ฐ, ๊ทธ๊ฑธ ๋ง๊ธฐ ์ํด ์ถ๊ฐ ๊ฒ์ฌ๋ฅผ ์ํํ๋ ๊ฒ์ด ํ๋ก์ธ์ค ๋ด์ง ๋ฉ๋ชจ๋ฆฌ ์ฑ๋ฅ์ ์ํฅ์ ์ค ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค. ํ์ํ ๊ฒ์ฌ๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ์์ฉ์ ๋ชซ์ด๋ค. /proc/[pid]/smaps
ํ์ผ์์ pkey๊ฐ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ํ์ํ๋ ๋ฐฉ์์ผ๋ก ์์ฉ์์ ๊ทธ๋ฐ ๊ฒ์ฌ๋ฅผ ๊ตฌํํ ์ ์๋ค.
๋ณดํธ ํค๋ฅผ ์ฌ์ฉํ๊ณ ์ ํ๋ ์์ฉ์ ๋ณดํธ ํค ์์ด๋ ๋์ํ ์ ์์ด์ผ ํ๋ค. ์์ฉ์ด ๋์ํ๋ ํ๋์จ์ด์์ ์ง์ํ์ง ์๊ฑฐ๋, ์ปค๋ ์ฝ๋์ ์ง์์ด ํฌํจ๋์ด ์์ง ์๊ฑฐ๋, ์ปค๋ ์ง์์ด ๊บผ์ ธ ์๊ฑฐ๋, ํค๊ฐ ๋ชจ๋ (๊ฒฝ์ฐ์ ๋ฐ๋ผ์ ์์ฉ์์ ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํด) ํ ๋น๋์ด์ ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ ์๋ ์์ ๊ฒ์ด๋ค. ๋ณดํธ ํค๋ฅผ ์ฌ์ฉํ๊ณ ์ ํ๋ ์์ฉ์์ ๊ธฐ๋ฅ ์ง์์ ํ์งํ๊ธฐ ์ํด ๋ค๋ฅธ ๋ฐฉ์์ ์๋ํ๋ ๋์ ๊ทธ๋ฅ pkey_alloc(2)์ ํธ์ถํด ๋ณด๊ธฐ๋ฅผ ๊ถ์ฅํ๋ค.
๋ถํ์ํ ์ผ์ด๊ธด ํ์ง๋ง ํ๋์จ์ด์ ๋ณดํธ ํค ์ง์์ cpuid
์ธ์คํธ๋ญ์
์ผ๋ก ํ์ธํด ๋ณผ ์๋ ์๋ค. ์์ธํ ๋ฐฉ๋ฒ์ Intel Software Developers Manual์์ ์ฐพ์ ์ ์๋ค. ์ปค๋์์ ๊ทธ ํ์ธ์ ํด์ /proc/cpuinfo
๋ด์ "flags" ํ๋๋ก ์ ๋ณด๋ฅผ ๋๋ฌ๋ธ๋ค. ์ด ํ๋์ ๋ฌธ์์ด "pku"๊ฐ ์์ผ๋ฉด ๋ณดํธ ํค๋ฅผ ํ๋์จ์ด์์ ์ง์ํ๋ค๋ ํ์์ด๊ณ ๋ฌธ์์ด "ospke"๊ฐ ์์ผ๋ฉด ์ปค๋์ ๋ณดํธ ํค ์ง์์ด ํฌํจ๋์ด ์๊ณ ์ผ์ ธ ์๋ค๋ ํ์์ด๋ค.
์ค๋ ๋์ ๋ณดํธ ํค๋ฅผ ์ฌ์ฉํ๋ ์์ฉ์์๋ ํนํ ์กฐ์ฌํด์ผ ํ ๊ฒ์ด๋ค. ์ค๋ ๋๋ clone(2) ์์คํ ํธ์ถ ์์ ์ ๋ถ๋ชจ๋ก๋ถํฐ ๋ณดํธ ํค ๊ถํ์ ๋ฌผ๋ ค๋ฐ๋๋ค. ์์ฉ์์๋ clone(2) ํธ์ถ ์์ ์ ์๊ธฐ ๊ถํ์ด ์์ ์ค๋ ๋์๊ฒ ์ ์ ํ๋๋ก ํ๊ฑฐ๋, ์๋๋ฉด ๊ฐ ์์ ์ค๋ ๋์์ ์์ฒด์ ์ผ๋ก ๋ณดํธ ํค ๊ถํ ์ด๊ธฐํ๋ฅผ ์ํํ ์ ์๋๋ก ํด์ผ ํ ๊ฒ์ด๋ค.
์๊ทธ๋ ํธ๋ค๋ฌ๊ฐ ๋ถ๋ฆด ๋๋ง๋ค (์ค์ฒฉ ์๊ทธ๋ ํฌํจ) ์ค๋จ๋ ๋ฌธ๋งฅ์ ๊ถํ์ ๋ฎ๋ ์๋ก์ด ๊ธฐ๋ณธ ๋ณดํธ ํค ๊ถํ ์ธํธ๊ฐ ์ค๋ ๋์๊ฒ ์์๋ก ์ฃผ์ด์ง๋ค. ์ฆ ์์ฉ์์ ์ํ๋ ๊ถํ์ด ๊ธฐ๋ณธ ์ธํธ์ ๋ค๋ฅด๋ค๋ฉด ์๊ทธ๋ ํธ๋ค๋ฌ ์ง์ ์งํ์ ์ํ๋ ๋ณดํธ ํค ๊ถํ์ ์ฌ์ค์ ํด์ผ ํ๋ค. ์๊ทธ๋ ํธ๋ค๋ฌ๊ฐ ๋ฐํํ ๋ ์ค๋จ๋๋ ๋ฌธ๋งฅ์ ๊ถํ์ด ๋ณต์๋๋ค.
์ด๋ฐ ํน์ดํ ์๊ทธ๋ ๋์ ๋ฐฉ์์ (๋ณดํธ ํค ์ ๊ทผ๊ถ์ ์ ์ฅํ๋) x86 PKRU ๋ ์ง์คํฐ๋ฅผ ๋ถ๋์์์ ๋ ์ง์คํฐ์ ๊ฐ์ ํ๋์จ์ด ๋ฉ์ปค๋์ฆ(XSAVE)์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ด ์๊ทธ๋ ๋์ ๋ฐฉ์์ ๋ถ๋์์์ ๋ ์ง์คํฐ์ ๋์ผํ๋ค.
๋ฆฌ๋ ์ค ์ปค๋์์ ๊ตฌํํ๊ณ ์๋ pkey ๊ด๋ จ ์์คํ ํธ์ถ์ pkey_mprotect(2), pkey_alloc(2), pkey_free(2)์ด๋ค.
๋ฆฌ๋
์ค์ pkey ์์คํ
ํธ์ถ์ CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
์ต์
์ผ๋ก ์ปค๋์ ๊ตฌ์ฑํ์ฌ ๋น๋ ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
์๋ ํ๋ก๊ทธ๋จ์์๋ ๋ฉ๋ชจ๋ฆฌ ํ ํ์ด์ง๋ฅผ ์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ ํ๊ฐ๋ก ํ ๋นํ๋ค. ๊ทธ๋ฌ๊ณ ์ ๋ฉ๋ชจ๋ฆฌ์ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์จ๋ฃ๊ณ ์ฑ๊ณต์ ์ผ๋ก ์ฝ์ด๋ค์ธ๋ค. ๊ทธ ํ์ ๋ณดํธ ํค๋ฅผ ํ ๋นํ์ฌ WRPKRU ์ธ์คํธ๋ญ์ ์ผ๋ก ๊ทธ ํ์ด์ง์ ๋ํ ์ ๊ทผ์ ๋ถํํด ๋ณธ๋ค. ๊ทธ๋ฌ๊ณ ์ ํ์ด์ง์ ์ ๊ทผ์ ์๋ํ๋๋ฐ, ์ด๋ฒ์๋ ์์ฉ์ ์น๋ช ์ ์๊ทธ๋์ ์ผ์ผํค๊ฒ ๋๋ค.
$ ./a.out
buffer contains: 73
about to read buffer again...
Segmentation fault (core dumped)
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <sys/mman.h>
static inline void
wrpkru(unsigned int pkru)
{
unsigned int eax = pkru;
unsigned int ecx = 0;
unsigned int edx = 0;
asm volatile(".byte 0x0f,0x01,0xef\n\t"
: : "a" (eax), "c" (ecx), "d" (edx));
}
int
pkey_set(int pkey, unsigned long rights, unsigned long flags)
{
unsigned int pkru = (rights << (2 * pkey));
return wrpkru(pkru);
}
int
pkey_mprotect(void *ptr, size_t size, unsigned long orig_prot,
unsigned long pkey)
{
return syscall(SYS_pkey_mprotect, ptr, size, orig_prot, pkey);
}
int
pkey_alloc(void)
{
return syscall(SYS_pkey_alloc, 0, 0);
}
int
pkey_free(unsigned long pkey)
{
return syscall(SYS_pkey_free, pkey);
}
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
int
main(void)
{
int status;
int pkey;
int *buffer;
/*
* ๋ฉ๋ชจ๋ฆฌ ํ์ด์ง ํ ๊ฐ ํ ๋น
*/
buffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (buffer == MAP_FAILED)
errExit("mmap");
/*
* ํ์ด์ง์ ์ ๋นํ ์์ ๋ฐ์ดํฐ ๋ฃ๊ธฐ (์์ง ๊ฑด๋๋ ค๋ ๊ด์ฐฎ์)
*/
*buffer = __LINE__;
printf("buffer contains: %d\n", *buffer);
/*
* ๋ณดํธ ํค ํ ๋น
*/
pkey = pkey_alloc();
if (pkey == -1)
errExit("pkey_alloc");
/*
* "pkey"๊ฐ ์ค์ ๋ ๋ฉ๋ชจ๋ฆฌ(ํ์ฌ๋ ์์)์ ๋ํ ์ ๊ทผ ๋๊ธฐ
*/
status = pkey_set(pkey, PKEY_DISABLE_ACCESS, 0);
if (status)
errExit("pkey_set");
/*
* "buffer"์ ๋ณดํธ ํค ์ค์ .
* mprotect()์ ๊ด๋ จํด์ ์ฌ์ ํ ์ฝ๊ธฐ/์ฐ๊ธฐ์ด๋ฉฐ
* ์์ pkey_set()์ด ์ด๋ฅผ ์ค๋ฒ๋ผ์ด๋ ํ๋ค.
*/
status = pkey_mprotect(buffer, getpagesize(),
PROT_READ | PROT_WRITE, pkey);
if (status == -1)
errExit("pkey_mprotect");
printf("about to read buffer again...\n");
/*
* ์ ๊ทผ์ ๋ถํํ์ผ๋ฏ๋ก ์ฃฝ๊ฒ ๋จ
*/
printf("buffer contains: %d\n", *buffer);
status = pkey_free(pkey);
if (status == -1)
errExit("pkey_free");
exit(EXIT_SUCCESS);
}
pkey_alloc(2), pkey_free(2), pkey_mprotect(2), sigaction(2)
2019-03-06