init_pg_dir 도입 패치 분석

DEWH 2020.12.31 23:23 조회 수 : 234 추천:1

"이전에 해당 내용으로 글을 쓴 적이 있는데, 내용을 보완하여 공유합니다."
 

init_pg_dir 도입 패치 분석

Purpose

해당 패치의 목적은 KSMA(Kernel Space Mirroring Attack)을 어렵게 만드는 것이다.

 

 

Patch series

  1. arm64/mm: Separate boot-time page tables from swapper_pg_dir

  2. arm64/mm: use fixmap to modify swapper_pg_dir

  3. arm64/mm: move runtime pgds to rodata

 

KSMA

해당 공격 기법은 2018 Black hat에서 소개되었다. KSMA는 ARM MMU feature을 이용하고, EL0(user)에서 시스템 콜 없이 커널 이미지에 Read/Write 할 수 있게 된다.

 

Linux kernel은 아래 그림처럼 여러 단계의 변환을 통해 물리 주소로 변환된다.

d14fee_5cef9544047548e99bd1e3e81740c4d0~

ARM MMU의 각 단계의 변환 테이블들은 엔트리를 가지고 있다. 엔트리들은 3가지 타입으로 구성된다.

  1. Table descriptor

  2. Block descriptor

  3. Page descriptor

 

이 중에서 물리 메모리 주소를 저장하는 엔트리는 Block, Page descriptor이다. 이 두 엔트리들은 매핑된 메모리에 관한 속성들을 아래와 같이 저장한다.

 

d14fee_2a6cb3d2f73644029e317cc631427c3c~

 

 

 

그 중에서 AP 필드는 Read/Write 권한을 저장한다. AP가 가질 수 있는 값들은 아래의 테이블과 같다.

d14fee_601da94c3f8a4825bb7222276035273d~

이때 AP가 01일 때, Exception Level 0일 때도 Read/Write 할 수 있다.

 

따라서, pgd로 사용되는 swapper_pg_dir에 AP가 01로 설정된 block descriptor를 삽입하는 것이 핵심이다.

 

아래 그림은 swapper_pg_dir에 커널 이미지 영역을 매핑하는 block descriptor을 넣은 모습이다.

 

d14fee_2ce7f8963ba942cd9ade2db084bb070d~

물리 메모리 0x3002000에 접근할 때, Direct mapping된 가상 주소나 KSAM을 통한 가상 주소를 통해 접근할 수 있다.

 

Direct mapping

Virtual Addess: 0xFFFFFFC03002000 -> Physical Address: 0x3002000

EL1에서만 접근가능하다.

 

KSAM

Virtual Addess: 0xFFFFFFC23002000 -> Physical Address: 0x3002000

EL0에서도 Read/Write 가능하다.

 

 

Basic idea

공격의 대상이 되는 swapper_pg_dir을 rodata로 옮기자!

 

문제 : 불필요한 페이지들도 rodata로 묶인다.

해결 방안 : 부팅 단계의 페이지 테이블과 정규 페이지 테이블로 분리한다.

 

문제 : swapper_pg_dir에 값을 쓸 방법을 제공해야 한다.

해결 방안 : fixmap에 매핑한 다음 해당 주소를 사용한다.

 

결과:

 

1. 부팅 초기 단계에 수행했던 swapper_pg_dir의 역할은 init_pg_dir로 대체된다.

2. swapper_pg_dir은 한 페이지로 축소되며, rodata 섹션에 위치하게 된다.

3. init_pg_dir이 추가되어 page_init에서 새로운 pgd를 할당받지 않아도 된다.

4. swapper_pg_dir에 값을 쓰기 위해서는 fixmap에 매핑해야 한다.

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 강좌, 팁, 정보등에 대해 올리는 게시판입니다. woos 2016.04.09 246
129 Pro Git 2장, 3장 요약입니다. 아폴로 2013.11.05 52112
128 포토샵 웹버전입니다. [1] 강진성 2010.05.14 40685
127 맥에서 리눅스 커널 빌드하기 [2] K 2013.06.30 24822
126 #pragma에 관련해서.. [2] 원민수 2006.07.19 20782
125 kernel 2.6의 kzalloc함수 (원민수 씀) 백창우 2007.02.23 19337
124 태훈님에 이어. ARM kernel 참고자료 백창우 2007.11.05 19014
123 리눅스 커널 스터디 참고자료 (x86) [4] 리누즈박 2013.05.06 18397
122 누가 나를 호출했는지 찾기 + 포인터를 심볼 이름으로 변환하여 출력하기 [1] 지현구 2007.02.27 17863
121 systemtap 관련 간단한 소개입니다. 남용우 2007.11.06 17057
120 허접 영어 사전입니다. [3] 백창우 2008.04.22 16092
119 define을 사용한 version 처리. 원민수 2008.02.09 15026
118 여기는 팁, 기타 정보를 올리는 곳입니다. 백창우 2006.06.05 14751
117 커널 분석용 vim 플러그인 설치하기 (Rev.4) [21] 리누즈박 2013.06.30 13973
116 막강 디버깅 매크로 DM_PRINT() [4] file 배상경 2010.11.23 12045
115 if문에 사용하는 likely와 unlikely 함수의 용도 [1] 아폴로 2014.03.05 11174
114 조금은 묵직한 시스템, 뇌감시장치 김성현2 2011.11.17 10585
113 리눅스 커널 코딩 스타일입니다. [1] 아폴로 2013.09.13 10147
112 xen 4.1 설치 방법(우분투 11.04) [2] 이상철 2012.11.14 10109
111 Kernel 소스코드 github에 복사하는 법 [6] 리누즈박 2013.06.16 9837
110 돈되는 이야기?! 삼성 손가락 혈압계 [1] 김성현2 2011.10.20 9493
XE Login