Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement eBPF backend #35

Merged
merged 111 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
161f940
feat: add placeholder ebpf feature and libbpf-rs dep
kxxt Aug 7, 2024
2822d46
feat/ebpf: add a placeholder bpf program
kxxt Aug 7, 2024
5c7baae
feat: add WIP ebpf program for system tracing
kxxt Aug 8, 2024
51466f4
WIP: add non-working version that cannot pass verifier
kxxt Aug 9, 2024
6506312
git: ignore .cache
kxxt Aug 9, 2024
fb44129
WIP: add event counter, output string using ringbuf
kxxt Aug 9, 2024
c409210
refactor/bpf: rework error flags and make string reading generic
kxxt Aug 9, 2024
b169dcd
feat/bpf: impl envp read
kxxt Aug 9, 2024
6657e40
feat/bpf: print ringbuf content in userspace
kxxt Aug 9, 2024
fa84d57
fix/build: rerun build.rs on bpf header change
kxxt Aug 9, 2024
a145de3
refactor/bpf: move some fields into a common header
kxxt Aug 9, 2024
3bcca7d
fix/ci: ignore /include for typos
kxxt Aug 9, 2024
cb7838a
refactor/bpf: add event type field to header
kxxt Aug 9, 2024
4be143a
deps: bump libbpf-rs to 0.24.1
kxxt Aug 9, 2024
f2a66bb
docs/bpf: add more comments in bpf program
kxxt Aug 9, 2024
a63ad53
feat/bpf: define MAX_CPUS in build.rs
kxxt Aug 9, 2024
3db128f
fix/bpf: only enable debug output if ebpf-debug or built in debug mode
kxxt Aug 9, 2024
333f5e6
fix/bpf: remove duplicated eid field
kxxt Aug 9, 2024
af31530
fix/bpf: increase ringbuf size
kxxt Aug 10, 2024
0278c62
feaat/bpf: send exec event to userspace
kxxt Aug 10, 2024
df41587
refactor/bpf: extract common part of execve{,at} code
kxxt Aug 10, 2024
2665dcb
feat/bpf: dynamically size cache map before load
kxxt Aug 10, 2024
90fab6a
bpf: bump events map size to 256MiB
kxxt Aug 10, 2024
0676474
wip/bpf: read kernel current->files->fdt
kxxt Aug 10, 2024
fd7a8d2
wip/bpf: read fdt->max_fds from kernel and set some consts
kxxt Aug 11, 2024
7a52f85
wip/bpf: set fdset max size to 2MiB and prepare to cache it
kxxt Aug 11, 2024
1ebbece
wip/bpf: read fdset from kernel
kxxt Aug 11, 2024
9dd8ef4
wip/bpf: read open fds
kxxt Aug 12, 2024
5331239
wip/bpf: prepare to read fd info
kxxt Aug 12, 2024
41f424e
bpf: disable open fd loop
kxxt Aug 12, 2024
dba48a9
feat/bpf: print argv and envp in userspace
kxxt Aug 12, 2024
6bd0b5f
fix/bpf: ensure string_event is sent
kxxt Aug 12, 2024
7a0a516
wip/bpf: read fdset words using bpf_loop
kxxt Aug 12, 2024
760ec7d
feat/bpf: read base filename of open fds
kxxt Aug 12, 2024
0219e40
feat/bpf: read fd flags
kxxt Aug 12, 2024
9ce99de
fix/bpf: fix condition in find_next_bit
kxxt Aug 12, 2024
077d862
feat/bpf: store fd count in event
kxxt Aug 12, 2024
1eb4d82
feat/bpf: save fdinfo in userspace
kxxt Aug 12, 2024
75112dd
fix/bpf: handle event drops for string_event in userspace
kxxt Aug 13, 2024
2f4d296
feat/bpf: follow forks
kxxt Aug 14, 2024
41f65b4
build: add script for downloading 3rdparty dependencies
kxxt Aug 14, 2024
d4380ac
lint: allow BSD-2-Clause license
kxxt Aug 14, 2024
06c8b27
deps: patch libbpf-sys and add static,vendored features
kxxt Aug 17, 2024
b0c4e95
fix/ebpf: track event losses
kxxt Aug 17, 2024
6f448f0
fix: guard ebpf code with cfg(feature = "ebpf")
kxxt Aug 17, 2024
d1e6021
refactor: decouple printer from tracer ProcessState
kxxt Aug 17, 2024
9ba401b
refactor!: split ptrace backend options from Modifier{Args,Config}
kxxt Aug 17, 2024
a2ed8b1
feat/bpf: implement --successful-only
kxxt Aug 17, 2024
6cb09d4
fix/cli: fix behavior of --show-filename
kxxt Aug 25, 2024
57deb68
feat/bpf: support running in non-init pid namespaces
kxxt Aug 25, 2024
2ba127c
fix/bpf: events may be sent out of order
kxxt Aug 25, 2024
8a4b70e
docs: comment about a bug of ebpf-debug feature
kxxt Aug 25, 2024
da0f690
feat/bpf: read path segments
kxxt Aug 26, 2024
76be03e
fix/bpf: stop path segment reading at mnt_root
kxxt Aug 26, 2024
0ca679c
feat/bpf: grab absolute path from kernel
kxxt Aug 27, 2024
0918ce6
fix/bpf: clean up ebpf code
kxxt Aug 28, 2024
fb20027
bpf: report syscall_nr and use signed path_id
kxxt Aug 28, 2024
6d71a91
feat/bpf: trace execveat and read pwd
kxxt Aug 28, 2024
79be92e
fix/bpf: rework on path reading and sending
kxxt Aug 28, 2024
389fa44
refactor/bpf: use refcell
kxxt Aug 28, 2024
6440ac1
fix: make cross-compilation work
kxxt Aug 29, 2024
6f4ab3b
ci: fix cross-compilation
kxxt Aug 29, 2024
65ae41a
ci: disable musl builds and offer static gnu builds
kxxt Aug 29, 2024
da3c923
refactor/tracer: use OutputMsg for argv
kxxt Aug 31, 2024
1d8c570
refacto/bpf: store temporary info in EventStorage
kxxt Aug 31, 2024
37c79e9
refactor/bpf: use OutputMsg for argv
kxxt Aug 31, 2024
300ba6a
feat: config native libraries linkage via featrue flags
kxxt Aug 31, 2024
121f187
docs: update install guide and move to INSTALL.md
kxxt Aug 31, 2024
35c43f0
refactor/tracer: use OutputMsg for envp
kxxt Sep 1, 2024
4eb6f49
chore: ignore (E)nvironment in typos.toml
kxxt Sep 1, 2024
d0001d4
refactor/tracer: make interpreter field optional in Exec{Data,Event}
kxxt Sep 1, 2024
ea546b0
refactor/tracer: use OutputMsg for filename and cwd
kxxt Sep 2, 2024
f90ee10
fix/bpf: rename identifiers to avoid collision with vmlinux.h on riscv64
kxxt Sep 2, 2024
b63c3b0
cli: make ebpf cli match original cli
kxxt Sep 2, 2024
64f173d
perf/bpf: eliminate extra copying
kxxt Sep 2, 2024
9bab652
bpf: collect paths
kxxt Sep 2, 2024
6ce00cf
feat/bpf: reuse printer impl for printing traces
kxxt Sep 4, 2024
7eabd99
fix/bpf: remove tgid from closure on process exit
kxxt Sep 5, 2024
e37b623
bpf: detect tracee exit in bpf instead of waitpid
kxxt Sep 5, 2024
2deb20e
feat/bpf: show absolute path for execveat
kxxt Sep 5, 2024
82fb3bb
refactor/bpf: save stack space in read_fds_impl
kxxt Sep 6, 2024
e790369
feat/bpf: set cloexec in flags if fd in cloexec_set
kxxt Sep 6, 2024
ed00763
feat/bpf: read ino and mnt_id of open file
kxxt Sep 7, 2024
5d0d12a
proc: compare fd equility by ino and mnt_id instead of path
kxxt Sep 7, 2024
f1cd91c
fix/printer: show cwd correctly with consistent style
kxxt Sep 7, 2024
252bdd5
bpf: use placeholder path if we got nothing from kernel
kxxt Sep 7, 2024
db1ea11
feat/bpf: manually detect socket and pipe and use procfs like name
kxxt Sep 7, 2024
237d414
fix/bpf: impl basic err handling for argv,envp and filename
kxxt Sep 7, 2024
c6f7d53
refactor: make tracer optional in TUI
kxxt Sep 13, 2024
80efe3f
refactor!: split debugger args/config from tui args/config
kxxt Sep 13, 2024
caf7617
refactor: move bpf userspace logic into (Running)EbpfTracer
kxxt Sep 14, 2024
b0890f8
fix/bpf: fix {PATH,FSTYPE}_SEGMENT_MAX off by one
kxxt Sep 14, 2024
c978b8c
feat/bpf: implement TUI command for eBPF
kxxt Sep 15, 2024
41884e3
feat/bpf: send exit code/signal in exit_event
kxxt Sep 15, 2024
678abae
feat/bpf: send fork event to userspace
kxxt Sep 15, 2024
3e54b34
feat/bpf: implement process status update
kxxt Sep 15, 2024
082d305
git: label vmlinux.h as generated file
kxxt Sep 15, 2024
e7827da
feat/bpf: store fstype as fdinfo.mnt
kxxt Sep 15, 2024
7d669dd
bpf: use /proc style display format of anon_inode
kxxt Sep 16, 2024
965ad8b
bpf: adjust loglvl
kxxt Sep 16, 2024
09e6e14
refactor/tracer: calc foreground in cli
kxxt Sep 16, 2024
23fb9c9
tracer: refactor TracerMode to include foreground and impl it in eBPF…
kxxt Sep 16, 2024
6bcf7a6
fix(lint): make clippy happy
kxxt Sep 16, 2024
a34cf72
feat/bpf: send tracee exit message
kxxt Sep 16, 2024
86153ef
fix/tui: off by one in cwd display code
kxxt Sep 16, 2024
1f86538
tui: don't assume tracer channel is kept open
kxxt Sep 16, 2024
591abaa
feat/bpf: add collect command
kxxt Sep 16, 2024
6321d33
chore: bump version to 0.6.0-beta.1
kxxt Sep 16, 2024
6518593
chore: upgrade crates
kxxt Sep 16, 2024
3861e31
perf/tui: use a smaller buf for scrollview if possible
kxxt Sep 16, 2024
641d6cd
fix/tui: fix Rect mismatch if clipped
kxxt Sep 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/include/*/vmlinux.h linguist-generated=true
86 changes: 70 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ jobs:
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
components: clippy,rustfmt
- name: Install native dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y libelf-dev zlib1g-dev build-essential
- name: Cache Cargo dependencies
uses: Swatinem/rust-cache@v2
- name: Run clippy
Expand All @@ -75,47 +79,97 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
toolchain: ["stable"]
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
- aarch64-unknown-linux-musl
- riscv64gc-unknown-linux-gnu
include:
- os: ubuntu-22.04
os-arch: amd64
target: x86_64-unknown-linux-gnu
arch: x86_64
libpath: usr/lib/x86_64-linux-gnu
no-default-features: false
- os: ubuntu-22.04
os-arch: amd64
target: x86_64-unknown-linux-gnu
arch: x86_64
libpath: usr/lib/x86_64-linux-gnu
no-default-features: false
args: '-F static,vendored'
rust_flags: -C target-feature=+crt-static
- os: ubuntu-22.04
os-arch: arm64
target: aarch64-unknown-linux-gnu
arch: aarch64
libpath: usr/lib/aarch64-linux-gnu
no-default-features: false
- os: ubuntu-22.04
os-arch: arm64
target: aarch64-unknown-linux-gnu
arch: aarch64
libpath: usr/lib/aarch64-linux-gnu
no-default-features: false
args: '-F static,vendored'
rust_flags: -C target-feature=+crt-static
- os: ubuntu-22.04
os-arch: riscv64
target: riscv64gc-unknown-linux-gnu
arch: riscv64
libpath: usr/lib/riscv64-linux-gnu
no-default-features: true
runs-on: ${{ matrix.os }}
env:
RUST_FLAGS: ${{ matrix.rust_flags }}
# LIBBPF_SYS_LIBRARY_PATH: ${{ github.workspace }}/3rdparty/${{ matrix.arch }}/${{ matrix.libpath }}
# LIBBPF_SYS_EXTRA_CFLAGS: -I ${{ github.workspace }}/3rdparty/${{ matrix.arch }}/usr/include
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust {{ matrix.toolchain }}
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
toolchain: "1.80"
targets: ${{ matrix.target }}
components: rustfmt
- name: Install cross-compilation tools
uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: ${{ matrix.target }}
- name: Add apt sources for ${{ matrix.os-arch }}
if: matrix.os-arch != 'amd64'
run: |
dpkg --add-architecture ${{ matrix.os-arch }}

release=$(. /etc/os-release && echo "$UBUNTU_CODENAME")
sed -i 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list
printf 'deb [arch=${{ matrix.os-arch }}] http://ports.ubuntu.com/ %s main restricted\n' \
$release $release-updates $release-security \
>> /etc/apt/sources.list
shell: sudo sh -e {0}
- name: Install build dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y build-essential autopoint gettext libelf-dev zlib1g-dev \
libelf-dev:${{ matrix.os-arch }} zlib1g-dev:${{ matrix.os-arch }}
# - name: Prepare libelf and zlib
# run: 3rdparty/prepare-native-dependencies.sh ${{ matrix.arch }}
- name: Cache Cargo dependencies
uses: Swatinem/rust-cache@v2
- name: Run cargo build with default features
if: matrix.target != 'riscv64gc-unknown-linux-gnu'
run: cargo build --bins --tests --target ${{ matrix.target }}
run: cargo build --bins --tests --target ${{ matrix.target }} ${{ matrix.args }}
- name: Run cargo build with no default features
if: matrix.target == 'riscv64gc-unknown-linux-gnu'
run: cargo build --bins --tests --target ${{ matrix.target }} --no-default-features
run: cargo build --bins --tests --target ${{ matrix.target }} --no-default-features ${{ matrix.args }}
- name: Run cargo check with default features
if: matrix.target != 'riscv64gc-unknown-linux-gnu'
run: cargo check --target ${{ matrix.target }}
run: cargo check --target ${{ matrix.target }} ${{ matrix.args }}
env:
RUST_BACKTRACE: full
- name: Run cargo check with no default features
if: matrix.target == 'riscv64gc-unknown-linux-gnu'
run: cargo check --target ${{ matrix.target }} --no-default-features
run: cargo check --target ${{ matrix.target }} --no-default-features ${{ matrix.args }}
env:
RUST_BACKTRACE: full
- name: Run cargo test with default features
if: matrix.target == 'x86_64-unknown-linux-gnu' || matrix.target == 'x86_64-unknown-linux-musl'
run: cargo test --target ${{ matrix.target }}
run: cargo test --target ${{ matrix.target }} ${{ matrix.args }}
env:
RUST_BACKTRACE: full
53 changes: 50 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,48 @@ jobs:
matrix:
include:
- os: ubuntu-22.04
os-arch: amd64
target: x86_64-unknown-linux-gnu
arch: x86_64
libpath: usr/lib/x86_64-linux-gnu
no-default-features: false
- os: ubuntu-22.04
target: x86_64-unknown-linux-musl
os-arch: amd64
target: x86_64-unknown-linux-gnu
arch: x86_64
libpath: usr/lib/x86_64-linux-gnu
no-default-features: false
features: static,vendored
artifact-suffix: -static
rust_flags: -C target-feature=+crt-static
- os: ubuntu-22.04
os-arch: arm64
target: aarch64-unknown-linux-gnu
arch: aarch64
libpath: usr/lib/aarch64-linux-gnu
no-default-features: false
- os: ubuntu-22.04
target: aarch64-unknown-linux-musl
os-arch: arm64
target: aarch64-unknown-linux-gnu
arch: aarch64
libpath: usr/lib/aarch64-linux-gnu
no-default-features: false
features: static,vendored
artifact-suffix: -static
rust_flags: -C target-feature=+crt-static
- os: ubuntu-22.04
os-arch: riscv64
target: riscv64gc-unknown-linux-gnu
arch: riscv64
libpath: usr/lib/riscv64-linux-gnu
no-default-features: true
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- uses: taiki-e/install-action@v2
with:
tool: cargo-about
Expand All @@ -53,9 +76,27 @@ jobs:
prefix-key: ${{ matrix.os }}-${{ matrix.target }}-rust
cache-targets: true
cache-on-failure: false

- name: Add apt sources for ${{ matrix.os-arch }}
if: matrix.os-arch != 'amd64'
run: |
dpkg --add-architecture ${{ matrix.os-arch }}

release=$(. /etc/os-release && echo "$UBUNTU_CODENAME")
sed -i 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list
printf 'deb [arch=${{ matrix.os-arch }}] http://ports.ubuntu.com/ %s main restricted\n' \
$release $release-updates $release-security \
>> /etc/apt/sources.list
shell: sudo sh -e {0}
- name: Install native dependencies
if: runner.os == 'Linux'
run: sudo apt update -y && sudo apt install -y binutils-aarch64-linux-gnu gcc-aarch64-linux-gnu binutils-riscv64-linux-gnu gcc-riscv64-linux-gnu
run: |
sudo apt update -y
sudo apt install -y {binutils,gcc}-{aarch64,riscv64}-linux-gnu \
build-essential autopoint gettext libelf-dev zlib1g-dev \
libelf-dev:${{ matrix.os-arch }} zlib1g-dev:${{ matrix.os-arch }}
# - name: Prepare libelf and zlib
# run: 3rdparty/prepare-native-dependencies.sh ${{ matrix.arch }}
- name: Publish to crates.io
if: matrix.os == 'ubuntu-22.04' && matrix.target == 'x86_64-unknown-linux-gnu'
continue-on-error: true
Expand All @@ -65,9 +106,15 @@ jobs:
- name: Generate third-party licenses
run: cargo about generate -o THIRD_PARTY_LICENSES.HTML about.hbs
- uses: taiki-e/upload-rust-binary-action@v1
env:
RUST_FLAGS: ${{ matrix.rust_flags }}
# LIBBPF_SYS_LIBRARY_PATH: ${{ github.workspace }}/3rdparty/${{ matrix.arch }}/${{ matrix.libpath }}
# LIBBPF_SYS_EXTRA_CFLAGS: -I ${{ github.workspace }}/3rdparty/${{ matrix.arch }}/usr/include
with:
bin: tracexec
token: ${{ secrets.GITHUB_TOKEN }}
archive: $bin-$target${{ matrix.artifact-suffix }}
target: ${{ matrix.target }}
no-default-features: ${{ matrix.no-default-features }}
features: ${{ matrix.features }}
include: THIRD_PARTY_LICENSES.HTML,LICENSE
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
/target
.vscode
# BPF
*.skel.rs
*.bpf.o
# Clangd
/.cache
4 changes: 4 additions & 0 deletions 3rdparty/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
x86_64/
aarch64/
riscv64/
*.deb
80 changes: 80 additions & 0 deletions 3rdparty/prepare-native-dependencies.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/bin/bash

set -e

# Dependencies are fetched from debian snapshot,
# like: https://snapshot.debian.org/binary/libelf1/


libelf_ver=0.190-1
zlib_ver=1.3.dfsg+really1.3.1-1
wget="wget -c"

rust_arch2deb_arch() {
case "$1" in
x86_64)
echo "amd64"
;;
aarch64)
echo "arm64"
;;
*)
echo "$1"
;;
esac
}

unpack_deb_for() {
mkdir -p "$1"
dpkg --fsys-tarfile "$2" | tar -C "$1" -x
}

libelf_deb_name_for() {
if [[ "$2" = "dynamic" ]]; then
echo "libelf1_${libelf_ver}_$(rust_arch2deb_arch "$1").deb"
else
echo "libelf-dev_${libelf_ver}_$(rust_arch2deb_arch "$1").deb"
fi
}

zlib_deb_name_for() {
if [[ "$2" = "dynamic" ]]; then
echo "zlib1g_${zlib_ver}_$(rust_arch2deb_arch "$1").deb"
else
echo "zlib1g-dev_${zlib_ver}_$(rust_arch2deb_arch "$1").deb"
fi
}

prepare_libelf_for() {
dynamic_deb="$(libelf_deb_name_for "$1" dynamic)"
$wget "https://snapshot.debian.org/archive/debian/20231117T085632Z/pool/main/e/elfutils/${dynamic_deb}"
unpack_deb_for "$1" "$dynamic_deb"
static_deb="$(libelf_deb_name_for "$1" static)"
$wget "https://snapshot.debian.org/archive/debian/20231117T085632Z/pool/main/e/elfutils/${static_deb}"
unpack_deb_for "$1" "$static_deb"
}

prepare_zlib_for() {
timestamp="20240510T150153Z"
if [[ "$1" = "aarch64" ]]; then
timestamp="20240510T205852Z"
elif [[ "$1" = "riscv64" ]]; then
timestamp="20240510T150153Z"
fi
dynamic_deb="$(zlib_deb_name_for "$1" dynamic)"
$wget "https://snapshot.debian.org/archive/debian/$timestamp/pool/main/z/zlib/${dynamic_deb}"
unpack_deb_for "$1" "$dynamic_deb"
static_deb="$(zlib_deb_name_for "$1" static)"
$wget "https://snapshot.debian.org/archive/debian/$timestamp/pool/main/z/zlib/${static_deb}"
unpack_deb_for "$1" "$static_deb"
}

ARCH="$1"

if [[ -z "$ARCH" ]]; then
echo "Usage: $0 <RUST_ARCH>"
exit 1
fi

prepare_libelf_for "$ARCH"
prepare_zlib_for "$ARCH"
Loading