Skip to content

Latest commit

 

History

History
66 lines (54 loc) · 3.53 KB

ARCHITECTURE.md

File metadata and controls

66 lines (54 loc) · 3.53 KB

Architecture

This document describes BPFContain's project layout and explains what each source file does. The goal is to help new contributors develop a mental model of what BPFContain is, what technologies it relies on, and how it works.

src/bpf/bpfcontain.bpf.c

This file contains definitions for the eBPF programs and maps that make BPFContain work. For this, we leverage libbpf and BPF CO-RE, which provides several convenience helpers for loading and managing eBPF programs as well as "compile once, run everywhere" functionality.

On the Rust side, we use libbpf-rs which provides safe Rust bindings for libbpf. We use the accompanying libbpf-cargo crate to build the eBPF programs and generate a Rust skeleton file for easy program management.

eBPF Programs

  • LSM Programs
    • LSM programs define an interface for attaching BPF programs to LSM security hooks.
    • These form the backbone of BPFContain's policy enforcement.
    • LSM programs are annotated with the SEC("lsm/<target>") section label and are defined using libbpf's BPF_PROG(name, args...) helper macro.
    • They begin by filtering the current task to make sure that it is confined, then return a policy decision (0 means allowed, -EACCES means denied).
  • BTF Tracepoints
    • Tracepoints define a stable tracing interface for attaching BPF programs.
    • These are used for basic bookkeeping (i.e. keeping track of processes, and which policy and "container" they belong to).
    • They are annotated with the SEC("tp_btf/<target>") section label.
  • Uprobes
    • Uprobes allow BPF programs to be attached to target addresses in userspace applications.
    • In BPFContain, we use uprobes to provide an interface for userspace to interact with our eBPF programs.
    • They are annotated with the SEC("uprobe/<target>") section label.
    • Currently, we have one uprobe that allows a process to "containerize" itself.

eBPF Maps

All of BPFContain's maps are defined in src/bpf/include/map_defs.h.

  • Processes Map
    • This map caches information about actively confined processes and is used to implement filtering logic for the LSM programs.
  • Containers Map
    • This map caches information about active containers including which policy they are associated with along with other properties like taintedness.
  • Policy Maps
    • These are eBPF hash maps that define a mapping between policy "keys" and "values".
    • There are several policy maps, one per policy type.
    • The keys are comprised of a "policy id" along with the necessary data to describe the requested system object (e.g. inode and device number for a file).
    • The values are three bit vectors: allowed, tainted, and denied. Each of these vectors defines a bitmask which represents the corresponding access to the requested object.
      • allowed must be a superset of the requested access for access to be granted.
      • tainted can be any subset of the requested access for the process to become tainted.
      • denied can be any subset of the requested access for access to be denied.
    • "Tainting" is a feature of BPFContain which triggers default-deny enforcement (i.e. if access is not explicitly allowed, it is assumed to be denied). Once a process becomes tainted, it can never become untainted.

src/bpf/bpfcontain.skel.rs and src/bpf/mod.rs

These files are automatically generated by libbpf-cargo when building the project. They are not included in the repository proper.

TODO: Other Files Coming Soon