25. Memory Sealing (mseal)

๊ฐœ์š” (Overview)

mseal()์€ Linux ์ปค๋„์˜ ์‹œ์Šคํ…œ ํ˜ธ์ถœ๋กœ, ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ(VMA)์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋„๋ก "๋ด‰์ธ(sealing)"ํ•˜๋Š” ๋ณด์•ˆ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋ด‰์ธ์€ RWX(Read/Write/Execute) ๋น„ํŠธ ์™ธ์— ๋งคํ•‘ ์ž์ฒด๋ฅผ ๋ณดํ˜ธํ•˜์—ฌ, ์†์ƒ๋œ ํฌ์ธํ„ฐ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์„ ์•…์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” XNU ์ปค๋„์˜ VM_FLAGS_PERMANENT์ด๋‚˜ OpenBSD์˜ mimmutable๊ณผ ์œ ์‚ฌํ•œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

Linux 7.0์—์„œ mseal()์€ 64๋น„ํŠธ ์•„ํ‚คํ…์ฒ˜์—์„œ๋งŒ ์ง€์›๋˜๋ฉฐ(32๋น„ํŠธ๋Š” VM_SEALED๊ฐ€ VM_NONE์œผ๋กœ ์ •์˜), CONFIG_64BIT์ด ํ™œ์„ฑํ™”๋œ ์‹œ์Šคํ…œ์—์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋ด‰์ธ๋œ ๋งคํ•‘์€ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜๊ฑฐ๋‚˜ exec ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ด ๋ฐœ์ƒํ•  ๋•Œ๊นŒ์ง€ ํ•ด์ œ๋  ์ˆ˜ ์—†์œผ๋ฉฐ, ํ•œ๋ฒˆ ๋ด‰์ธ๋œ ๋ฉ”๋ชจ๋ฆฌ๋Š” munseal ๊ธฐ๋Šฅ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์†Œ์Šค ํŒŒ์ผ ๊ฒฝ๋กœ

mm/mseal.c                           # ํ•ต์‹ฌ ๊ตฌํ˜„ (191์ค„)
mm/vma.h                             # vma_is_sealed() ํ—ฌํผ
mm/vma.c                             # munmap ๊ฒฝ๋กœ์—์„œ ๋ด‰์ธ ๊ฒ€์‚ฌ
mm/mremap.c                          # mremap ์ฐจ๋‹จ ๊ฒ€์‚ฌ
mm/mprotect.c                        # mprotect ์ฐจ๋‹จ ๊ฒ€์‚ฌ
mm/madvise.c                         # madvise ์ฐจ๋‹จ ๊ฒ€์‚ฌ
fs/binfmt_elf.c                      # ELF ๋กœ๋”์—์„œ page 0 ์ž๋™ ๋ด‰์ธ
include/linux/mm.h                   # VM_SEALED ํ”Œ๋ž˜๊ทธ ์ •์˜
init/Kconfig                         # CONFIG_MSEAL_SYSTEM_MAPPINGS
Documentation/userspace-api/mseal.rst  # ๊ณต์‹ ๋ฌธ์„œ

๋น ๋ฅธ ์ ๊ฒ€ ๋ช…๋ น

# 1. mseal ์‹œ์Šคํ…œ ํ˜ธ์ถœ ์ง€์› ์—ฌ๋ถ€ ํ™•์ธ
grep -r "CONFIG_64BIT" /boot/config-$(uname -r)

# 2. do_mseal ์‹ฌ๋ณผ ํ™•์ธ
grep -w "do_mseal" /proc/kallsyms 2>/dev/null || echo "do_mseal ์‹ฌ๋ณผ ๋ฏธ๋…ธ์ถœ"

# 3. ๋ด‰์ธ ๊ด€๋ จ ์ปค๋„ ๋ชจ๋“ˆ/์„ค์ • ํ™•์ธ
zgrep "MSEAL" /proc/config.gz 2>/dev/null || grep "MSEAL" /boot/config-$(uname -r) 2>/dev/null

# 4. ์‹œ์Šคํ…œ ๋งคํ•‘ ๋ด‰์ธ ํ™œ์„ฑํ™” ํ™•์ธ
cat /proc/sys/vm/mmap_min_addr  # ์ตœ์†Œ ์ฃผ์†Œ ํ™•์ธ
grep -n "vdso\|vvar" /proc/self/maps  # ์‹œ์Šคํ…œ ๋งคํ•‘ ํ™•์ธ

# 5. mseal ๊ด€๋ จ ์ปค๋„ ๋กœ๊ทธ ํ™•์ธ
dmesg | grep -i "seal\|mseal" 2>/dev/null

# 6. seccomp์—์„œ mseal ํ˜ธ์ถœ ํ—ˆ์šฉ ์—ฌ๋ถ€ ํ™•์ธ
grep -i seccomp /proc/self/status

# 7. VMA ๊ฐœ์ˆ˜ ์ œํ•œ ํ™•์ธ (๋ด‰์ธ ์‹œ VMA ๋ถ„ํ•  ๊ฐ€๋Šฅ์„ฑ)
cat /proc/sys/vm/max_map_count

# 8. ํŠน์ • ํ”„๋กœ์„ธ์Šค์˜ ๋ด‰์ธ๋œ ๋งคํ•‘ ํ™•์ธ (VmFlags์— 'sl' ํ‘œ์‹œ)
grep -A 5 "VmFlags:.*sl" /proc/<pid>/smaps

ํ•ต์‹ฌ ์ž๋ฃŒ๊ตฌ์กฐ

mm_struct / vm_area_struct

mseal()์€ ํ˜„์žฌ ์ž‘์—…์˜ ์ฃผ์†Œ ๊ณต๊ฐ„(struct mm_struct)๊ณผ ๊ทธ ์•ˆ์˜ VMA(struct vm_area_struct)๋ฅผ ํ•จ๊ป˜ ๋‹ค๋ฃน๋‹ˆ๋‹ค. mm_struct๋Š” ์ž ๊ธˆ๊ณผ ๋ฒ”์œ„ ๊ฒ€์ƒ‰์˜ ๊ธฐ์ค€์ด ๋˜๊ณ , vm_area_struct๋Š” vm_start, vm_end, vm_flags๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ด‰์ธ ์—ฌ๋ถ€๋ฅผ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

/* mm/mseal.c:55-65 */
static int mseal_apply(struct mm_struct *mm,
		unsigned long start, unsigned long end)
{
	struct vm_area_struct *vma, *prev;
	VMA_ITERATOR(vmi, mm, start);

	vma = vma_iter_load(&vmi);
	prev = vma_prev(&vmi);
	if (start > vma->vm_start)
		prev = vma;
  • struct mm_struct: ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค์˜ ์ฃผ์†Œ ๊ณต๊ฐ„ ์ „์ฒด๋ฅผ ๋Œ€ํ‘œํ•ฉ๋‹ˆ๋‹ค. mmap_write_lock_killable(mm)์™€ range_contains_unmapped(mm, ...)์˜ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค.
  • struct vm_area_struct: ๋ด‰์ธ ๋Œ€์ƒ ๊ตฌ๊ฐ„์ž…๋‹ˆ๋‹ค. vma_modify_flags()๊ฐ€ ์ด ๊ตฌ์กฐ์ฒด์˜ vm_flags๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
  • VM_SEALED ํ”Œ๋ž˜๊ทธ

    VM_SEALED๋Š” vm_area_struct.vm_flags์— ์„ค์ •๋˜๋Š” ๋น„ํŠธ ํ”Œ๋ž˜๊ทธ๋กœ, ํ•ด๋‹น VMA๊ฐ€ ๋ด‰์ธ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    /* include/linux/mm.h:500-506 */
    #ifdef CONFIG_64BIT
    #define VM_SEALED		INIT_VM_FLAG(SEALED)   /* 64๋น„ํŠธ์—์„œ๋งŒ ์œ ํšจ */
    #else
    #define VM_SEALED		VM_NONE                /* 32๋น„ํŠธ์—์„œ๋Š” ๋น„ํ™œ์„ฑ */
    #endif
    /* include/linux/mm.h:536-540 - ์‹œ์Šคํ…œ ๋งคํ•‘ ๋ด‰์ธ */
    #ifdef CONFIG_MSEAL_SYSTEM_MAPPINGS
    #define VM_SEALED_SYSMAP	VM_SEALED  /* ์‹œ์Šคํ…œ ๋งคํ•‘ ์ž๋™ ๋ด‰์ธ */
    #else
    #define VM_SEALED_SYSMAP	VM_NONE   /* ์‹œ์Šคํ…œ ๋งคํ•‘ ๋ด‰์ธ ๋น„ํ™œ์„ฑ */
    #endif
  • /proc//smaps์˜ VmFlags์—๋Š” sl๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  • vma_is_sealed() ํ—ฌํผ ํ•จ์ˆ˜

    VMA๊ฐ€ ๋ด‰์ธ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ธ๋ผ์ธ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

    /* mm/vma.h:661-671 */
    #ifdef CONFIG_64BIT
    static inline bool vma_is_sealed(struct vm_area_struct *vma)
    {
    	return (vma->vm_flags & VM_SEALED);  /* VM_SEALED ๋น„ํŠธ ๊ฒ€์‚ฌ */
    }
    #else
    static inline bool vma_is_sealed(struct vm_area_struct *vma)
    {
    	return false;  /* 32๋น„ํŠธ์—์„œ๋Š” ํ•ญ์ƒ false */
    }
    #endif

    range_contains_unmapped() - VMA ํ™€ ๊ฒ€์‚ฌ

    mseal() ํ˜ธ์ถœ ์‹œ ์‹œ์ž‘/๋ ์ฃผ์†Œ ์‚ฌ์ด์— ๋งคํ•‘๋˜์ง€ ์•Š์€ ์˜์—ญ(VMA hole)์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    /* mm/mseal.c:38-53 */
    static bool range_contains_unmapped(struct mm_struct *mm,
    		unsigned long start, unsigned long end)
    {
    	struct vm_area_struct *vma;
    	unsigned long prev_end = start;
    	VMA_ITERATOR(vmi, current->mm, start);
    
    	for_each_vma_range(vmi, vma, end) {
    		if (vma->vm_start > prev_end)
    			return true;  /* ์ด์ „ ๋๊ณผ ํ˜„์žฌ ์‹œ์ž‘ ์‚ฌ์ด์— ํ™€ ์กด์žฌ */
    		prev_end = vma->vm_end;
    	}
    
    	return prev_end < end;  /* ๋งˆ์ง€๋ง‰ VMA๊ฐ€ end๋ณด๋‹ค ๋จผ์ € ๋๋‚˜๋Š” ๊ฒฝ์šฐ */
    }

    mseal_apply() - ๋ด‰์ธ ์ ์šฉ

    ์‹ค์ œ๋กœ VMA์— VM_SEALED ํ”Œ๋ž˜๊ทธ๋ฅผ ์„ค์ •ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. VMA ๋ถ„ํ• /๋ณ‘ํ•ฉ์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    /* mm/mseal.c:55-85 */
    static int mseal_apply(struct mm_struct *mm,
    		unsigned long start, unsigned long end)
    {
    	struct vm_area_struct *vma, *prev;
    	VMA_ITERATOR(vmi, mm, start);
    
    	vma = vma_iter_load(&vmi);
    	prev = vma_prev(&vmi);
    	if (start > vma->vm_start)
    		prev = vma;
    
    	for_each_vma_range(vmi, vma, end) {
    		const unsigned long curr_start = MAX(vma->vm_start, start);
    		const unsigned long curr_end = MIN(vma->vm_end, end);
    
    		if (!(vma->vm_flags & VM_SEALED)) {
    			vm_flags_t vm_flags = vma->vm_flags | VM_SEALED;
    			/* VMA ์ˆ˜์ • (๋ถ„ํ• /๋ณ‘ํ•ฉ ํ•„์š” ์‹œ) */
    			vma = vma_modify_flags(&vmi, prev, vma, curr_start,
    					       curr_end, &vm_flags);
    			if (IS_ERR(vma))
    				return PTR_ERR(vma);
    			vm_flags_set(vma, VM_SEALED);
    		}
    		prev = vma;
    	}
    	return 0;
    }

    ํ•ต์‹ฌ ํ•จ์ˆ˜

    1. do_mseal() - ๋ฉ”์ธ ์ง„์ž…์ 

    /* mm/mseal.c:139-185 */
    int do_mseal(unsigned long start, size_t len_in, unsigned long flags)
  • ์—ญํ• : mseal() ์‹œ์Šคํ…œ ํ˜ธ์ถœ์˜ ๋ฉ”์ธ ๋กœ์ง. ์ž…๋ ฅ ๊ฒ€์ฆ ํ›„ ๋ด‰์ธ ์ ์šฉ
  • ๋ถ„๊ธฐ ๋กœ์ง:
  • - flags != 0 โ†’ -EINVAL (์˜ˆ์•ฝ๋œ ํ”Œ๋ž˜๊ทธ)

    - start๊ฐ€ ํŽ˜์ด์ง€ ์ •๋ ฌ๋˜์ง€ ์•Š์Œ โ†’ -EINVAL

    - len_in์ด 0์œผ๋กœ ๋ผ์šด๋”ฉ๋จ โ†’ -EINVAL

    - end < start (์˜ค๋ฒ„ํ”Œ๋กœ์šฐ) โ†’ -EINVAL

    - end == start โ†’ ์„ฑ๊ณต (์•„๋ฌด ์ž‘์—… ์—†์Œ)

    - range_contains_unmapped()๊ฐ€ true โ†’ -ENOMEM

    - mseal_apply() ์‹คํŒจ โ†’ ํ•ด๋‹น ์—๋Ÿฌ ์ฝ”๋“œ ๋ฐ˜ํ™˜

    2. SYSCALL_DEFINE3(mseal) - ์‹œ์Šคํ…œ ํ˜ธ์ถœ ์ •์˜

    /* mm/mseal.c:187-191 */
    SYSCALL_DEFINE3(mseal, unsigned long, start, size_t, len, unsigned long, flags)
    {
    	return do_mseal(start, len, flags);
    }
  • ์—ญํ• : ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ์‹œ์Šคํ…œ ํ˜ธ์ถœ ์ธํ„ฐํŽ˜์ด์Šค
  • ์‹œ๊ทธ๋‹ˆ์ฒ˜: int mseal(void *addr, size_t len, unsigned long flags)
  • 3. can_madvise_modify() - madvise ํ—ˆ์šฉ ๊ฒ€์‚ฌ

    /* mm/madvise.c:1297-1331 */
    static bool can_madvise_modify(struct madvise_behavior *madv_behavior)
    {
    	struct vm_area_struct *vma = madv_behavior->vma;
    
    	/* ๋ด‰์ธ๋˜์ง€ ์•Š์€ VMA๋ฉด ํ—ˆ์šฉ */
    	if (!vma_is_sealed(vma))
    		return true;
    
    	/* ๋ด‰์ธ๋œ VMA๋ผ๋„ discard๊ฐ€ ์•„๋‹ˆ๋ฉด ํ—ˆ์šฉ */
    	if (!is_discard(madv_behavior->behavior))
    		return true;
    
    	/* ์ต๋ช… read-only SEALED ๋งคํ•‘์˜ ์ผ๋ถ€ discard๋Š” ํ—ˆ์šฉ */
    	if (!vma_is_anonymous(vma))
    		return true;
    
    	/* ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ ๋งคํ•‘์ด๋ฉด ํ—ˆ์šฉ */
    	if ((vma->vm_flags & VM_WRITE) &&
    	    arch_vma_access_permitted(vma, /* ์“ฐ๊ธฐ= */ true,
    				      /* ์‹คํ–‰= */ false, /* ์™ธ๋ถ€= */ false))
    		return true;
    
    	/* ๊ทธ ์™ธ์—๋Š” ํ—ˆ์šฉํ•˜์ง€ ์•Š์Œ */
    	return false;
    }
  • ์—ญํ• : ๋ด‰์ธ๋œ VMA์—์„œ madvise() ํ˜ธ์ถœ์ด ํ—ˆ์šฉ๋˜๋Š”์ง€ ํŒ๋‹จ
  • ๋ถ„๊ธฐ ๋กœ์ง:
  • - VMA๊ฐ€ ๋ด‰์ธ๋˜์ง€ ์•Š์Œ โ†’ ํ—ˆ์šฉ

    - discard ์—ฐ์‚ฐ์ด ์•„๋‹˜ โ†’ ํ—ˆ์šฉ

    - ํŒŒ์ผ ๊ธฐ๋ฐ˜ ๋งคํ•‘ (shared/private) โ†’ ํ—ˆ์šฉ

    - ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ๋งคํ•‘ โ†’ ํ—ˆ์šฉ

    - ๊ทธ ์™ธ (์ต๋ช… ์ฝ๊ธฐ ์ „์šฉ ๋ด‰์ธ ๋งคํ•‘) โ†’ ์ฐจ๋‹จ

    4. is_discard() - discard ๊ณ„์—ด ํŒ๋ณ„

    /* mm/madvise.c:1273-1284 */
    static bool is_discard(int behavior)
    {
    	switch (behavior) {
    	case MADV_FREE:
    	case MADV_DONTNEED:
    	case MADV_DONTNEED_LOCKED:
    	case MADV_REMOVE:
    	case MADV_DONTFORK:
    	case MADV_WIPEONFORK:
    	case MADV_GUARD_INSTALL:
    		return true;
    	}
    
    	return false;
    }
  • madvise()๊ฐ€ ๋ฐ์ดํ„ฐ ํ๊ธฐ ๊ณ„์—ด์ธ์ง€ ๋จผ์ € ๊ฐ€๋ ค๋‚ธ ๋’ค, ๋ด‰์ธ๋œ ์ต๋ช… ์ฝ๊ธฐ ์ „์šฉ VMA์—์„œ๋งŒ ์ œํ•œ์„ ๊ฑธ์–ด๋‘ก๋‹ˆ๋‹ค.
  • 5. vma_is_sealed() - ๋ด‰์ธ ์ƒํƒœ ํ™•์ธ

    /* mm/vma.h:662-664 */
    static inline bool vma_is_sealed(struct vm_area_struct *vma)
    {
    	return (vma->vm_flags & VM_SEALED);
    }
  • ์—ญํ• : VMA์˜ vm_flags์—์„œ VM_SEALED ๋น„ํŠธ ๊ฒ€์‚ฌ
  • ์‚ฌ์šฉ์ฒ˜: mremap, mprotect, munmap, madvise ๋“ฑ์—์„œ ํ˜ธ์ถœ
  • 6. range_contains_unmapped() - VMA ํ™€ ๊ฒ€์ฆ

    /* mm/mseal.c:38-53 */
    static bool range_contains_unmapped(struct mm_struct *mm,
    		unsigned long start, unsigned long end)
  • ์—ญํ• : ๋ด‰์ธ ๋ฒ”์œ„ ๋‚ด์— ๋งคํ•‘๋˜์ง€ ์•Š์€ ์˜์—ญ์ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • ๋ฐ˜ํ™˜๊ฐ’: ํ™€์ด ์žˆ์œผ๋ฉด true, ์—†์œผ๋ฉด false

  • ํ˜ธ์ถœ ํ๋ฆ„

    ์‚ฌ์šฉ์ž ๊ณต๊ฐ„
    โ”‚
    โ–ผ
    mseal(addr, len, flags)          โ† ์‹œ์Šคํ…œ ํ˜ธ์ถœ
    โ”‚
    โ–ผ
    SYSCALL_DEFINE3(mseal)           โ† mm/mseal.c:187
    โ”‚
    โ–ผ
    do_mseal(start, len, flags)      โ† mm/mseal.c:139
    โ”‚
    โ”œโ”€โ–บ flags ๊ฒ€์ฆ                 โ† flags != 0 โ†’ -EINVAL
    โ”œโ”€โ–บ untagged_addr(start)       โ† ํƒœ๊ทธ ์ œ๊ฑฐ (MTE ๋“ฑ)
    โ”œโ”€โ–บ PAGE_ALIGNED(start) ๊ฒ€์ฆ   โ† ํŽ˜์ด์ง€ ์ •๋ ฌ ํ™•์ธ
    โ”œโ”€โ–บ len = PAGE_ALIGN(len_in)   โ† ๊ธธ์ด ์ •๋ ฌ
    โ”œโ”€โ–บ end = start + len          โ† ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ๊ฒ€์‚ฌ
    โ”‚
    โ”œโ”€โ–บ mmap_write_lock_killable(mm)  โ† ์“ฐ๊ธฐ ์ž ๊ธˆ ํš๋“
    โ”‚
    โ”œโ”€โ–บ range_contains_unmapped(mm, start, end)  โ† VMA ํ™€ ๊ฒ€์‚ฌ
    โ”‚     โ”‚
    โ”‚     โ””โ”€โ–บ for_each_vma_range() โ†’ ํ™€ ๋ฐœ๊ฒฌ ์‹œ -ENOMEM
    โ”‚
    โ”œโ”€โ–บ mseal_apply(mm, start, end)  โ† VM_SEALED ํ”Œ๋ž˜๊ทธ ์„ค์ •
    โ”‚     โ”‚
    โ”‚     โ””โ”€โ–บ for_each_vma_range()
    โ”‚           โ”œโ”€โ–บ vma_modify_flags()  โ† VMA ๋ถ„ํ• /๋ณ‘ํ•ฉ
    โ”‚           โ””โ”€โ–บ vm_flags_set(vma, VM_SEALED)
    โ”‚
    โ””โ”€โ–บ mmap_write_unlock(mm)      โ† ์“ฐ๊ธฐ ์ž ๊ธˆ ํ•ด์ œ

    ๋ด‰์ธ ํ›„ ์ฐจ๋‹จ๋˜๋Š” ์‹œ์Šคํ…œ ํ˜ธ์ถœ ํ๋ฆ„

    ๋ด‰์ธ๋œ VMA์—์„œ ํ˜ธ์ถœ ์‹œ
    โ”‚
    โ”œโ”€โ–บ munmap()     โ†’ mm/vma.c:1403,1423  โ†’ -EPERM
    โ”œโ”€โ–บ mremap()     โ†’ mm/mremap.c:1666    โ†’ -EPERM
    โ”œโ”€โ–บ mprotect()   โ†’ mm/mprotect.c:706   โ†’ -EPERM
    โ””โ”€โ–บ madvise()    โ†’ mm/madvise.c:1302   โ†’ ํ—ˆ์šฉ/์ฐจ๋‹จ ๋ถ„๊ธฐ

    ์กฐ๊ฑด๋ณ„ ๋น„๊ต

    ๋ด‰์ธ ํ›„ ์‹œ์Šคํ…œ ํ˜ธ์ถœ ํ—ˆ์šฉ ์—ฌ๋ถ€

    ์‹œ์Šคํ…œ ํ˜ธ์ถœํ—ˆ์šฉ ์—ฌ๋ถ€๊ฒ€์‚ฌ ์œ„์น˜๋น„๊ณ 
    `munmap()`์ฐจ๋‹จ (-EPERM)mm/vma.c:1403๋ด‰์ธ๋œ VMA ๋ถ„ํ•  ์‹œ๋„ ์‹œ
    `mremap()`์ฐจ๋‹จ (-EPERM)mm/mremap.c:1666์ด๋™/ํ™•์žฅ/์ถ•์†Œ ๋ชจ๋‘ ์ฐจ๋‹จ
    `mprotect()`์ฐจ๋‹จ (-EPERM)mm/mprotect.c:706RWX ๋ณดํ˜ธ ๋น„ํŠธ ๋ณ€๊ฒฝ ์ฐจ๋‹จ
    `pkey_mprotect()`์ฐจ๋‹จ (-EPERM)mm/mprotect.c:706pkey ํฌํ•จ mprotect
    `madvise(discard ๊ณ„์—ด)`์กฐ๊ฑด๋ถ€ ์ฐจ๋‹จmm/madvise.c:1274,1302`MADV_FREE`, `MADV_DONTNEED`, `MADV_DONTNEED_LOCKED`, `MADV_REMOVE`, `MADV_DONTFORK`, `MADV_WIPEONFORK`, `MADV_GUARD_INSTALL`
    `madvise(๋น„-discard)`ํ—ˆ์šฉmm/madvise.c:1306`is_discard()`๊ฐ€ false์ด๋ฉด ํ—ˆ์šฉ
    `mmap(MAP_FIXED)`์ฐจ๋‹จ (๊ฐ„์ ‘)mm/vma.c:1403๊ธฐ์กด ๋งคํ•‘ ๊ต์ฒด ๋ถˆ๊ฐ€

    mseal() ํ˜ธ์ถœ ์กฐ๊ฑด๋ณ„ ๊ฒฐ๊ณผ

    ์กฐ๊ฑด๊ฒฐ๊ณผ๋น„๊ณ 
    `flags != 0`-EINVAL์˜ˆ์•ฝ๋œ ํ”Œ๋ž˜๊ทธ
    ์‹œ์ž‘ ์ฃผ์†Œ ๋ฏธ์ •๋ ฌ-EINVALํŽ˜์ด์ง€ ์ •๋ ฌ ํ•„์š”
    ๋ฒ”์œ„ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ-EINVALstart + len > ULONG_MAX
    ๋นˆ ๋ฒ”์œ„ (len=0)์„ฑ๊ณต (0)์•„๋ฌด ์ž‘์—… ์—†์Œ
    VMA ํ™€ ์กด์žฌ-ENOMEM์‹œ์ž‘/๋ ์‚ฌ์ด ๋งคํ•‘ ์—†์Œ
    32๋น„ํŠธ ์•„ํ‚คํ…์ฒ˜-EPERMmseal ๋ฏธ์ง€์›
    ์ด๋ฏธ ๋ด‰์ธ๋œ VMA์„ฑ๊ณต (0)๋ฉฑ๋“ฑ์„ฑ (idempotent)
    ์ •์ƒ์ ์ธ ๋ด‰์ธ์„ฑ๊ณต (0)VM_SEALED ํ”Œ๋ž˜๊ทธ ์„ค์ •

    ์‹œ์Šคํ…œ ๋งคํ•‘ ๋ด‰์ธ (CONFIG_MSEAL_SYSTEM_MAPPINGS)

    ์„ค์ •๋™์ž‘์ง€์› ์•„ํ‚คํ…์ฒ˜
    `CONFIG_MSEAL_SYSTEM_MAPPINGS=y`vdso, vvar ๋“ฑ ์‹œ์Šคํ…œ ๋งคํ•‘ ์ž๋™ ๋ด‰์ธx86-64, arm64, loongarch, s390
    `CONFIG_MSEAL_SYSTEM_MAPPINGS=n`์‹œ์Šคํ…œ ๋งคํ•‘ ๋ด‰์ธ ๋น„ํ™œ์„ฑ๋ชจ๋“  ์•„ํ‚คํ…์ฒ˜
    `CONFIG_ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS`์•„ํ‚คํ…์ฒ˜ ์ˆ˜์ค€ ์ง€์›x86-64, arm64, loongarch, s390

    ๋ด‰์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€

    1. ELF ๋กœ๋” ์ž๋™ ๋ด‰์ธ

    /* fs/binfmt_elf.c:1358 - SVr4 ํ˜ธํ™˜ page 0 ์ž๋™ ๋ด‰์ธ */
    if (current->personality & MMAP_PAGE_ZERO) {
    	error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
    			MAP_FIXED | MAP_PRIVATE, 0);
    	retval = do_mseal(0, PAGE_SIZE, 0);  /* page 0 ๋ด‰์ธ */
    }

    2. ๋ณด์•ˆ ์ ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค

  • Chrome ๋ธŒ๋ผ์šฐ์ €: ๋ณด์•ˆ ์ค‘์š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๋ณดํ˜ธ
  • glibc: ๋™์  ๋กœ๋”๊ฐ€ ELF ์„ธ๊ทธ๋จผํŠธ ๋ด‰์ธ
  • ์‹œ์Šคํ…œ ๋งคํ•‘: vdso, vvar ๋“ฑ ์ปค๋„ ๋งคํ•‘ ๋ณดํ˜ธ
  • 3. ์‚ฌ์šฉ ๋ถˆ๊ฐ€ ์‹œ๋‚˜๋ฆฌ์˜ค

  • aio/shm: ํ”„๋กœ์„ธ์Šค ์ˆ˜๋ช…๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋งคํ•‘ ๊ด€๋ฆฌ โ†’ ๋ˆ„์ˆ˜ ์œ„ํ—˜
  • malloc ํž™: ํž™ ๊ด€๋ฆฌ์ž ๋™์ž‘ ๋ฐฉํ•ด โ†’ ๋น„๊ฒฐ์ •์  ๊ฒฐ๊ณผ

  • ๋ด‰์ธ ๋งคํ•‘์—์„œ์˜ ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ๊ฒฝ๋กœ

    ๋ด‰์ธ๋œ ์ฝ๊ธฐ ์ „์šฉ ๋งคํ•‘์—๋„ ์“ฐ๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค (๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ):

    ๊ฒฝ๋กœ๋ฉ”์ปค๋‹ˆ์ฆ˜์ฐจ๋‹จ ๋ฐฉ๋ฒ•
    `/proc/self/mem`FOLL_FORCE๋กœ ์“ฐ๊ธฐSELinux/SMACK
    `ptrace`PTRACE_POKETEXTseccomp
    `userfaultfd`ํŽ˜์ด์ง€ ํดํŠธ ์ฒ˜๋ฆฌseccomp

    ๊ด€๋ จ ๋ฌธ์„œ

  • 00-overview.html - ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ฐœ์š”
  • 03-vma_mmap.html - VMA / mmap
  • 36-mprotect.html - mprotect
  • 37-mremap.html - mremap
  • 08-oom.html - OOM Killer
  • mseal.rst - ๊ณต์‹ ์ปค๋„ ๋ฌธ์„œ

  • SVG ๋‹ค์ด์–ด๊ทธ๋žจ

    ํ˜ธ์ถœ ํ๋ฆ„

    mseal ํ˜ธ์ถœ ํ๋ฆ„

    ๋ด‰์ธ ๊ฒ€์‚ฌ ์œ„์น˜

    ๋ด‰์ธ ๊ฒ€์‚ฌ ์œ„์น˜