This project demonstrates the use of eBPF (Extended Berkeley Packet Filter) to trace file deletion events on a Linux system. The eBPF program is loaded from an ELF file and attached to the appropriate kernel hooks to monitor file deletions.
Watch the video for a short demonstration of this tool in action.
- Go (version 1.16 or higher)
- Linux system with eBPF support
clang
andllvm
for compiling eBPF programslibbpf
librarybpftool
command-line tool to inspect and manage BPF objects
- Install Go: Follow the instructions on the official Go website. In Ubuntu/Debian you can also install go as follows:
sudo apt install golang-go echo 'export GOPATH=$HOME/go' >> ~/.profile echo 'export PATH=$GOPATH/bin:$PATH' >> ~/.profile source ~/.profile
- Install clang and llvm:
sudo apt-get install clang llvm
- Install libbpf:
sudo apt-get install libbpf-dev
- Clone the repository:
git clone https://github.com/srodi/ebpf-file-delete-tracer.git cd ebpf-file-delete-tracer
- Compile the eBPF program:
clang -O2 -g -target bpf -c trace_file_delete.c -o trace_file_delete.o
- Run the Go program:
sudo go run main.go
The implementation for the eBPF program is found in trace_file_delete.c and the implementation for the user space application is in main.go.
This eBPF program is designed to trace the unlinkat
system call, which is used to delete files in the Linux operating system. The program captures and logs details about the process performing the deletion and the file being deleted. Below is a detailed description of the key components and functionality of the program:
-
Header Inclusions:
vmlinux.h
: Includes kernel structures and definitions.bpf_helpers.h
,bpf_tracing.h
,bpf_core_read.h
: Include BPF-specific functions and helpers.
-
Event Structure:
- Defines a structure
event
to hold the data that will be sent to user space. This includes:pid
: Process ID of the process performing the deletion.comm
: Command name (process name).filename
: Name of the file being deleted.
- Defines a structure
-
BPF Map:
- Defines a BPF map
events
of typeBPF_MAP_TYPE_PERF_EVENT_ARRAY
to send events to user space. This map can hold up to 1024 entries.
- Defines a BPF map
-
Tracepoint:
- Attaches to the
sys_enter_unlinkat
tracepoint, which is triggered when theunlinkat
system call is invoked. - In the tracepoint handler
trace_unlinkat
:- Initializes an
event
structure. - Retrieves the current process ID and command name.
- Reads the filename argument from user space.
- Outputs the event to user space using
bpf_perf_event_output
.
- Initializes an
- Attaches to the
-
License:
- Specifies the license for the eBPF program as GPL.
This Go file sets up an eBPF program to monitor and prevent file deletions. The program performs the following steps:
-
Set RLIMIT_MEMLOCK Resource Limit:
- Adjusts the RLIMIT_MEMLOCK resource limit to allow locking memory for eBPF.
- Uses
unix.Setrlimit
to set the RLIMIT_MEMLOCK resource limit to memLockLimit which is set to 64 MiB.
-
Load eBPF Program:
- Loads the compiled eBPF program from an ELF file specified by
bpfProgPath
. - Uses
ebpf.LoadCollectionSpec
to load the eBPF program from the specified ELF file.
- Loads the compiled eBPF program from an ELF file specified by
-
Create eBPF Collection:
- Creates a new eBPF collection from the loaded program.
- Uses
ebpf.NewCollection
to create a new eBPF collection from the loaded program.
-
Attach eBPF Program to Tracepoint:
- Attaches the eBPF program to the
sys_enter_unlinkat
tracepoint to monitor file deletions. - Uses
link.Tracepoint
to attach the eBPF program to thesys_enter_unlinkat
tracepoint.
- Attaches the eBPF program to the
-
Set Up Perf Event Reader:
- Sets up a perf event reader to read events generated by the eBPF program.
- Uses
perf.NewReader
to create a perf event reader for theevents
map in the eBPF collection.
-
Handle System Signals:
- Handles system signals (SIGINT, SIGTERM) for graceful shutdown.
- Uses
os.Signal
andsyscall
to handle SIGINT and SIGTERM signals for graceful shutdown.
-
Read and Print eBPF Program Output:
- Reads and prints the output from the eBPF program (perf event reader), which includes the PID, command, and filename of the process attempting to delete a file.
This file is essential for setting up and running the eBPF program to monitor file deletions on a Linux system.
We welcome contributions! Please follow these steps:
- Fork the repository.
- Create a new branch (
git checkout -b feature-branch
). - Make your changes.
- Commit your changes (
git commit -am 'Add new feature'
). - Push to the branch (
git push origin feature-branch
). - Create a new Pull Request.
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
Update the package lists for upgrades and new package installations, and upgrade all installed packages to their latest versions without prompting for confirmation.
sudo apt update && sudo apt upgrade --yes
Install the libbpf development library and search for the file named "bpf_helpers.h"
within the /usr/include
directory.
sudo apt install libbpf-dev
find /usr/include -name "bpf_helpers.h"
Ensure that the BPF filesystem is mounted
sudo mount -t bpf bpf /sys/fs/bpf/
bpftool
is a utility for inspection and manipulation of eBPF programs and maps on a Linux system. It allows users to load, verify, and attach eBPF programs, as well as query and update eBPF maps. For more information, refer to the libbpf/bpftool GitHub repo
Install and use bpftool
. 4. In Linux distributions this package is provided by linux-tools-common
sudo apt-get install linux-tools-common
If you are using WSL2
you will have to install bpftool
manually
git clone --recurse-submodules https://github.com/libbpf/bpftool.git
cd bpftool/src
sudo make install
Generate vmlinux.h
using bpftools
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
Compile the C
code
clang -O2 -g -target bpf -c trace_file_delete.c -o trace_file_delete.o
Load the BPF Program using bpftool
- this command will also attach
the program to tracepoint/syscalls/sys_enter_unlinkat
sudo bpftool prog load trace_file_delete.o /sys/fs/bpf/trace_unlinkat autoattach
Show loaded BPF program details in json
format
sudo bpftool --json --pretty prog show |jq -r '.[] | select(.name=="trace_unlinkat")'
To detach the program and remove the pinned file (prior to re-compiling C
code)
sudo rm /sys/fs/bpf/trace_unlinkat
You can add arbitrary print statements in the ebpf program as follows
// debug sending output at /sys/kernel/debug/tracing/trace_pipe
bpf_printk("PID: %d, COMM: %s, FILENAME: %s\n", evt.pid, evt.comm, evt.filename);
You can view the debug log at /sys/kernel/debug/tracing/trace_pipe
❯ sudo cat /sys/kernel/debug/tracing/trace_pipe | grep -i bpf_trace_printk
<...>-138718 [010] ....1 32416.629533: bpf_trace_printk: PID: 138718, COMM: rm, FILENAME: some
Check for kernel logs errors
dmesg | tail