메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

Fast, Flexible, and Practical Kernel Extensions

noriwiki


SOSP 2024
Kumar Kartikeya Dwivedi, Rishabh Lyer, Sandihya Kashyap

개요

OS의 커널 리소스와 Kernel-extension의 리소르를 구분하여, Kernel extension을 Pratical하게 만드는 방법을 제시하고 Kflex라는 새로운 Abstraction domain을 구현함

KFLEX는 기존의 eBPF Extension연구와는 다르게, Motivation포인트를 새로운 방향에서 출발하고 있음. 즉, eBPF를 확장하는 것이 아니라, 새로운 kernel extension을 만드는 것으로 Motivation을 잡음.

Motivation

Kernel extension은 많이 연구되어 왔고, 실제로도 많이 사용되고 있다. Kernel extension은 다음 4가지를 충족시켜주어야 한다.

  • Safety: Extension이 kernel의 integrity를 해치면 안된다.
  • Flexibility: User가 diverse한 기능을 가진 functionality를 커널에 offloading가능하여야 한다.
  • Performance: Extension이 excessive runtime overhead를 발생시키면 안된다.
  • Practicality: Framework이 developer들에게 쉬워야 하며, new programming languages나 specific한 toolchain에 의존하면 안된다.

Importance

현재 존재하는 Kernel extension기법들은 위의 4가지를 충족시키지 못한다.

The trade-off between four important traits between protection domains
Safety Flexibility Performance Practicality
Type and memory safe programming languages O O O X
Runtime checks O O X O
Static verification (eBPF) O X O O
Kflex O O O O
  • Safe memory languages: Spin OS, Singularity, TockOS, Rust
  • Software Fault Isolation: VINO, NACL
  • Static verification: Necula, eBPF

Main Design Ideas

커널의 Safety property를 여러 타입으로 구분하고, kernel에 대한 방어는 static verification으로 extension에 대한 방어는 runtime verification으로 막았다. 이를 통해서 다음과 같은 이점 (Programming model)을 제공하였다.

  • Arbitrary memory layout을 통해서 Own data structure을 정의할 수 있도록 함
  • Complex한 Loop을 사용할 수 있도록 함
  • 여러개의 Spin lock을 획득할 수 있도록 함
    • 이를 위해서 Loop에서 획득한 커널 리소스는 반드시 Iteration이 끝난뒤 Release하도록 하였다. 이는 eBPF의 loop analysis logic을 위해서 존재한다.

Design

우선 KFLEX는 kernel safety를 두가지 타입으로 구분하였다. kernel-interface (커널 내부의 safety) 그리고 extension correctness (Extension자체의 safety)로 구분하였다. 여기서 추가적으로 KFlex는 kernel resource를 Internal, External의 두 타입으로 분류하였다. Internal과 같은 경우에는 Memory access이며, External과 같은 경우에는 Helper function, Kernel function이 주된 공격 포인트로 간주하였다. Internal은 SFI로 막았고, External과 같은 경우에는 Runtime check으로 막았다.

  • Kernel-interface compliance: Kernel이 소유하고 있는 Resource에 대한 방어
    • Internal resource: Kernel memory에 대한 Integrity
    • External resource: Kernel의 function call에 대한 integrity
  • Extension correctness: Extension이 작동하는 환경에 대한 방어
    • Extension memory safety: Extension이 사용하는 메모리에 대한 Integrity
    • Terminate correctly: Exntesion이 infinite loop이나 termination을 제대로 하지 못하는 경우에 대한 방어
Kernel-interface compliance
KFlex는 eBPF기반으로 작성되어 있기 때문에, Static하게 잡을 수 있는 Kernel-interface complicance와 같은 경우에는 SFI를 사용하지 않도록 하여서, 성능상의 이점을 가져올 수 있었다. 즉, 위 도식에서 Kernel-interfrace compliance의 Internal resource, 그리고 External resource는 eBPF를 활용하면 자연스럽게 해결되는 부분이다.
Extension memory safety
Software fault isolation기법을 활용하여 모든 pointer dereference에 guard를 하도록 하였다. 이러한 guarding mechanisms은 maksing을 통해서 overhead를 최소한으로 할 수 있도록 구현하였다. KFLEX는 eBPF Static verifier을 통해서 자명한 부분에는 이러한 guarding을 생략할 수 있도록 하여서, overhead를 더욱 줄였다. Performance Mode에서는 read에 대해서는 이러한 guarding이 필요없도록 하여서 더욱 속도를 올렸다 (대신 information leak이 발생할 수 있음).
Terminate correctly
KFlex는 eBPF verifier를 수정해서 Loop을 돌 수 있도록 하였다. 따라서, 안전하게 Termination을 할 수 있도록 하기 위해서, KFlex는 Kernel이 eBPF프로그램을 실행시키기 전에 수정을 가해서 모든 possible loop안에 terminate라고 하는 heap영역을 참조하여서, 만약 terminate가 true이면 리소스를 정리하고 빠져나오도록 하였다. termination조건은 timer로 구현하였다. 또한 SFI가 invalid한 memory access를 탐지한 경우에도 terminate가 되도록 하였다. Terminate가 되면서 Acquire한 Kernel resource들을 모두 Release해야 하는데, 이를 위해서 KFLEX는 CP (Calcel point)라는 것을 모든 possible terminate마다 두어서, 그 루프안에서 발생한 Object allocation들을 별도의 Runtime object table을 통해서 기록하고, 참고하여 Release하도록 하였다.
Low overhead communication with user space
Kernel과 User가 메모리를 공유하기 위해서는 다음의 두개를 고려해야 한다. 첫째, User와 Kernel가 같은 Virtual address를 볼수 있도록 할것. 이를 통해서 Data structure의 pointer arithmetic이 같은 의미를 가지도록 할것. 둘째, User와 Kernel의 Synchronization이 가능할것. 첫번째를 위해서 Runtime이 User와 공유되어 있는 영역 (e.g., mmap된 메모리 영역)을 그대로 커널이 볼 수 있도록 하였다. SFI가 guarding으로 이 영역을 보호하도록 하였다. 두번째를 위하여, User가 temporary time slice extension을 요구하면, 커널이 그 영역에 대해서 잠시동안 mutex가 걸리도록 하였다.

Conclusion

우선 많은 KFLex의 Motivation은 eBPF로 구현가능하다. 우선 bpf_arena를 통해서 eBPF도 Userspace처럼 자유롭게 Data structure를 작성할 수 있다. 두번째로 bpf_loop을 사용하면 거의 대부분의 loop을 구현할 수 있다.

개인적으로, Automated verification이 kernel-interface에 대한 최선의 verification방법이라고 생각하지 않는다. Kernel function을 위해서는 사용자가 일일이 Verification을 지정해주어야 하는데, 이는 TCB증가 뿐만 아니라 앞서 주장한 Practicality측면에서도 위반되는 사항이다. 즉, kflex의 장점이라고 소개된 function에 대한 임의이 접근을 막기 위해서는 모든 커널 함수에 대한 적절한 sanitizing이 있어야 하는데, 구체적으로 어떻게 할 것인지에 대한 설명이 없다.

추가적으로, eBPF는 Pointer leak과 같은 일도 막지만, KFlex는 정확히 어떻게 그러한 일을 해야 하는지에 대한 설명이 부족하다. 예를 들어서, Cancellation포인트에 대한 설명은 possible kernel data mismatch를 어떻게 극복할지 고려하지 못하였다. 예를 들어서 커널 메모리에 접근하다가 루프를 빠져나와 버리면 그 영역은 corruption이 일어난 상태로 방치되어 버린다. 또한 Loop에 Static한 boundary limit을 두는 것은 궁극적인 Termination condition을 해결하는 방향이 아니다. 물론 Halting problem을 해결하는 것이 힘든 것은 잘 알려진 사실이다.

그러나 Motivation으로 가져온, Safety, Flexibility, Performance, and Practicality에 대한 분석은 흥미로운 부분이었다. 또한 논문을 이끌어나가는 방향성도 Style측면에서 좋다고 생각한다.