콘텐츠로 이동

Strict Devmem 물리 메모리 직접 접근 차단

1. 개요 및 위협 모델 (Overview & Threat Model)

Strict Devmem (CONFIG_STRICT_DEVMEM) 및 Strict I/O Devmem (CONFIG_IO_STRICT_DEVMEM)은 특권 사용자(root / UID 0 / CAP_SYS_RAWIO)라 할지라도 /dev/mem 문자 디바이스를 통해 시스템 물리 RAM(System RAM) 및 디바이스 드라이버가 사용 중인 I/O 메모리에 직접 매핑하거나 읽기/쓰기하는 행위를 원천 차단하는 커널 방어 기술임.

전통적인 유닉스 시스템에서 /dev/mem은 전체 물리 주소 공간(Physical Address Space)에 대한 바이트 단위 직접 접근을 허용하였으며, 초기 X11 디스플레이 서버가 VGA 프레임버퍼나 BIOS ROM을 제어하기 위해 사용되었음. 그러나 현대 보안 관점에서는 치명적인 링-0 우회 통로로 작용함:

  1. 물리 메모리 직접 조작을 통한 커널 장악 (Ring 0 Bypass):
  2. 공격자가 유저 공간에서 root 권한을 획득한 후, /dev/mem을 mmap()하여 실행 중인 커널 코드 섹션(.text), 시스템 콜 디스패치 테이블, 또는 특정 프로세스의 task_struct->cred 구조체(UID/GID 필드)를 물리 주소에서 직접 0으로 덮어써 영구적인 링-0 백도어를 설치하는 공격 벡터.
  3. 커널 암호키 및 기밀 데이터 물리 덤프 위협:
  4. 디스크 암호화 마스터 키(LUKS), 커널 난수 풀(Entropy Pool), 프로세스 민감 메모리를 물리 RAM 상에서 직접 탐색하여 추출하는 위협.
  5. 디바이스 DMA 레지스터 하이재킹 위협:
  6. 활성화된 네트워크 카드(NIC)나 NVMe 스토리지의 MMIO 레지스터를 직접 조작하여 악의적인 DMA(Direct Memory Access) 전송을 트리거하고 커널 메모리를 오염시키는 위협.
  7. Strict Devmem 2단계 방어 체계:
  8. CONFIG_STRICT_DEVMEM=y: 시스템 물리 RAM(System RAM) 영역 접근 전면 차단 (devmem_is_allowed(pfn) == 0).
  9. CONFIG_IO_STRICT_DEVMEM=y: 커널 드라이버가 활발히 점유 중인 MMIO 레지스터 접근 차단 (devmem_is_unconsumed(pfn) == 0).

2. 방어 아키텍처 및 메커니즘 (Architecture & Mechanism)

1. Strict Devmem 인터랙티브 아키텍처 시뮬레이터


2. 실생활 비유: 금고 건물의 '물리 배선 접근 차단 방화벽'

Strict Devmem의 방어 메커니즘은 중앙은행 전산실의 물리적 회선 보호벽과 유사함:

[ 비활성화 상태 (Permissive: CONFIG_STRICT_DEVMEM=n) ]
  침입자(Root): "내가 빌딩 최고 관리자 권한을 가졌으니, 서버 본체 전원선과 메인보드 버스(/dev/mem)를
                 물리적으로 직접 납땜하고 칩셋 데이터를 복제하겠다!"
  경비 시스템:   "최고 권한자이므로 모든 물리 주소 배선 연결 허용." (물리 메모리 오염 위험)

[ Strict Devmem 활성화 (CONFIG_STRICT_DEVMEM=y) ]
  침입자(Root): "System RAM 영역에 속하는 물리 메모리(커널 코드/데이터)를 매핑 시도!"
  하드웨어 센서: "devmem_is_allowed(pfn) 호출! 대상 물리 프레임이 System RAM에 속함!"
  조치:         "접근 즉시 차단 (-EPERM 거부)! 관리자라 할지라도 물리 RAM 직접 매핑 불가!"

[ Strict I/O Devmem 활성화 (CONFIG_IO_STRICT_DEVMEM=y) ]
  침입자(Root): "현재 NVMe 스토리지 드라이버가 제어 중인 DMA 레지스터 MMIO를 직접 매핑 시도!"
  검문 센서:     "devmem_is_unconsumed(pfn) 호출! 드라이버가 점유 중인 활성 I/O 리소스 확인!"
  조치:         "접근 차단 (-EPERM 거부)! 디바이스 DMA 하이재킹 원천 방어!"

3. 커널 내부 판정 알고리즘 상세

1) devmem_is_allowed(unsigned long pfn)

  • 유저 공간이 /dev/mem에 대해 mmap(), read(), write()를 호출할 때 아키텍처별 함수를 통해 PFN(Page Frame Number)을 검사함.
  • 대상 PFN이 커널 페이지 할당기(Page Allocator)에 의해 관리되는 System RAM 범위에 속할 경우 0을 반환하여 -EPERM 에러 발생.
  • 오직 시스템 RAM 외부의 레거시 영역(e.g., BIOS ROM, VGA 텍스트 프레임버퍼 0xa0000)만 접근 허용.

2) devmem_is_unconsumed(unsigned long pfn)

  • CONFIG_IO_STRICT_DEVMEM=y 설정 시 동작함.
  • 대상 PFN이 I/O 리소스 트리(/proc/iomem의 PCI 디바이스 메모리)에 등록되어 있고, 특정 커널 드라이버가 request_mem_region() 또는 devm_ioremap_resource()를 통해 이미 소유권을 주장(Claimed)한 상태라면 0을 반환하여 차단함.

3. Kconfig 설정 및 인터페이스 (Configuration)

1. Kconfig 프래그먼트

# configs/features/strict-devmem.config
CONFIG_DEVMEM=y
CONFIG_STRICT_DEVMEM=y
CONFIG_IO_STRICT_DEVMEM=y

2. 커널 제어 인터페이스 및 시스템 파일

인터페이스 / 파일 유형 설명
/dev/mem 문자 디바이스 (1:1) 물리 메모리 직접 접근 인터페이스 (STRICT_DEVMEM에 의해 필터링)
/proc/iomem R-only 시스템 물리 주소 맵 조회 (System RAM, PCI Bus, 드라이버 점유 MMIO 범위 확인)
devmem=relaxed 커널 cmdline 부팅 시 STRICT_DEVMEM 제한을 일시 해제(Permissive)하는 디버깅용 옵션

4. 실습 및 검증 (Hands-on Verification & Exploit PoC)

1. 테스트 시나리오 개요

  • root 계정으로 로그인하여 물리 메모리 조작을 시도:
  • Phase 1: Baseline (Permissive Mode):
    • 물리 System RAM, 활성 드라이버 MMIO, 레거시 ROM 접근이 모두 허용됨.
  • Phase 2: Mode 1 (Strict RAM - CONFIG_STRICT_DEVMEM=y):
    • 물리 System RAM 접근 시 커널이 즉각 -EPERM으로 차단.
    • 드라이버 MMIO 및 레거시 ROM 접근은 허용.
  • Phase 3: Mode 3 (Strict RAM + I/O - CONFIG_IO_STRICT_DEVMEM=y):
    • 물리 System RAM 접근 차단 (-EPERM).
    • 드라이버 점유 MMIO 접근 차단 (-EPERM).
    • 레거시 미점유 ROM 접근만 안전하게 허용.
  • Phase 4: Direct /dev/mem Probe:
    • /proc/iomem의 System RAM 시작 주소를 파싱한 후, mmap(/dev/mem) 호출 시 커널이 -EPERM을 반환함을 직접 검증.

2. 듀얼 아키텍처 실측 실행 로그

./scripts/run_qemu.sh --arch arm64 --kernel build_dir/arm64-devmem/arch/arm64/boot/Image --test test_strict_devmem
================================================================
   Lab 37: Strict Devmem & Strict I/O Devmem Verification Suite 
   Kernel: 6.12.109 on aarch64                           
================================================================
[*] Step 1: Inspecting /dev/mem device node and /proc/iomem...
crw-r-----    1 root     kmem        1,   1 Jan  1 00:00 /dev/mem
    System physical memory map preview (/proc/iomem):
    40000000-7fffffff : System RAM
      40080000-413effff : Kernel code
      41570000-41abffff : Kernel data
[*] Step 2: Checking target driver at /proc/vuln_strict_devmem...
[+] Target driver detected.

[*] Step 4: Running Strict Devmem PoC...
================================================================
  Strict Devmem & Strict I/O Devmem Verification PoC            
  UID: 0, GID: 0                                                
================================================================
[*] Initial Target Driver Status:
========================================================
        Linux Strict Devmem Status Report               
========================================================
Strict Devmem Mode      : [2] Strict RAM + Active I/O (2: System RAM & Driver I/O protected)
System RAM Defense      : ENFORCED (CONFIG_STRICT_DEVMEM=y) (devmem_is_allowed)
Active I/O Protection   : ENFORCED (CONFIG_IO_STRICT_DEVMEM=y) (devmem_is_unconsumed)
Total Access Probes     : 0
Access Requests Granted : 0
System RAM Denials      : 0 (-EPERM)
Active I/O Denials      : 0 (-EPERM)
========================================================

[*] PHASE 1: Evaluating Baseline (Mode: Permissive - 0)
    -> Accessing physical System RAM... (GRANTED)
    -> Accessing active driver I/O memory... (GRANTED)
    -> Accessing legacy unclaimed ROM/VGA... (GRANTED)

[*] PHASE 2: Evaluating Mode 1 (Strict RAM)
    -> Accessing physical System RAM (expecting BLOCKED: -EPERM)... (BLOCKED: -EPERM)
    -> Accessing active driver I/O memory (expecting GRANTED)... (GRANTED)
    -> Accessing legacy unclaimed ROM/VGA (expecting GRANTED)... (GRANTED)

[*] PHASE 3: Evaluating Mode 2 (Strict RAM + I/O)
    -> Accessing physical System RAM (expecting BLOCKED: -EPERM)... (BLOCKED: -EPERM)
    -> Accessing active driver I/O memory (expecting BLOCKED: -EPERM)... (BLOCKED: -EPERM)
    -> Accessing legacy unclaimed ROM/VGA (expecting GRANTED)... (GRANTED)

[*] Testing direct /dev/mem mmap() on System RAM (Phys: 0x40000000)...
    [+] SUCCESS: mmap(/dev/mem) to System RAM blocked by kernel: Operation not permitted (errno=1)
        -> CONFIG_STRICT_DEVMEM successfully defended kernel memory!

[+] Strict Devmem Verification Complete: Physical Memory Protections Proven!

[*] Step 5: Inspecting kernel dmesg for Strict Devmem events:
[    4.210450] strict_devmem: [DENIED] Attempted /dev/mem access to System RAM (pfn > 0x100) rejected: -EPERM
[    4.210480] System RAM protection active: devmem_is_allowed() returned 0!
[    4.211902] strict_devmem: [DENIED] Attempted /dev/mem access to driver-claimed I/O memory rejected: -EPERM
[    4.211930] Active I/O memory protection active: devmem_is_unconsumed() returned 0!
================================================================
   Lab 37 Test Complete: Verified Strict Devmem Protections     
================================================================

./scripts/run_qemu.sh --arch x86_64 --kernel build_dir/x86_64-devmem/arch/x86/boot/bzImage --test test_strict_devmem
================================================================
   Lab 37: Strict Devmem & Strict I/O Devmem Verification Suite 
   Kernel: 6.12.109 on x86_64                           
================================================================
[*] Step 1: Inspecting /dev/mem device node and /proc/iomem...
crw-r-----    1 root     kmem        1,   1 Jan  1 00:00 /dev/mem
    System physical memory map preview (/proc/iomem):
    00001000-0009fbff : System RAM
    00100000-3ffdffff : System RAM
      01000000-01c01fff : Kernel code
      01c02000-023fffff : Kernel data
[*] Step 2: Checking target driver at /proc/vuln_strict_devmem...
[+] Target driver detected.

[*] Step 4: Running Strict Devmem PoC...
================================================================
  Strict Devmem & Strict I/O Devmem Verification PoC            
  UID: 0, GID: 0                                                
================================================================
[*] PHASE 1: Evaluating Baseline (Mode: Permissive - 0)
    -> Accessing physical System RAM... (GRANTED)
    -> Accessing active driver I/O memory... (GRANTED)
    -> Accessing legacy unclaimed ROM/VGA... (GRANTED)

[*] PHASE 2: Evaluating Mode 1 (Strict RAM)
    -> Accessing physical System RAM (expecting BLOCKED: -EPERM)... (BLOCKED: -EPERM)
    -> Accessing active driver I/O memory (expecting GRANTED)... (GRANTED)
    -> Accessing legacy unclaimed ROM/VGA (expecting GRANTED)... (GRANTED)

[*] PHASE 3: Evaluating Mode 2 (Strict RAM + I/O)
    -> Accessing physical System RAM (expecting BLOCKED: -EPERM)... (BLOCKED: -EPERM)
    -> Accessing active driver I/O memory (expecting BLOCKED: -EPERM)... (BLOCKED: -EPERM)
    -> Accessing legacy unclaimed ROM/VGA (expecting GRANTED)... (GRANTED)

[*] Testing direct /dev/mem mmap() on System RAM (Phys: 0x100000)...
    [+] SUCCESS: mmap(/dev/mem) to System RAM blocked by kernel: Operation not permitted (errno=1)
        -> CONFIG_STRICT_DEVMEM successfully defended kernel memory!

[+] Strict Devmem Verification Complete: Physical Memory Protections Proven!

[*] Step 5: Inspecting kernel dmesg for Strict Devmem events:
[    8.110290] strict_devmem: [DENIED] Attempted /dev/mem access to System RAM (pfn > 0x100) rejected: -EPERM
[    8.110320] System RAM protection active: devmem_is_allowed() returned 0!
[    8.111812] strict_devmem: [DENIED] Attempted /dev/mem access to driver-claimed I/O memory rejected: -EPERM
[    8.111840] Active I/O memory protection active: devmem_is_unconsumed() returned 0!
================================================================
   Lab 37 Test Complete: Verified Strict Devmem Protections     
================================================================


5. 성능 및 호환성 분석 (Performance & Compatibility)

  1. 런타임 오버헤드 (Zero Runtime Impact):
  2. 물리 메모리 필터링 검사는 사용자가 /dev/mem에 대해 open(), mmap(), read(), write()를 호출하는 진입 시점에만 단 한 번 수행되므로, 일반 애플리케이션 실행 속도에 미치는 영향은 0%임.
  3. 모던 디스플레이 서버(KMS/DRM) 호환성:
  4. 과거 X11 서버는 하드웨어 레지스터 제어를 위해 /dev/mem에 의존했으나, 현대 리눅스의 커널 모드 세팅(KMS / Direct Rendering Manager) 아키텍처에서는 커널 DRM 드라이버가 GPU 메모리를 전담하므로 /dev/mem 차단으로 인한 그래픽 호환성 문제가 전혀 발생하지 않음.
  5. 디버깅 도구 제약 사항:
  6. busybox devmem과 같은 저수준 메모리 디버거를 통한 RAM 내용 덤프가 차단되므로, 커널 분석이 필요한 개발 환경에서는 devmem=relaxed 부팅 파라미터를 선별적으로 활용할 것을 권장함.

6. 강의 및 발표 스크립트 (Lecture & Presentation Script - English Practice)

Standard 4-Step Technical English Presentation

1. Opening Hook & Problem Statement

"Good morning, everyone. In early Unix architecture, the /dev/mem character device was considered a standard feature, allowing direct byte-level mapping of physical address space. However, in modern threat landscapes, unrestricted /dev/mem completely obliterates the distinction between user space and kernel space. Even if virtual memory protections like W^X or SMAP are in place, a privileged root user or compromised service can simply open /dev/mem and overwrite running kernel text or credentials directly in physical RAM. Today, we investigate Strict Devmem and Strict I/O Devmem."

2. Diagram & Architecture Walkthrough

"Please direct your attention to the interactive architecture simulator on the screen. Notice the physical address classification. When an application attempts to map an address via /dev/mem, the kernel invokes two defensive checks. First, devmem_is_allowed(pfn) verifies whether the requested page resides within physical System RAM. Under CONFIG_STRICT_DEVMEM=y, all RAM pages are unconditionally rejected with an -EPERM error. Second, devmem_is_unconsumed(pfn) checks whether the target MMIO range is actively claimed by a hardware driver. Under CONFIG_IO_STRICT_DEVMEM=y, active device registers and DMA control spaces are also isolated, leaving only harmless unclaimed legacy ROMs accessible."

3. Live Demo Commentary

"In our live demonstration on ARM64 and x86_64, look at the contrast between modes. In Permissive mode, arbitrary physical RAM addresses can be mapped directly into userspace. However, when we evaluate Hardened mode, any attempt to access physical System RAM—such as address 0x40000000 on ARM64 or 0x100000 on x86_64—is immediately intercepted, returning -EPERM. Furthermore, our raw syscall probe confirms that mmap(/dev/mem) fails with 'Operation not permitted'. The kernel text, creds, and page tables remain completely impenetrable."

4. Key Takeaways & Production Advice

"To conclude: Enabling CONFIG_STRICT_DEVMEM=y and CONFIG_IO_STRICT_DEVMEM=y is an indispensable requirement for enterprise systems and cloud hypervisors. It seals off physical backdoors, ensuring that root privileges in userland cannot be translated into Ring 0 kernel compromise through physical memory tampering."