개요
SFI (software fault isolation)은 memory access와 control transfer operation에 dynmaic한 checks를 수행함으로써 malicious한 프로그램의 실행에서 host를 보호하는 기법이다. SFI는 OS kernel extension의 분리, browser에서 plug-in들의 분리, 그리고 JVM에서 native libraries들의 분리와 같은 여러 분야에서 사용되고 있다.
원리
SFI는 machine-code level에서 프로세스간의 logical protection을 제공한다. SFI는 untrust한 code가 동작하는 memory 영역을 구별한다. 이러한 protection을 제공하기 위해서, interpreter, rewriter 혹은 compiler의 지원으로 동작한다. SFI는 구별된 memory 영역에서 conde의 data-access와 control flow에 제한을 가하는 것으로 protection을 구현한다. (즉 Data region, code region그리고 trusted runtime region을 구별한다.)
- 모든 data access는 반드시 data region에 있는 메모리 영역만 참조할 수 있다.
- control flow는 code region사이에서만 일어나거나 external trusted runtime region만을 참고할 수 있다.
이 두 원칙을 구현하는 모든 code는 지정된 protection boundary밖으로 탈출 할 수 없기에, protection boundary에서 돌아간다고 할 수 있다. 이러한 원칙을 구현하기 위해서 다음과 같은 방식들이 사용된다.
- Binary translation: interpreter가 모든 machine code들을 검사하면서, 이 machine code들이 제대로 SFI policy를 따르고 있는지 검사하는 기법이다.
- Inlined Reference monitor: Machine code rewriter가 실행하고자 하는 프로그램에 inline checks들을 삽입해서, 실행하는 프로그램이 SFI policy를 따르고 있는지 감시하는 기법이다.
한계
Bound check그리고 Pointer maksing과 같은 Runtime overhead가 매우 크다. 예를 들어서 Native Client와 같은 경우 untrusted code 실행에 있어서 거의 42%의 해당하는 overhead가 발생한다고 알려져 있다.
또한 SFI는 control flow를 탈취하거나 변조하는 공격에는 취약하다. 따라서 이러한 한계를 극복하기 위해서 SFI는 CFI와 같은 control-flow의 integrity를 체킹하는 기법들과 함께 사용되어야 한다. 그러나 CFI와 같은 기법들은 오버헤드가 심하기 때문에 또한 여기서도 performance downgradation이 발생한다.