ARMv8.5 에서 추가된 보안기법으로, 메모리 할당/해제 연산마다 (1) 사용되는 포인터와 (2) 접근하는 메모리 간에 상호 태그를 하고, 태그 정보 비교를 통해 안전한 접근인지 체크하는 일종의 Sanitizer 기법이다.
그동안 수많은 Sanitizer 기법들이 메모리 할당자를 통한 Buffer overflow, Use-after-Free (UAF) 등 메모리 안전 버그 (Memory Safety Bug)를 탐지하기 위해 제안되었지만, 휴리스틱하게 탐지하는 등 탐지율이 낮거나 사용성이 좋지 않은 단점이 있었다.
ARM에서는 이걸 하드웨어로 해결해버렸다.
이 그림이 MTE의 핵심을 한번에 설명 해 준다.
Buffer overflow 탐지: 메모리 할당 시에 포인터에 상위 비트에 태깅 정보를 설정하고 (파란색), 이 포인터를 통해 할당된 영역 이상의 범위를 참조하게 되면 (노란색) 일종의 segmentation fault를 발생시킨다.
Use-After-Free (UAF) 탐지: 포인터 해제 시점에 메모리에 다른 태깅 정보 (혹은 태깅 초기화)를 설정하고, 해당 포인터를 통해 기존 메모리 영역을 접근하게 되면 (연두색) 마찬가지로 segmentation fault를 발생시킨다.
같은 원리로 out-of-scope나 각종 boundary violation 등을 탐지 가능하다.
하드웨어 Memory controller를 통해서, 태깅 정보가 다른 경우에 실제로 SIGSEGV 발생시켜서 결과적으로는 SEGV_MTESERR
(동기모드, 실시간탐지) 나 SEGV_MTEAERR
(비동기모드) 에러를 발생시킨다.
새로 추가된 명령어는 비교적 간단하다. 태그를 생성하고 메모리와 포인터에 태깅을 하면 끝.
IRG
: 랜덤 태그를 할당하는 명령어
STG, STZG
: allocation tag (할당태그)를 메모리에 저장하는 명령어
LDG
: 메모리에서 allocation tag를 로딩하고, address tag (주소태그)를 생성하는 명령어
포인터와 메모리 접근 시마다 태깅 정보를 비교하는 건 Memory controller 수정을 통해 가능하다.
하드웨어를 통해 Memory Controller에서 지원되고, 컴파일러가 아닌 커널이나 운영체제의 memory allocator 수정을 통해 가능하다보니 개발자가 만든 어플리케이션 컴파일 시에는 어려운 코딩이 필요 없다.
커널개발자라면 CONFIG_ARM64_MTE=y
와 CONFIG_KASAN_HW_TAGS=y
설정을 확인하자. 새로운 매핑 flag인 PROT_MTE
도 확인할 수 있다.
https://www.kernel.org/doc/html/next/arch/arm64/memory-tagging-extension.html
Android 개발자라면 실행파일에 memtag_heap: true
나 LOCAL_SANITIZE := memtag_heap
를 추가하여 어플리케이션 별로 MTE를 동작시킬 수 있다.
MTE에 대한 소개는 사실 https://source.android.com/docs/security/test/memory-safety 에 자세히 나와 있고, 오늘 기록하고 싶은 내용은 다름 아니라 MTE가 과연 얼마나 안전한지에 대해서이다.
PAC와 마찬가지로, MTE도 64비트 주소 중에 사용하지 않는 top byte를 사용한다. 다만 스펙상 MTE를 위한 top byte가 4 byte 밖에 되지 않는 정도인데, entropy가 매우 모자라다고 생각된다.
만약에 neighboring coloring 같은 문제를 기억해보면, 결국 공간인접성이 있는 메모리 접근이라 정확도 측면에서는 다소 떨어질 것 같다. (공격자가 인접 메모리에 allocation을 일부러 발생시키고, 같은 태그 정보를 가진 포인터/메모리 pair를 gadget 처럼 모으는 공격도 가능하지 않을까 싶다)
메모리 할당 문제에서 고질적이긴한데, page aligned 된 영역에서만 MTE가 유효하다는 점이다. Page 내에서 Buffer overflow나 UAF 같은 건 당연하겠지만 탐지하지 못 한다.
최근 오픈된 Android U OS 기능 보면, arm64.memtag.bootctl
을 통해서 MTE를 on/off 할 수 있도록 지원하는 것 같다. 그렇다면 bootcontrol message만 탈취하면 MTE on/off를 조정할 수 있다는 걸로 보이는데, Pixel8에서 된다고 하니 기능을 조금 더 살펴볼 필요는 있을 것 같다.
MTE가 만능은 아니라고는 하지만, 지금까지 나왔던 Sanitizer 중에서 가장 센세이션한 건 맞는 것 같다. 원래 ARM에서 만든 기술인데, 왜인지는 모르겠지만 Google이 제일 열심히 신나게 포스팅을 하고 있다.
https://googleprojectzero.blogspot.com/2023/11/first-handset-with-mte-on-market.html
https://security.googleblog.com/2023/11/mte-promising-path-forward-for-memory.html?m=1
아무래도 하드웨어 기능이다 보니까, Android 플랫폼에서 지원한다고 해도 AP칩에서 지원하지 않으면 도입할 수 없는 기술이라고 생각한다.
그래서 지금까지는 구글에서 만드는 Pixel8, Tensor G3 정도만 볼 수 있지 않을까? 라고 생각했는데
말이 나오기 무섭게 Mediatek Dimensity9300 발표 할 때 귀신 같이 MTE를 지원한다고 전면에 내세웠다 (타이밍이 좀 신기하긴하다)
https://corp.mediatek.com/news-events/press-releases/mediateks-new-all-big-core-design-for-flagship-dimensity-9300-chipset-maximizes-smartphone-performance-and-efficiency