Arm Permission Overlay Extension (POE)

Ph.D Chroniclesยท2026๋…„ 9์›” 7์ผ

ARM

๋ชฉ๋ก ๋ณด๊ธฐ
5/5

๐Ÿ“ Permission Indirection / Overlay Extension?

ARMv8.9-A / ARMv9.4-A ์—์„œ ์ถ”๊ฐ€๋œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์ œ์–ด ๊ธฐ๋ฒ•์œผ๋กœ, page table์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ TLB invalidation ์—†์ด ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์˜ ์ ‘๊ทผ ๊ถŒํ•œ์„ ๋™์ ์œผ๋กœ ์ œํ•œํ•˜๋Š” ๊ฒƒ์„ ๋ชฉ์ ์œผ๋กœ ํ•œ๋‹ค.

PAC, MTE๊ฐ€ ๊ฐ๊ฐ control flow ๋ฌด๊ฒฐ์„ฑ๊ณผ ๋ฉ”๋ชจ๋ฆฌ ํƒœ๊น…์„ ๋‹ด๋‹นํ–ˆ๋‹ค๋ฉด, ์ด๋ฒˆ์— ๋‹ค๋ฃฐ PIE + POE๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋„๋ฉ”์ธ ๊ฒฉ๋ฆฌ๋ฅผ ํ•˜๋“œ์›จ์–ด ๋ ˆ๋ฒจ์—์„œ ๋‹ค๋ฃจ๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.

POE๋ฅผ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๋ ค๋ฉด ARMv8.9์—์„œ ํ•จ๊ป˜ ๋„์ž…๋œ Permission Indirection Extension (PIE) ๋ฅผ ๋จผ์ € ์งš์–ด์•ผ ํ•œ๋‹ค. ๋‘˜์€ spec์ƒ ๋…๋ฆฝ์ ์ธ feature์ง€๋งŒ, POE๋Š” PIE์˜ ํ•œ๊ณ„๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋œ ๋ณด์™„ ๊ธฐ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


๐Ÿ“ Background

Intel MPK๋Š” ์•Œ๊ณ  ์žˆ์—ˆ๋‚˜์š”?

x86 ์ง„์˜์—์„œ๋Š” ์ด๋ฏธ Intel Memory Protection Keys (MPK) ๋ผ๋Š” ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์ด ์žˆ์—ˆ๋‹ค.
MPK๋Š” userspace์—์„œ page table entry๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋„ PKRU ๋ ˆ์ง€์Šคํ„ฐ ํ•˜๋‚˜๋งŒ ๋ฐ”๊ฟ”์„œ ํŠน์ • ๋ฉ”๋ชจ๋ฆฌ ๋„๋ฉ”์ธ์˜ read/write๋ฅผ ๋น ๋ฅด๊ฒŒ on/offํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฒ•์ธ๋ฐ, syscall์ด๋‚˜ TLB flush ์—†์ด ์œ ์ € ๊ณต๊ฐ„์—์„œ ๊ถŒํ•œ์„ ๋ณ€๊ฒฝํ•œ๋‹ค๋Š” ์ ์ด ํ•ต์‹ฌ์ด์—ˆ๋‹ค.

ARM์—๋„ ARMv7 ์‹œ์ ˆ Memory Domains๋ผ๋Š” ๋น„์Šทํ•œ ๊ฐœ๋…์ด ์žˆ์—ˆ๋‹ค. ํ•˜์ง€๋งŒ DACR (Domain Access Control Register)๋Š” EL0์—์„œ ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ–ˆ๊ณ , AArch64์—์„œ๋Š” ์•„์˜ˆ deprecated ๋˜์—ˆ๋‹ค. ์ด๊ฑธ ์ œ๋Œ€๋กœ ๋‹ค์‹œ ๋งŒ๋“ค๊ฒ ๋‹ค๊ณ  ๋‚˜์˜จ ๊ฒŒ PIE์™€ POE๋‹ค.

๊ธฐ์กด direct permission ๋ฐฉ์‹์˜ ํ•œ๊ณ„

AArch64์˜ ๊ธฐ์กด permission ๋ชจ๋ธ์€ direct ๋ฐฉ์‹์ด๋‹ค. PTE์˜ ๋ช‡ ๊ฐ€์ง€ ๋น„ํŠธ๋“ค์ด ํ•ด๋‹น ํŽ˜์ด์ง€์˜ ๊ถŒํ•œ์„ ์ง์ ‘ ์ธ์ฝ”๋”ฉํ•œ๋‹ค.

PTE[54] = UXN  (User eXecute Never)
PTE[53] = PXN  (Privileged eXecute Never)
PTE[51] = DBM/WRITE
PTE[6]  = AP[1] (USER accessible)

์ด ๋ฐฉ์‹์€ ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ด์ง€๋งŒ, ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

์ฒซ์งธ, ํ‘œํ˜„ ๊ฐ€๋Šฅํ•œ permission ์กฐํ•ฉ์ด ์ œํ•œ์ ์ด๋‹ค. ์œ„ 4๊ฐœ ๋น„ํŠธ์˜ ์กฐํ•ฉ์œผ๋กœ๋Š” ๊ธฐ๋ณธ์ ์ธ r/w/x ์ •๋„๋งŒ ํ‘œํ˜„ ๊ฐ€๋Šฅํ•˜๊ณ , ์˜ˆ๋ฅผ ๋“ค์–ด "์ฝ๊ธฐ๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์“ฐ๊ธฐ๋Š” ํŠน์ˆ˜ instruction์œผ๋กœ๋งŒ" ๊ฐ™์€ ์„ธ๋ฐ€ํ•œ ๊ถŒํ•œ์€ ํ‘œํ˜„ํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค. (GCS๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๋ฐ”๋กœ ๊ทธ ๊ถŒํ•œ์ด๋‹ค)

๋‘˜์งธ, ๊ถŒํ•œ์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ๋น„์šฉ์ด ํฌ๋‹ค. mprotect() syscall์„ ํ†ตํ•ด PTE๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ํ•„์—ฐ์ ์œผ๋กœ kernel mode ์ „ํ™˜, TLB invalidation, ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ™˜๊ฒฝ์—์„œ๋Š” TLB shootdown IPI๊นŒ์ง€ ๋”ฐ๋ผ์˜จ๋‹ค. JIT compiler, sandbox, memory isolation์ด ๋นˆ๋ฒˆํ•œ ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ์—์„œ๋Š” ์ด ๋น„์šฉ์ด ๊ฝค ํฌ๋‹ค.


๐Ÿ“ Permission Indirection Extension (PIE)

PTE์˜ ๋น„ํŠธ๋ฅผ "๊ถŒํ•œ ๊ทธ ์ž์ฒด"๊ฐ€ ์•„๋‹Œ "๊ถŒํ•œ ํ…Œ์ด๋ธ”์˜ ์ธ๋ฑ์Šค"๋กœ ์“ฐ์ž!

PIE (FEAT_S1PIE)๋Š” permission ์ธ์ฝ”๋”ฉ ๋ฐฉ์‹์„ indirectํ•˜๊ฒŒ ๋ฐ”๊พผ๋‹ค. ๊ธฐ์กด์— permission ๋น„ํŠธ๋กœ ์‚ฌ์šฉํ•˜๋˜ PTE ํ•„๋“œ๋“ค์„ PIIndex (Permission Indirection Index) ๋กœ ์žฌํ™œ์šฉํ•˜๊ณ , ์‹ค์ œ ๊ถŒํ•œ์€ ๋ณ„๋„ ๋ ˆ์ง€์Šคํ„ฐ์— ์ •์˜๋œ ํ…Œ์ด๋ธ”์—์„œ lookupํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

PIIndex: PTE์—์„œ domain index ์ถ”์ถœ

PIE๊ฐ€ ํ™œ์„ฑํ™” (TCR2_EL1.PIE = 1) ๋˜๋ฉด PTE์˜ 4๊ฐœ ๋น„ํŠธ๊ฐ€ 4-bit PIIndex๋กœ ์žฌํ•ด์„๋œ๋‹ค.

PIIndex[3] โ† PTE[54] UXN  (User eXecute Never)
PIIndex[2] โ† PTE[53] PXN  (Privileged eXecute Never)
PIIndex[1] โ† PTE[51] WRITE/DBM
PIIndex[0] โ† PTE[6]  USER  (AP[1])

PIIndex๋Š” ์—ฐ์†๋œ ๋น„ํŠธ ํ•„๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ PTE ๋‚ด 4๊ฐœ์˜ ๋ถ„์‚ฐ๋œ ๋น„ํŠธ๋ฅผ ์กฐํ•ฉํ•ด์„œ ๋งŒ๋“œ๋Š” index๋‹ค. ๊ทธ๋ž˜์„œ Linux ์ปค๋„์—์„œ pte_pi_index()๋ผ๋Š” ๋ณ„๋„ ํ•จ์ˆ˜๋กœ ๊ฐ ๋น„ํŠธ๋ฅผ ์ˆ˜์ง‘ํ•ด์„œ ๊ณ„์‚ฐํ•œ๋‹ค.

4-bit์ด๋ฏ€๋กœ 0~15, ์ด 16๊ฐœ์˜ domain์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

PIRE0_EL1 / PIR_EL1: domain๋ณ„ ์‹ค์ œ ๊ถŒํ•œ ์ •์˜

PIIndex๋กœ lookupํ•  ์‹ค์ œ ๊ถŒํ•œ์€ ๋‘ ๊ฐœ์˜ ๋ ˆ์ง€์Šคํ„ฐ์— ์ •์˜๋œ๋‹ค.

๋ ˆ์ง€์Šคํ„ฐ๋Œ€์ƒ EL์—ญํ• 
PIRE0_EL1EL0 (userspace)๊ฐ™์€ PIIndex์— ๋Œ€ํ•ด EL0์— ๋ถ€์—ฌํ•  ๊ถŒํ•œ
PIR_EL1EL1 (kernel)๊ฐ™์€ PIIndex์— ๋Œ€ํ•ด EL1์— ๋ถ€์—ฌํ•  ๊ถŒํ•œ

๋‘ ๋ ˆ์ง€์Šคํ„ฐ๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” domain ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๋ ค๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋™์ผํ•œ PIIndex์— ๋Œ€ํ•ด EL0์™€ EL1์ด ์„œ๋กœ ๋‹ค๋ฅธ ๊ถŒํ•œ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋‹ค. ๊ฐ ๋ ˆ์ง€์Šคํ„ฐ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ 16๊ฐœ domain์˜ permission์„ ์ •์˜ํ•˜์ง€๋งŒ, ์ด domain ์ˆ˜๋Š” 16๊ฐœ๋‹ค.

๊ฐ ๋ ˆ์ง€์Šคํ„ฐ๋Š” 64-bit์ด๋ฉฐ, domain๋‹น 4-bit์”ฉ permission์„ ์ •์˜ํ•œ๋‹ค.

PIRE0_EL1 ๋˜๋Š” PIR_EL1:
[63:60] perm15 : r, w, x, gcs
[59:56] perm14 : r, w, x, gcs
...
[3:0]   perm0  : r, w, x, gcs

16๊ฐœ domain์ด ์‹ค์ œ๋กœ ์ง€์นญํ•˜๋Š” ๊ฒƒ๋“ค

PIIndex์˜ 16๊ฐœ domain์€ "์ƒˆ๋กœ์šด ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์—ญ 16๊ฐ€์ง€"๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ธฐ์กด PTE permission ๋น„ํŠธ 4๊ฐœ์˜ ๋ชจ๋“  ์กฐํ•ฉ (2โด = 16)์ด ๊ทธ๋Œ€๋กœ index๋กœ ์žฌํ™œ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ index๋Š” ๊ธฐ์กด์˜ page type๊ณผ 1:1 ๋Œ€์‘๋œ๋‹ค.

Linux ์ปค๋„ pgtable-prot.h์— ์ฃผ์„์œผ๋กœ ์ „์ฒด ๋งคํ•‘์ด ๋ช…์‹œ๋˜์–ด ์žˆ๋‹ค:

/* 0x0: PAGE_DEFAULT                                         */
/* 0x1: PTE_USER                          (๋ฏธ์‚ฌ์šฉ)           */
/* 0x2: PTE_WRITE                         (๋ฏธ์‚ฌ์šฉ)           */
/* 0x3: PTE_WRITE | PTE_USER              (๋ฏธ์‚ฌ์šฉ)           */
/* 0x4: PAGE_EXECONLY      PTE_PXN                          */
/* 0x5: PAGE_READONLY_EXEC PTE_PXN | PTE_USER               */
/* 0x6: PTE_PXN | PTE_WRITE               (๋ฏธ์‚ฌ์šฉ)           */
/* 0x7: PAGE_SHARED_EXEC   PTE_PXN | PTE_WRITE | PTE_USER   */
/* 0x8: PAGE_KERNEL_ROX    PTE_UXN                          */
/* 0x9: PAGE_GCS_RO        PTE_UXN | PTE_USER               */
/* 0xa: PAGE_KERNEL_EXEC   PTE_UXN | PTE_WRITE              */
/* 0xb: PAGE_GCS           PTE_UXN | PTE_WRITE | PTE_USER   */
/* 0xc: PAGE_KERNEL_RO     PTE_UXN | PTE_PXN               */
/* 0xd: PAGE_READONLY      PTE_UXN | PTE_PXN | PTE_USER     */
/* 0xe: PAGE_KERNEL        PTE_UXN | PTE_PXN | PTE_WRITE    */
/* 0xf: PAGE_SHARED        PTE_UXN | PTE_PXN | PTE_WRITE | PTE_USER */

์‹ค์ œ๋กœ Linux์—์„œ ๊ฐ domain์— ๋ถ€์—ฌํ•˜๋Š” permission์€ PIE_E0 (โ†’ PIRE0_EL1) ์™€ PIE_E1 (โ†’ PIR_EL1) ๋กœ ์ •์˜๋œ๋‹ค.

// EL0 permission table (PIRE0_EL1)
#define PIE_E0 (
    PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS),           PIE_GCS)    // 0xb: GCSSTR๋งŒ ํ—ˆ์šฉ
    PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS_RO),        PIE_R)      // 0x9: ์ฝ๊ธฐ๋งŒ
    PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY),      PIE_X_O)    // 0x4: ์‹คํ–‰๋งŒ (overlay on)
    PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_RX_O)   // 0x5: ์ฝ๊ธฐ+์‹คํ–‰ (overlay on)
    PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC),   PIE_RWX_O)  // 0x7: ์ฝ์“ฐ์‹ค (overlay on)
    PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY),      PIE_R_O)    // 0xd: ์ฝ๊ธฐ๋งŒ (overlay on)
    PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED),        PIE_RW_O))  // 0xf: ์ฝ์“ฐ (overlay on)

// EL1 permission table (PIR_EL1)
#define PIE_E1 (
    PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS),           PIE_NONE_O) // 0xb: ์ ‘๊ทผ ๋ถˆ๊ฐ€
    PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS_RO),        PIE_NONE_O) // 0x9: ์ ‘๊ทผ ๋ถˆ๊ฐ€
    PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY),      PIE_NONE_O) // 0x4: ์ ‘๊ทผ ๋ถˆ๊ฐ€
    PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_R)      // 0x5: ์ฝ๊ธฐ๋งŒ
    PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC),   PIE_RW)     // 0x7: ์ฝ์“ฐ
    PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY),      PIE_R)      // 0xd: ์ฝ๊ธฐ๋งŒ
    PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED),        PIE_RW)     // 0xf: ์ฝ์“ฐ
    PIRx_ELx_PERM(pte_pi_index(_PAGE_KERNEL_ROX),    PIE_RX)     // 0x8: ์ฝ๊ธฐ+์‹คํ–‰
    PIRx_ELx_PERM(pte_pi_index(_PAGE_KERNEL_EXEC),   PIE_RWX)    // 0xa: ์ฝ์“ฐ์‹ค
    PIRx_ELx_PERM(pte_pi_index(_PAGE_KERNEL_RO),     PIE_R)      // 0xc: ์ฝ๊ธฐ๋งŒ
    PIRx_ELx_PERM(pte_pi_index(_PAGE_KERNEL),        PIE_RW))    // 0xe: ์ฝ์“ฐ

์—ฌ๊ธฐ์„œ ์ฃผ๋ชฉํ•  ์ ์ด ๋‘ ๊ฐ€์ง€ ์žˆ๋‹ค.

GCS permission์ด PIE ์—†์ด๋Š” ๋ถˆ๊ฐ€๋Šฅํ•œ ์ด์œ : PAGE_GCS (0xb)๋Š” direct model์—์„œ PTE_UXN | PTE_WRITE | PTE_USER๋กœ, "UXN์ด๋ฉด์„œ USER ์ ‘๊ทผ ๊ฐ€๋Šฅ"์ด๋ผ๋Š” ๋ชจ์ˆœ์ ์ธ ์กฐํ•ฉ์ด์—ˆ๋‹ค. PIE ํ•˜์—์„œ๋Š” ์ด ๋น„ํŠธ ์กฐํ•ฉ์„ index๋กœ ์žฌํ•ด์„ํ•ด์„œ PIE_GCS๋ผ๋Š” ์ƒˆ permission์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. "์ผ๋ฐ˜ write๋Š” ๋ง‰๊ณ  GCSSTR instruction์œผ๋กœ๋งŒ ์“ธ ์ˆ˜ ์žˆ๋Š”" GCS ์ „์šฉ ๊ถŒํ•œ์ด ๋ฐ”๋กœ ์ด๊ฒƒ์ด๋‹ค. GCS๋Š” PIE ์—†์ด๋Š” ํ‘œํ˜„ ์ž์ฒด๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

_O suffix์˜ ์˜๋ฏธ: PIE_RW_O์ฒ˜๋Ÿผ _O๊ฐ€ ๋ถ™์€ encoding์€ "POE overlay ์ ์šฉ ๊ฐ€๋Šฅ" ๋ฒ„์ „์ด๋‹ค. EL0์šฉ PIRE0_EL1์—์„œ๋Š” ์ „๋ถ€ _O suffix ๋ฒ„์ „์„ ์‚ฌ์šฉํ•ด์•ผ POE์™€ ํ•จ๊ป˜ ๋™์ž‘ํ•œ๋‹ค. EL1์šฉ PIR_EL1์—๋Š” overlay๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ _O ์—†๋Š” ๋ฒ„์ „์„ ์“ด๋‹ค.

PIE์˜ ํ•œ๊ณ„

PIE๋กœ ๋” ํ’๋ถ€ํ•œ ๊ถŒํ•œ ํ‘œํ˜„์ด ๊ฐ€๋Šฅํ•ด์กŒ์ง€๋งŒ, ๊ถŒํ•œ ๋ณ€๊ฒฝ ๋น„์šฉ ๋ฌธ์ œ๋Š” ์—ฌ์ „ํžˆ ํ•ด๊ฒฐ๋˜์ง€ ์•Š๋Š”๋‹ค.
PIRE0_EL1์€ EL1(์ปค๋„)์—์„œ๋งŒ ์“ธ ์ˆ˜ ์žˆ๊ณ , ๋ณ€๊ฒฝ ํ›„ TLB flush๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ๊ถŒํ•œ์„ ๋ฐ”๊พธ๋ ค๋ฉด ์—ฌ์ „ํžˆ ์ปค๋„ ์ง„์ž…์ด ๋ถˆ๊ฐ€ํ”ผํ•˜๋‹ค.

์—ฌ๊ธฐ์„œ POE๊ฐ€ ๋“ฑ์žฅํ•œ๋‹ค.


๐Ÿ“ Permission Overlay Extension (POE)

PIE๋กœ base permission์„ ์ •ํ–ˆ์œผ๋ฉด, ๊ทธ ์œ„์— overlay๋ฅผ ์”Œ์›Œ์„œ EL0์—์„œ ์ง์ ‘ ์กฐ์ด์ž!

POE (FEAT_S1POE)๋Š” PIE๊ฐ€ ๊ฒฐ์ •ํ•œ base permission ์œ„์— ์ถ”๊ฐ€์ ์ธ ์ œํ•œ(overlay) ์„ EL0์—์„œ ์ง์ ‘, syscall ์—†์ด ๊ฑธ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.

POIndex: PIIndex์™€๋Š” ์™„์ „ํžˆ ๋ณ„๊ฐœ

POE๋Š” PIE์™€ ๋…๋ฆฝ์ ์ธ ๋ณ„๋„์˜ index ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•œ๋‹ค.

PIIndexPOIndex
PTE ๋น„ํŠธ ์œ„์น˜UXN[54], PXN[53], DBM[51], USER[6] โ€” ๋ถ„์‚ฐ๋œ 4๋น„ํŠธ[62:60] โ€” ์—ฐ์†๋œ 3๋น„ํŠธ
๋น„ํŠธ ์ˆ˜4-bit3-bit
domain ์ˆ˜16๊ฐœ8๊ฐœ
lookup ๋ ˆ์ง€์Šคํ„ฐPIRE0_EL1 / PIR_EL1POR_EL0 / POR_EL1
๋ˆ„๊ฐ€ ์ˆ˜์ •EL1 (์ปค๋„)EL0 (์œ ์ €, syscall ์—†์ด!)

PIIndex์™€ POIndex๋Š” ์„œ๋กœ ๋‹ค๋ฅธ PTE ๋น„ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํ•˜๋‚˜์˜ PTE์— ๋‘ index๊ฐ€ ๋™์‹œ์— ์กด์žฌํ•œ๋‹ค.

POE์˜ 8๊ฐœ domain

POIndex๋Š” 3-bit์ด๋ฏ€๋กœ 0~7, ์ด 8๊ฐœ์˜ domain์ด๋‹ค. ์ด domain๋“ค์€ PIE์˜ 16๊ฐœ domain๊ณผ ๋ณ„๊ฐœ์˜ ๊ณต๊ฐ„์ด๋ฉฐ, "์–ด๋–ค ์‹คํ–‰ ๋งฅ๋ฝ(context)์—์„œ ํ—ˆ์šฉํ•  ๊ถŒํ•œ" ์„ ์ •์˜ํ•œ๋‹ค.

POR_EL0:
[63:60] perm7 : r, w, x, po
[59:56] perm6 : r, w, x, po
[55:52] perm5 : r, w, x, po
[51:48] perm4 : r, w, x, po
[47:44] perm3 : r, w, x, po
[43:40] perm2 : r, w, x, po
[39:36] perm1 : r, w, x, po
[3:0]   perm0 : (๊ณ ์ •: full permission, ํ˜ธํ™˜์„ฑ ๋ณด์žฅ)

domain 0๋Š” full permission์œผ๋กœ ๊ณ ์ •๋˜์–ด ์žˆ์–ด์„œ ์‹ค์งˆ์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ overlay domain์€ 7๊ฐœ (index 1~7) ๋‹ค.

PIE + POE๊ฐ€ ํ•จ๊ป˜ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹

๋‘ extension์ด ๋ชจ๋‘ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ, ๊ถŒํ•œ ์ฒด์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

PTE[UXN,PXN,WRITE,USER] โ†’ PIRE0_EL1[PIIndex] โ†’ base_perm  (PIE๊ฐ€ ๊ฒฐ์ •)
                                                      โ†“ AND
PTE[62:60]              โ†’ POR_EL0[POIndex]   โ†’ overlay_perm (POE๊ฐ€ ์ถ”๊ฐ€ ์ œํ•œ)
                                                      โ†“
                                              effective_perm

overlay๋Š” ๊ถŒํ•œ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๊ณ  ์ œํ•œ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋˜ํ•œ POR_EL0๋Š” TLB์— ์บ์‹ฑ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๋ ˆ์ง€์Šคํ„ฐ write ํ•œ ๋ฒˆ์œผ๋กœ ์ฆ‰์‹œ effective permission์ด ๋ฐ”๋€๋‹ค.

PIE ์—†์ด POE๋งŒ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ์—๋Š” ๊ธฐ์กด direct PTE permission์ด base_perm์ด ๋œ๋‹ค.


๐Ÿ“ PIE + POE in your code

Kernel engineer

CONFIG_ARM64_POE=y   # ARMv8.9 architectural features ๋ฉ”๋‰ด

PIE ์ดˆ๊ธฐํ™”๋Š” arch/arm64/mm/proc.S์˜ __cpu_setup์—์„œ:

mrs_s x1, SYS_ID_AA64MMFR3_EL1
ubfx  x1, x1, #ID_AA64MMFR3_EL1_S1PIE_SHIFT, #4
cbz   x1, .Lskip_indirection

mov_q x0, PIE_E0        // PIRE0_EL1 ์„ธํŒ…
msr   REG_PIRE0_EL1, x0
mov_q x0, PIE_E1        // PIR_EL1 ์„ธํŒ…
msr   REG_PIR_EL1, x0
mov   x0, TCR2_ELx_PIE
msr   REG_TCR2_EL1, x0  // PIE ํ™œ์„ฑํ™”

POE context switch๋Š” arch/arm64/kernel/process.c์—์„œ POR_EL0๋ฅผ per-task๋กœ save/restore.
Linux 6.13-rc1๋ถ€ํ„ฐ PIE + POE ๋ชจ๋‘ mainline ๋ฐ˜์˜ ์™„๋ฃŒ.

Application engineer

POE๋Š” Linux Memory Protection Keys (pkeys) syscall ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋…ธ์ถœ๋œ๋‹ค.

// 1. protection key ํ• ๋‹น (์ปค๋„์ด POIndex๋ฅผ ํ• ๋‹น)
int pkey = pkey_alloc(0, 0);

// 2. ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— pkey ์—ฐ๊ฒฐ (PTE์˜ POIndex ๋น„ํŠธ๋ฅผ ์„ค์ •, ์ปค๋„ ์ง„์ž… ํ•„์š”)
pkey_mprotect(addr, len, PROT_READ | PROT_WRITE, pkey);

// 3. EL0์—์„œ POR_EL0 ์ง์ ‘ ์ˆ˜์ • โ€” syscall ์—†์Œ!
pkey_set(pkey, PKEY_DISABLE_WRITE);   // write overlay ์ œํ•œ
pkey_set(pkey, PKEY_DISABLE_ACCESS);  // read/write overlay ์ œํ•œ

// 4. ๋‹ค์‹œ ํ—ˆ์šฉ
pkey_set(pkey, 0);

step 1~2๋Š” ์ปค๋„ ์ง„์ž…์ด ํ•„์š”ํ•˜์ง€๋งŒ, ๊ถŒํ•œ์„ ์ž์ฃผ ๋ฐ”๊พธ๋Š” step 3~4๋Š” ์ˆœ์ˆ˜ ์œ ์ € ๊ณต๊ฐ„์—์„œ ๋ ˆ์ง€์Šคํ„ฐ write ํ•œ ๋ฒˆ์œผ๋กœ ๋๋‚œ๋‹ค๋Š” ๊ฒŒ ํ•ต์‹ฌ ์ด์ .


๐Ÿ“ Security analysis

์–ด๋””์— ์“ธ ์ˆ˜ ์žˆ๋‚˜

PIE + POE์˜ ํ•ต์‹ฌ ํƒ€๊ฒŸ์€ intra-process isolation์ด๋‹ค.

  • JIT runtime ๊ฒฉ๋ฆฌ: PIE๋กœ JIT-compiled code ์˜์—ญ์— ์ ์ ˆํ•œ base permission์„ ๋ถ€์—ฌํ•˜๊ณ , POE๋กœ ์‹คํ–‰ ๋งฅ๋ฝ์— ๋”ฐ๋ผ ์ ‘๊ทผ ๋ฒ”์œ„๋ฅผ ๋™์ ์œผ๋กœ ์ขํž˜
  • Sandbox: ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” third-party ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ syscall ์—†์ด ์‹คํ–‰ ์‹œ์ ์— ์ œํ•œ
  • GCS ์—ฐ๋™: PIE๊ฐ€ ์•„๋‹ˆ๋ฉด ํ‘œํ˜„ ์ž์ฒด๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•œ PIE_GCS permission์„ ํ†ตํ•ด return address stack ๋ณดํ˜ธ

ํ•œ๊ณ„์ 

Domain ์ˆ˜ ์ œํ•œ: POIndex๊ฐ€ 3-bit์ด๋ฏ€๋กœ ์‹ค์งˆ์ ์œผ๋กœ 7๊ฐœ overlay domain๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. PIE์˜ 16๊ฐœ domain๊ณผ๋Š” ๋ณ„๊ฐœ์˜ ๊ณต๊ฐ„์ด๊ณ , ๋‘˜์„ ์กฐํ•ฉํ•ด์„œ ๋Š˜๋ฆด ์ˆ˜๋Š” ์žˆ์ง€๋งŒ (NanoZone ๋…ผ๋ฌธ ์ฐธ๊ณ ) ๊ทธ๊ฑด ์•„ํ‚คํ…์ฒ˜ ์ŠคํŽ™ ๋ฐ–์˜ ์—ฐ๊ตฌ ๋ ˆ๋ฒจ ๊ธฐ๋ฒ•์ด๋‹ค.

intra-process ๋ฒ”์œ„: POE๋Š” ํ”„๋กœ์„ธ์Šค ๋‚ด ๊ฒฉ๋ฆฌ๋‹ค. ์ปค๋„์ด ํƒ€ํ˜‘๋˜๋ฉด PIRE0_EL1 ์ด๋‚˜ PTE์˜ POIndex๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

POR_EL0 ๋ฌด๊ฒฐ์„ฑ: POR_EL0๋Š” EL0์—์„œ ์ง์ ‘ ์ˆ˜์ • ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ๊ณต๊ฒฉ์ž๊ฐ€ ์ž„์˜ ์ฝ”๋“œ ์‹คํ–‰ ๊ถŒํ•œ์„ ์ด๋ฏธ ํš๋“ํ–ˆ๋‹ค๋ฉด overlay ์„ค์ •์„ ๋ฐ”๊ฟ”๋ฒ„๋ฆด ์ˆ˜ ์žˆ๋‹ค. POE๋Š” ๋ฒ„๊ทธ๋กœ ์ธํ•œ ์˜๋„์น˜ ์•Š์€ ์ ‘๊ทผ์„ ๋ง‰๋Š” ๋ฐ๋Š” ํšจ๊ณผ์ ์ด์ง€๋งŒ, ์•…์˜์ ์ธ ์ฝ”๋“œ์˜ ์˜๋„์ ์ธ ์šฐํšŒ์— ๋Œ€ํ•ด์„œ๋Š” ๋ณ„๋„ ๋ณดํ˜ธ ๋ ˆ์ด์–ด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.


๐Ÿ“ Discussion

์ฒ˜์Œ์— PIE ์ŠคํŽ™๋งŒ ๋ดค์„ ๋•Œ๋Š” "PTE ๋น„ํŠธ๋ฅผ index๋กœ ์žฌํ™œ์šฉํ•˜๋Š” cleverํ•œ trick์ด๊ตฌ๋‚˜" ์ •๋„์˜€๋Š”๋ฐ, domain ๋งคํ•‘ ํ…Œ์ด๋ธ”์„ ์ง์ ‘ ๋œฏ์–ด๋ณด๋‹ˆ ์„ค๊ณ„ ์˜๋„๊ฐ€ ๊ฝค ๋ช…ํ™•ํ–ˆ๋‹ค. ๊ธฐ์กด 16๊ฐ€์ง€ PTE ๋น„ํŠธ ์กฐํ•ฉ์„ ๊ทธ๋Œ€๋กœ index๋กœ ์žฌํ™œ์šฉํ•ด์„œ ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ GCS ๊ฐ™์€ ์‹ ๊ทœ permission type์„ ๋ผ์›Œ ๋„ฃ๋Š” ๋ฐฉ์‹์ด ์ธ์ƒ์ ์ด๋‹ค. ํŠนํžˆ PAGE_GCS๊ฐ€ direct model์—์„œ๋Š” ๋ชจ์ˆœ์ ์ธ ๋น„ํŠธ ์กฐํ•ฉ์ด์—ˆ๋˜ ๊ฑธ PIE๋กœ ์œ ์šฉํ•˜๊ฒŒ ์žฌํƒ„์ƒ์‹œํ‚จ ๋ถ€๋ถ„์ด ์žฌ๋ฏธ์žˆ๋‹ค.

PIE์™€ POE์˜ ์—ญํ•  ๋ถ„๋‹ด๋„ ๊น”๋”ํ•˜๋‹ค. PIE๋Š” ์ปค๋„์ด "์ด ํŽ˜์ด์ง€์—๋Š” ์–ด๋–ค permission์„ ์ค„ ์ˆ˜ ์žˆ๋Š”์ง€"๋ฅผ ํ…Œ์ด๋ธ”๋กœ ์ •์˜ํ•˜๊ณ , POE๋Š” ์œ ์ €๊ฐ€ "์ง€๊ธˆ ์ด ์‹คํ–‰ ๋งฅ๋ฝ์—์„œ ๊ทธ ์ค‘ ์–ผ๋งˆ๋‚˜ ํ—ˆ์šฉํ•  ๊ฑด์ง€"๋ฅผ ๋ ˆ์ง€์Šคํ„ฐ๋กœ ์‹ค์‹œ๊ฐ„ ์กฐ์ ˆํ•˜๋Š” ๊ตฌ์กฐ. ๋‘˜์ด ์ง์„ ์ด๋ค„์•ผ ๋น„๋กœ์†Œ "ํ‘œํ˜„๋ ฅ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋น„์šฉ ์—†์ด ๋ฐ”๊พธ๋Š”" ๊ฒŒ ์™„์„ฑ๋œ๋‹ค.

๋‹ค์Œ์— ๋‚˜์˜ฌ POE2 (FEAT_S1POE2)๋Š” domain ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๊ณ  caller context ๊ธฐ๋ฐ˜ overlay๊นŒ์ง€ ์ง€์›ํ•œ๋‹ค๊ณ  ํ•˜๋‹ˆ, ๊ธฐ๋Œ€ํ•ด๋ณผ ๋งŒ ํ•˜๋‹ค.

๊ด€๋ จํ•ด์„œ PIE + POE๋ฅผ ARM CCA ํ™˜๊ฒฝ์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ฒฉ๋ฆฌ์— ํ™œ์šฉํ•œ NanoZone ๋…ผ๋ฌธ๋„ ์ตœ๊ทผ ๋‚˜์™”์œผ๋‹ˆ ๊ด€์‹ฌ ์žˆ๋‹ค๋ฉด ์ฝ์–ด๋ณผ ๋งŒ ํ•˜๋‹ค.

profile
Security researcher, Ravenclaw wannabe

0๊ฐœ์˜ ๋Œ“๊ธ€