근묵자흑

Learning eBPF 9장 : eBPF for Security 본문

k8s/learning-ebpf

Learning eBPF 9장 : eBPF for Security

Luuuuu 2026. 9. 19. 19:50

O'Reilly, Liz Rice, Learning eBPF (2023) 9장 "eBPF for Security" 스터디

 

관찰 도구는 시스템에서 일어난 일을 기록합니다. 보안 도구는 그 기록을 정책과 비교해 허용할 일인지, 조사할 일인지, 즉시 막을 일인지 판단해야 합니다.

예를 들어 프로세스가 자기 작업 디렉터리에 로그를 쓰는 일은 정상일 수 있습니다. 같은 프로세스가 /etc/passwd를 수정하거나, 예상하지 못한 권한 상승을 시도하면 보안 이벤트가 됩니다. 이벤트 하나만으로는 판단하기 어렵기 때문에 프로세스, 사용자, 컨테이너, 파일, 네트워크 대상, 부모 프로세스 같은 컨텍스트가 함께 필요합니다.

 

1. 용어

용어 의미 이 장에서의 역할
syscall 사용자 공간 프로그램이 커널 기능을 요청하는 인터페이스 seccomp와 syscall 추적의 관찰 지점
seccomp-BPF syscall 번호와 값 인자를 검사하는 BPF 필터 프로세스가 사용할 syscall 표면을 제한
tracepoint 커널이 제공하는 비교적 안정적인 이벤트 지점 syscall 발생 사실을 수집
TOCTOU 검사 시점과 실제 사용 시점 사이의 불일치 syscall 진입점에서 포인터 인자를 볼 때 생기는 위험
LSM hook 커널 보안 모듈이 허용 여부를 판단하는 지점 커널이 대상 객체를 준비한 뒤 감사 또는 차단
BPF LSM LSM hook에 연결하는 eBPF 프로그램 커널 안에서 정책 판단
Tetragon Kubernetes 중심의 eBPF 보안 관찰·런타임 집행 도구 정책, kprobe, 컨텍스트, 조치를 연결
audit 위반 이벤트를 기록하고 조사하는 모드 정책을 적용하기 전 오탐을 확인
enforcement 정책 위반 작업을 거부하거나 프로세스를 종료하는 모드 예방적 보안

보안 정책은 정상 경로만 기록해서 만들면 부족합니다. 디스크가 가득 찼을 때 알림을 보내는 오류 경로처럼 평소에는 드문 행동도 정상일 수 있기 때문입니다. 프로파일을 만들 때는 성공 경로와 오류 경로를 모두 실행해야 합니다.

2. 정책과 컨텍스트의 관계

flowchart LR
    E[커널 이벤트] --> C[컨텍스트 수집]
    C --> P{정책과 비교}
    P -->|허용 범위| A[통과 또는 무기록]
    P -->|조사 필요| L[보안 이벤트 로그]
    P -->|즉시 차단| D[거부 또는 SIGKILL]
    L --> S[SIEM 또는 알림 시스템]

 

같은 openat()이라도 실행 주체와 대상 경로에 따라 의미가 달라집니다. 따라서 “이 syscall이 호출됐는가”만 기록하면 보안 판단에 필요한 정보가 빠집니다. 최소한 PID와 프로세스 이름, 부모 프로세스, UID, 컨테이너 또는 Pod 식별자, 대상 파일이나 네트워크 주소, syscall 결과를 함께 다뤄야 합니다.

3. 보안 도구는 경보기가 아니라 출입문과 기록기를 함께 운영합니다

이 장의 핵심은 “이벤트를 봤다”에서 “정책에 맞는지 판단하고 적절한 시점에 행동한다”로 이동하는 것입니다. 공항 출입문에 비유하면, 카메라는 누가 지나갔는지 기록하고, 출입 카드는 허용된 사람인지 확인하며, 차단 장치는 문제가 있는 통과를 막습니다. eBPF에서는 tracepoint가 카메라에 가깝고, seccomp와 BPF LSM은 출입문에 가깝습니다. 사용자 공간 알림은 조사팀에 연락하는 절차이므로 강력한 차단보다 늦을 수 있습니다.

실행 지점이 중요합니다. syscall 진입점은 사용자 포인터를 받은 직후라 관찰하기 쉽지만, 커널이 포인터가 가리키는 값을 복사하기 전입니다. 그 사이 값이 바뀌면 기록한 값과 커널이 실제로 사용한 값이 달라질 수 있습니다. LSM hook은 커널 내부 객체를 기준으로 판단하므로 같은 문제를 줄이는 데 적합합니다.

TOCTOU 흐름

4. seccomp-BPF: 프로세스의 syscall 표면 줄이기

4.1 seccomp의 역할

seccomp는 프로세스가 커널에 요청할 수 있는 syscall 집합을 제한합니다. seccomp-BPF 필터는 syscall 번호와 struct seccomp_data에 담긴 값 인자를 보고 다음과 같은 결과를 선택할 수 있습니다.

  • 허용
  • 오류 코드 반환
  • 스레드 또는 프로세스 종료
  • 사용자 공간 알림(SECCOMP_RET_USER_NOTIF)

포인터가 가리키는 메모리는 필터가 역참조할 수 없습니다. 이 제약은 필터 표현력을 줄이지만, syscall 인자를 검사한 뒤 사용자 메모리가 바뀌는 TOCTOU 문제를 피하는 데도 도움이 됩니다. Linux 공식 문서도 seccomp를 완전한 샌드박스로 설명하지 않고, 노출된 커널 표면을 줄이는 도구로 설명합니다.

실무에서는 syscall 번호만 비교하면 안 됩니다. 아키텍처 값을 먼저 확인해야 같은 번호가 다른 syscall ABI에서 다르게 해석되는 상황을 막을 수 있습니다. seccomp_data.arch를 검사하는 것이 기본입니다.

4.2 Kubernetes에서의 seccomp

Kubernetes는 Pod 또는 컨테이너의 securityContext.seccompProfile에서 다음 프로파일 유형을 지정합니다.

apiVersion: v1
kind: Pod
metadata:
  name: seccomp-runtime-default
spec:
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      securityContext:
        allowPrivilegeEscalation: false

 

RuntimeDefault는 컨테이너 런타임이 제공하는 기본 프로파일을 사용합니다. Localhost는 노드에 미리 배치한 프로파일을 사용합니다. Unconfined는 제한을 적용하지 않습니다. Kubernetes 문서 기준으로 seccomp API는 안정 기능이며, Restricted Pod Security Standard에서는 RuntimeDefault 또는 Localhost를 사용하도록 요구합니다.

 

privileged: true인 컨테이너에는 seccomp 제한을 적용할 수 없고 항상 Unconfined로 동작합니다. 따라서 seccomp만 켜고 컨테이너 권한, Linux capabilities, allowPrivilegeEscalation, AppArmor 또는 SELinux를 따로 점검하지 않으면 보호 범위를 과대평가하게 됩니다.

4.3 프로파일 생성의 함정

애플리케이션이 실제로 호출한 syscall을 수집해 프로파일을 만드는 방법은 수작업보다 현실적입니다. 책에서는 eBPF를 사용해 raw_syscalls:sys_enter를 관찰하고, 확인한 syscall 집합을 OCI 또는 Kubernetes용 JSON 프로파일로 만드는 도구를 소개합니다.

프로파일 생성 시 다음 상황을 실행 범위에 포함해야 합니다.

  • 정상 요청과 정상 종료
  • 재시도와 타임아웃
  • 디스크 부족, 권한 부족 같은 오류 경로
  • TLS, DNS, 로그, 임시 파일 사용
  • 자식 프로세스와 초기화 작업
  • 실제 배포 환경의 볼륨, 네트워크, 런타임 차이

관찰한 목록은 허용 목록의 초안입니다. 관찰하지 못한 syscall이 필요하지 않다고 단정할 수는 없습니다. 먼저 RuntimeDefault와 감사 모드로 영향 범위를 확인한 뒤, 애플리케이션 단위의 Localhost 프로파일을 좁혀 가는 편이 안전합니다.

4.4 Inspektor Gadget으로 프로파일 만들기

Inspektor Gadget은 Linux 호스트와 Kubernetes에서 eBPF 기반 Gadget을 실행하는 도구입니다. Chapter 9의 seccomp 프로파일 생성과 직접 연결되는 advise_seccomp Gadget은 지정한 컨테이너가 사용한 syscall을 수집해 seccomp JSON 초안을 출력합니다. trace_exec 같은 Gadget은 프로세스 실행 이벤트를 컨테이너 정보와 함께 보여주므로, syscall 목록만 수집할 때 빠지기 쉬운 실행 주체 컨텍스트를 확인하는 데도 유용합니다.

5. syscall 추적 보안 도구와 TOCTOU

Falco는 syscall 이벤트를 규칙과 비교해 보안 경보를 만드는 CNCF 프로젝트입니다. Falco는 syscall event source를 사용하고, 규칙에 맞는 이벤트를 사용자 공간 출력으로 보냅니다. 이미 실행 중인 프로세스에서 발생한 이벤트도 관찰할 수 있으므로, 프로세스 시작 시점에 필터를 설치해야 하는 seccomp와 적용 방식이 다릅니다.

5.1 Falco의 eBPF 드라이버

이번 Lima 환경의 Kubernetes kind 클러스터에서는 docker.io/falcosecurity/falco:0.44.1이 실행 중이었고, Falco 설정의 engine.kindmodern_ebpf였습니다. bpftool에서도 open_e, openat_e, sys_exit, sched_p_exec 계열 프로그램과 sys_enter_openat, sys_enter_connect tracepoint attach를 확인했습니다. 따라서 이 환경에서는 책의 “syscall 진입·종료 지점에 eBPF 프로그램을 붙인다”는 설명이 현재 Falco 구현과 연결됩니다.

문제는 syscall 진입 시점의 포인터 인자입니다.

sequenceDiagram
    participant App as 사용자 프로그램
    participant Enter as sys_enter BPF
    participant Kernel as syscall 구현
    participant User as 사용자 공간 분석기

    App->>Enter: 사용자 포인터를 포함한 syscall 호출
    Enter->>User: 당시 관찰한 값 전송
    Note over App,Kernel: 이 사이에 사용자 메모리의 값이 바뀔 수 있음
    App->>Kernel: 다른 값이 들어 있는 포인터
    Kernel->>Kernel: 사용자 데이터를 커널 객체로 복사
    Kernel-->>App: syscall 처리 결과

 

이 차이가 TOCTOU입니다. 진입 시점에 /tmp/safe로 보였던 문자열이 커널이 읽는 순간 /etc/passwd로 바뀌면, 이벤트 기록과 실제 작업이 다릅니다. 진입 이벤트는 탐지와 분석에는 유용하지만, 그 값만으로 보안 차단을 결정하면 위험합니다.

syscall 종료 시점에 파일 디스크립터 테이블이나 커널 객체를 확인하면 실제 처리 결과를 더 정확하게 기록할 수 있습니다. 다만 syscall은 이미 끝났으므로 종료 시점 관찰만으로는 작업을 되돌리거나 예방할 수 없습니다.

6. BPF LSM: 커널 객체를 기준으로 판단하기

LSM은 커널이 파일, 프로세스, 자격 증명 같은 보안 관련 객체를 처리하기 직전에 호출하는 hook 집합입니다. BPF LSM은 이 hook에 eBPF 프로그램을 연결합니다. Linux 공식 문서 예시는 file_mprotect hook에서 감사하거나 -EPERM을 반환해 작업을 거부하는 형태입니다.

책의 path_chmod 예시는 개념을 보여주는 코드입니다. 실제 코드는 커널 구조체를 안전하게 읽고, 정책의 대상과 예외를 정한 뒤, 허용 시 0을 반환하고 거부 시 적절한 음수 오류를 반환해야 합니다.

SEC("lsm/path_chmod")
int BPF_PROG(path_chmod,
             const struct path *path,
             umode_t mode,
             int ret)
{
    if (ret != 0)
        return ret;

    /* 실제 정책에서는 경로를 문자열 하나로만 판단하지 않습니다. */
    if (/* 보호 대상 파일 */)
        return -EPERM;

    return 0;
}

 

위 코드는 설명용 골격이며 그대로 빌드할 수 있는 완성 예제가 아닙니다. BPF LSM 프로그램에서는 BTF와 CO-RE를 사용해 대상 커널의 타입 정보를 활용할 수 있고, 로더는 libbpf의 LSM attach API를 사용할 수 있습니다. LSM BPF는 Linux 5.7부터 제공됐지만 실제 사용 가능 여부는 배포판의 커널 설정과 BPF 권한 정책을 확인해야 합니다.

LSM hook과 syscall은 일대일 관계가 아닙니다. 하나의 syscall이 여러 LSM hook을 실행할 수 있고, 반대로 정책 목적에 맞는 hook을 찾아야 합니다. 파일 경로를 문자열 접두사 하나로 비교하는 방식도 심볼릭 링크, 하드 링크, mount namespace, rename을 충분히 다루지 못할 수 있습니다.

7. Tetragon: Kubernetes 정책으로 eBPF 보안 기능 묶기

Tetragon은 Kubernetes 리소스인 TracingPolicy로 관찰 지점, 인자 조건, 컨텍스트, 동작을 묶습니다. 책의 예시는 fd_install에 kprobe를 붙여 /etc/ 관련 파일 디스크립터가 설치되는 상황을 확인하는 흐름입니다. fd_install은 커널 파일 객체가 준비된 뒤 호출되므로 syscall 진입점보다 커널이 실제로 사용할 객체에 가까운 위치를 볼 수 있습니다.

Tetragon의 eBPF 보안 관찰 구조

개념적인 정책 형태는 다음과 같습니다.

apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: protect-demo-file
spec:
  kprobes:
    - call: "fd_install"
      syscall: false
      args:
        - index: 0
          type: "int"
        - index: 1
          type: "file"
      selectors:
        - matchArgs:
            - index: 1
              operator: "Equal"
              values:
                - "/tmp/tetragon"
          matchActions:
            - action: Sigkill

 

이 정책은 Tetragon 공식 예제의 구조를 단순화한 설명용 예시입니다. 공식 문서도 파일명만으로 접근을 제한하는 정책은 하드 링크 같은 방법으로 우회할 수 있으므로 실제 보호 정책으로 사용하지 말라고 경고합니다. 운영 정책은 파일 객체, 프로세스 계보, 사용자 ID, namespace, 컨테이너 이미지와 함께 설계하고 우회 경로를 시험해야 합니다.

 

Tetragon은 모든 이벤트를 사용자 공간으로 보내기 전에 커널에서 조건을 좁힐 수 있습니다. 이 방식은 이벤트 양과 사용자 공간 처리 비용을 줄이고, 정책 위반에 대한 조치를 커널 실행 흐름 가까이에서 선택할 수 있게 합니다. kprobe가 내부 커널 함수에 의존하는 만큼 커널 버전과 배포판 패치에 따라 함수 시그니처, 호출 시점, 사용 가능 여부가 달라질 수 있습니다. 가능한 경우 안정적인 tracepoint 또는 LSM hook을 먼저 검토하고, kprobe를 사용할 때는 지원 커널 범위를 고정해 검증해야 합니다.

8. 탐지와 예방의 시간 차이

사용자 공간 알림 방식은 다음 순서로 동작합니다.

flowchart LR
    K[커널 이벤트] --> B[eBPF 필터]
    B --> R[ring buffer 또는 perf buffer]
    R --> U[사용자 공간 에이전트]
    U --> X[로그, 알림, 후속 조치]

이 구조는 조사와 포렌식에 좋지만, 사용자 공간 에이전트가 이벤트를 읽고 조치하는 동안 작업이 이미 진행될 수 있습니다. Tetragon의 Sigkill 같은 조치는 정책 조건이 커널 eBPF 안에서 충족되면 bpf_send_signal()로 현재 프로세스를 종료하는 방향을 사용합니다. 책의 표현처럼 동기적인 예방 효과를 노릴 수 있지만, 모든 작업을 원상 복구하는 트랜잭션은 아닙니다. 이미 외부로 전송된 데이터나 이미 생성된 파일을 되돌리지는 못합니다.

운영 적용 순서는 다음처럼 잡는 편이 안전합니다.

  1. audit 모드로 정상 트래픽과 오류 경로를 수집합니다.
  2. 이벤트에 프로세스 계보, 이미지, Pod, 사용자, 대상 객체가 포함되는지 확인합니다.
  3. 오탐을 분류하고 예외를 최소 범위로 추가합니다.
  4. 개발 또는 canary 환경에서 차단 모드를 켭니다.
  5. 장애 복구 절차와 정책 롤백 방법을 확인합니다.
  6. 범위를 좁힌 뒤 운영에 적용하고, 정책 위반률과 애플리케이션 오류를 함께 관찰합니다.

9. Kubernetes에서의 적용 위치

Kubernetes 보안은 한 가지 eBPF 프로그램으로 해결되지 않습니다. 계층마다 목적이 다릅니다.

계층 주된 수단 막는 대상 확인할 점
프로세스 syscall 표면 seccomp RuntimeDefault 또는 Localhost 불필요한 syscall 오류 경로와 런타임 차이
컨테이너 권한 capabilities, allowPrivilegeEscalation, Pod Security Standards 권한 상승과 과도한 권한 privileged 컨테이너 예외
파일·프로세스 런타임 BPF LSM, Tetragon, Falco 실행, 파일, 권한, 네트워크 이벤트 audit와 enforcement 구분
Pod 네트워크 Cilium 등 eBPF 네트워크 정책 허용되지 않은 연결 identity, namespace, L7 프록시 범위
노드·인터넷 경계 XDP, TC 대량 패킷, 악성 패킷, DDoS 드라이버 지원과 처리 위치

추천하는 구성 흐름은 RuntimeDefault와 Restricted Pod Security Standard를 기본선으로 두고, 애플리케이션별 seccomp 프로파일을 별도로 좁힌 다음, Tetragon이나 Falco를 audit 모드로 운영하는 것입니다. 네트워크 정책은 CiliumNetworkPolicy 같은 네트워크 계층 정책으로 관리하고, 프로세스 런타임 정책과 섞어 하나의 규칙으로 표현하지 않습니다.

10. Lima ARM64에서 확인한 실습

실습은 ebpf-lab Lima VM에서 수행했습니다. 실행 환경은 Ubuntu 24.04.4 LTS, ARM64, Linux 6.8.0-138-generic, bpftool v7.4.0, bpftrace입니다. 결과는 이 VM의 커널과 권한 설정에 종속됩니다.

실습 A. 커널과 BPF 지원 확인

uname -a
uname -m
test -r /sys/kernel/btf/vmlinux && echo "BTF: yes" || echo "BTF: no"
mount | grep /sys/fs/bpf || true
bpftool feature probe kernel | sed -n '1,120p'

확인할 내용은 aarch64, 커널 BTF 존재 여부, BPF filesystem 마운트 여부, lsmbpf 관련 기능입니다. bpftool이 없으면 배포판 패키지를 설치합니다. 실제 기능은 도구 버전보다 Lima VM 내부 커널이 결정합니다.

실습 B. Kubernetes RuntimeDefault 확인

kubectl apply -f seccomp-runtime-default.yaml
kubectl get pod seccomp-runtime-default -o yaml \
  | sed -n '/securityContext:/,/containers:/p'
kubectl delete pod seccomp-runtime-default

Pod가 실행되는지와 적용된 securityContext를 확인합니다. privileged: true를 추가한 변형에서는 seccomp가 Unconfined가 되므로, 이 차이도 별도로 확인합니다.

실습 C. syscall 프로파일 관찰과 차단 비교

관찰 도구가 제공하는 audit 프로파일을 사용해 간단한 컨테이너의 syscall 사용을 기록합니다. 이어서 RuntimeDefault 또는 좁은 Localhost 프로파일을 적용하고, 정상 동작과 실패한 동작을 비교합니다.

kubectl get pod -o wide
kubectl describe pod <pod-name>
kubectl logs <pod-name>

프로파일을 한 번 실행해 통과했다고 해서 충분하지 않습니다. DNS, 로그, 재시작, readiness probe, graceful shutdown을 포함해 반복해야 합니다.

실습 D. Tetragon audit 후 제한 정책 시험

Tetragon 설치 방법은 사용 중인 릴리스의 공식 문서를 기준으로 선택합니다. 먼저 이벤트 출력만 확인하고, 공식 예제처럼 파일 접근 정책을 좁은 테스트 Pod에 적용합니다. Sigkill 정책은 Lima VM 내부의 별도 테스트 namespace에서만 시험합니다.

kubectl create namespace ebpf-security-lab
kubectl -n ebpf-security-lab run shell --image=busybox:1.36 \
  --restart=Never -- sh -c 'sleep 3600'
kubectl -n ebpf-security-lab get pod -o wide

확인할 결과는 다음입니다.

  • 이벤트에 Pod와 컨테이너 식별자가 포함되는지
  • 프로세스 계보가 예상과 맞는지
  • 정책이 파일명만 보는지 파일 객체와 컨텍스트를 함께 보는지
  • audit 모드에서 정상 작업이 기록되는지
  • enforcement 모드에서 대상 프로세스만 종료되는지
  • 에이전트 재시작과 노드 재부팅 뒤 정책이 다시 연결되는지

운영 클러스터에서 임의의 SIGKILL 정책을 실행하면 안 됩니다. 이 초안에서는 실제 Tetragon 설치와 차단 실험을 수행했다고 주장하지 않습니다.

실습 E. 실제 실행 결과

E-1. seccomp-BPF로 syscall 차단

ARM64 syscall 번호 173인 getppidEPERM 반환 동작으로 바꾸는 네 개의 BPF 명령을 프로세스에 설치했습니다. 필터 설치 뒤 직접 syscall을 호출한 결과는 다음과 같았습니다.

blocked_syscall_return -1
NoNewPrivs:     1
Seccomp:        2
Seccomp_filters: 1

Seccomp: 2는 filter mode, Seccomp_filters: 1은 필터 하나가 설치됐다는 뜻입니다. 차단된 syscall의 반환값이 -1이 된 것도 확인했습니다. 이 실험은 syscall을 실제로 제한할 수 있다는 점을 확인하며, Kubernetes의 RuntimeDefaultLocalhost 프로파일이 적용됐다는 증거는 아닙니다.

E-2. syscall tracepoint 관찰

다음 bpftrace 프로그램을 약 8초 동안 실행하면서 openat 이벤트 수를 집계했습니다.

sudo timeout 8 bpftrace -e \
  'tracepoint:syscalls:sys_enter_openat { @openat = count(); }
   interval:s:2 { print(@openat); clear(@openat); }'

실행 중 관찰된 카운터에는 다음 값이 나타났습니다.

@openat: 102
@openat: 101
@openat: 1205
@openat: 946

프로세스가 실행되는 동안 sys_enter_openat가 반복해서 발생하는 것을 확인했습니다. 이 결과는 이벤트 관찰에 해당하며, 정책 위반을 판정하거나 작업을 차단한 결과는 아닙니다.

별도 확인으로 cat /etc/hostname 실행 시 다음 이벤트도 수집했습니다.

pid=564715 comm=cat

PID는 실행 시점마다 달라지며, 중요한 확인점은 cat 프로세스가 openat tracepoint를 발생시켰다는 사실입니다.

E-3. 커널 BPF 기능과 현재 로드 상태

bpftool feature probe kernel에서 다음 기능을 확인했습니다.

eBPF program_type kprobe is available
eBPF program_type tracepoint is available
eBPF program_type lsm is available
eBPF program_type netfilter is available

helper 목록에서는 bpf_send_signal, bpf_send_signal_thread, bpf_probe_read_user, bpf_probe_read_user_str를 확인했습니다. /sys/kernel/security/lsm에는 다음 순서가 표시됐습니다.

lockdown,capability,landlock,yama,apparmor

bpftool prog show에서는 tracepoint와 cgroup 프로그램이 이미 로드돼 있었고, bpftool net show의 XDP, TC, flow dissector, netfilter 항목에는 별도 프로그램이 표시되지 않았습니다. 이 VM에서 LSM 프로그램 타입을 지원하는 것과 실제 BPF LSM 정책을 로드해 시험한 것은 구분해야 합니다.

E-4. Kubernetes와 Tetragon

호스트 kubectl에는 현재 context가 없었지만, Lima VM 안의 kind control-plane 컨테이너에 있는 /etc/kubernetes/admin.conf를 사용해 클러스터에 접근할 수 있었습니다. 클러스터는 Kubernetes v1.31.0, kind control-plane과 worker 두 노드로 구성돼 있었습니다. Lima VM과 kind 노드는 같은 Linux 6.8.0-138-generic 커널을 사용합니다.

Tetragon 실행 파일과 Tetragon Pod는 이 클러스터에 없었습니다. 따라서 Kubernetes RuntimeDefault 적용, Tetragon TracingPolicy, Sigkill enforcement는 실행하지 않았습니다.

이 제한 때문에 Tetragon 절은 공식 문서와 실행 절차를 기반으로 작성했으며, 위의 seccomp syscall 필터나 bpftrace 결과를 Tetragon 적용 결과로 확대하지 않습니다.

E-5. Falco의 syscall 경보

Falco DaemonSet과 테스트 workload가 이미 실행 중인 falco-study namespace를 사용했습니다. 14일 동안 실행 중이던 falco-study-workload-xpsq4 Pod에서 다음 작업을 수행했습니다.

kubectl -n falco-study exec falco-study-workload-xpsq4 -- \
  sh -c 'touch /tmp/ch09-falco-test; cat /etc/shadow >/dev/null; /bin/true'

Falco Pod 로그에서 다음 경보를 확인했습니다.

Warning Sensitive file opened for reading by non-trusted program
file=/etc/shadow process=cat command=cat /etc/shadow
container_name=workload container_image=docker.io/library/ubuntu
k8s_pod_name=falco-study-workload-xpsq4 k8s_ns_name=falco-study

이 결과로 확인한 내용은 세 가지입니다. Falco가 실행 중인 기존 Pod의 syscall 이벤트를 수집했고, cat /etc/shadow를 규칙과 비교해 Warning을 만들었으며, 이벤트에 컨테이너와 Kubernetes namespace·Pod 정보가 포함됐습니다. 경보는 source=syscall로 기록됐고, Falco가 파일 접근을 사후 관찰해 알린 결과입니다. 이 규칙은 작업을 차단하지 않았으므로 BPF LSM이나 seccomp enforcement 결과로 해석하면 안 됩니다.

E-6. Inspektor Gadget의 컨테이너 관찰과 seccomp 초안

Lima VM에 ig 바이너리는 없었지만 Docker와 ARM64 공식 이미지를 사용해 실행했습니다. 테스트용 BusyBox 컨테이너에서 프로세스를 반복 실행한 뒤 trace_exec Gadget을 붙였습니다.

docker run --name ig-test -d --rm busybox:1.36 sh -c \
  'while true; do true; date; cat /etc/hostname >/dev/null; sleep 1; done'

docker run --rm --privileged -v /:/host --pid=host \
  ghcr.io/inspektor-gadget/ig:latest \
  run trace_exec:latest --containername ig-test

공식 이미지 버전은 v0.56.0으로 확인됐고, 이미지 아키텍처는 arm64/linux였습니다. 출력에는 다음과 같은 실행 이벤트가 반복됐습니다.

RUNTIME.CONTAINERNAME  COMM   ARGS
ig-test                true   /bin/true
ig-test                date   /bin/date
ig-test                cat    /bin/cat /etc/hostname
ig-test                sleep  /bin/sleep 1

이어 advise_seccomp를 같은 컨테이너에 연결해 syscall 프로파일을 생성했습니다.

docker run --rm --privileged -v /:/host --pid=host \
  ghcr.io/inspektor-gadget/ig:latest \
  run advise_seccomp:latest --containername ig-test

프로파일에는 brk, clone, execve, openat, read, write 등 관찰된 syscall이 포함됐습니다. 이번 ARM64 실행 결과의 architecturesSCMP_ARCH_X86_64, SCMP_ARCH_X86, SCMP_ARCH_X32로 출력됐습니다.

 

참고 문서