MarkUs: Drop-in use-after-free prevention for low-level languages


개요

MarkUS는 GC기반의 Memory allocator로써, Free된 메모리를 Quarantine영역에 보관하고 있다가, Dangling pointer가 사라지만 다시 사용하도록 하여서 UAF버그를 Prevent할 수 있는 기법을 제시하였다.

Motivation

기존에 pointer nullification이나 static analysis, dynamic tracking과 같은 방식은 메모리 그리고 성능 면에서 좋지 않았다. MarkUS는 GC가 아니다. GC는 가비지, 즉 사용되지 않지만 free되지 않은 메모리들을 잡아낸다 (Memory leak을 막기 위한 목적). MarkUS는 GC와 비슷한 방식으로 Pointer tracking을 하지만 목적이 UAF버그를 막는 것이다. 따라서 더 Simplify된 코드로 UAF버그들을 검출할 수 있다.

Main Idea

UAF버그를 탐지 하기 위해서 MarkUS는 GC처럼 Mark and sweep을 이용하여서 Reuse할 수 있는 포인터들을 찾아 내었다. 기존 GC와 다른 점은 MarkUS는 프로그램의 free()함수를 기점으로 포인터가 Free됨을 힌트로 삼을 수 있다는 점이다.

Design

사용자가 Object A를 free()한 경우.

  1. 만약 Object A가 large object인 경우 바로 virtual address를 unmap시키고, reuse할 수 있도록 delete한다.
  2. 만약 Object A가 Page size보다 작은 small object일 경우, Object A는 Quarantine List에 들어간다.
  3. 주기적으로 Quarantine list에 있지만, 현재 stack, heap, bss, data, registers에 포인터 reference가 없는 reuse가능한 포인터들을 search한다. 이때 상호참조를 해결하기 위해서, graph traversing을 통해서 pointer들을 walking하여서 free할 수 있는 포인터들을 찾는다. 이 phase는 parallel하게 진행할 수 있다. 만약 Object A에 해당하는 참조가 없을 경우, Object A를 delete하지만 아닐 경우 quarantine list에서 계속 추적한다.
  4. Mark-and-sweep은 free()를 통해서 얻은 현재 free된 메모리 양을 통해서 heuristic하게 어느 시점에 시작할 것인지를 조절할 수 있다. 정확하지는 않지만, 이 방식을 통해서 Memory overhead의 정도를 어느정도 조절할 수 있다. 또한 dirty bit tracking을 통해서 stop-the-world 시간을 최소화 하였다.

Evaluation

  1. 전반적으로 Acceptable한 Overhead를 보여주었음. (SPEC CPU 2006기준, performance 14% memory 27%의 오버헤드)
  2. 특정 벤치에서 (NGINX)에서 매우 큰 Memory leak이 관측되었음. 이는 False-positive때문일 것이라 사료됨.

Conclusion

Limitations

  1. False-positive가 존재할 수 있다.
  2. Obfuscated된 Pointer들을 추적할 수 없다.
  3. Bohem방식의 GC를 사용함으로 Concurrency가 떨어진다.
  4. High-contention상황에서 성능이 매우 떨어진다.

Positive

  1. GC방식과 비슷하면서 다른 방식을 사용하여 UAF버그를 어떻게 Quarantine방식을 통해서 막을 수 있는지를 보임
  2. 이 방식은 후속연구(Minesweeper)들에 영향을 미침