Post

[Linux] BPF

개요

Linux Kernel 관련 1-day 취약점을 공부하다가 BPF에서 LPE 취약점이 발견되어서 BPF에 대해서 서술하고자 합니다.

BPF

BPF는 Berkeley Packet Filter의 약자로 말 그대로 패킷을 걸러내는 필터 역할을 수행합니다.

  • BPF는 in-kernel virtual machine으로 가상의 레지스터를 가지고 있으며 이를 바탕으로 코드를 실행합니다. 때문에 User 영역에서도 커널에서 무슨일이 일어나는지 분석이 가능합니다.

eBPF

eBPF는 BPF의 확장된 버전으로 Extended Berkeley Packet Filter의 약자입니다. 기존 BPF에서 사용하던 레지스터가 확장되고 스택과 맵을 추가했다고 합니다.

💡 기존에 있던 BPF는 cBPF로 불렸지만, 현재는 eBPF만 사용한다고 합니다. 따라서, BPF라고 하는 것은 eBPF라고 생각하시면 됩니다!

동작 방식

eBPF는 이벤트 기반으로 작동하게 됩니다. 사전 정의된 hook를 통해서 아래와 같이 프로그래밍한다면 execve가 실행될 때마다 eBPF로 확인이 가능하게 됩니다.

💡 만약, 사전 정의된 hook가 없다면 kprobe나 uprobe를 생성해서 연결이 가능합니다.

0동작 방식

Programming

eBPF Program은 c언어로 작성된 뒤 컴파일러를 통해 bytecode로 변환되게 됩니다. 즉, Linux Kernel은 eBPF Program이 bytecode로 로드될 것이라고 예상합니다.

1Programming

Loader & Verification Architecture

컴파일된 eBPF는 bpf 시스템콜에 의해 다음 그림과 같이 Verifier 이후 JIT(Just-in-Time) 컴파일러에 의해서 컴파일이 되면 실행가능한 상태가 됩니다.

💡 JIT 컴파일러로 컴파일하는 이유는 프로그램의 실행속도를 최적화하기 위해서라고 합니다.

2BPF 전체 구조

Verification

eBPF는 커널과 밀접한 관계가 있기 때문에 검증도 매우 중요한 단계입니다. 따라서, 다음과 같은 검증을 진행하게 됩니다.

  1. eBPF 프로그램을 로드하는 프로세스는 권한이 있어야합니다.
  2. 로드되는 eBPF가 충돌하거나 시스템에 해를 끼치면 안됩니다.
  3. 로드되는 eBPF는 항상 완료되야 합니다.

💡 eBPF 프로그램은 Linux Kernel에 로드되기 때문에 까다로운 검증을 하게됩니다.

JIT Compiler

앞에서 언급했듯이 검증이 완료된 eBPF 프로그램은 JIT Compiler에 의해 컴파일이 진행됩니다. 이는, 실행 속도를 최적화하기 위함입니다.

Maps

eBPF Maps 기능을 이용해 수집된 정보를 공유하고 상태를 저장하게 됩니다. eBPF Maps은 시스템 호출을 통해 eBPF 프로그램과 User 공간의 애플리케이션에서도 액세스할 수 있습니다.

3BPF Maps

참고사이트

This post is licensed under CC BY 4.0 by the author.