Is it normal for tracepoint eBPF program inside the container to spit out stuff on the host OS? #1547
-
Hi there! I'm trying to create a lab environment inside devcontainer to run a trivial tutorial eBPF program, which spins up the docker image with SYS_ADMIN capability:
//go:build ignore
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#define BPF_NO_GLOBAL_DATA
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
typedef int pid_t;
const pid_t pid_filter = 0;
char LICENSE[] SEC("license") = "Dual BSD/GPL";
SEC("tp/syscalls/sys_enter_write")
int handle_tp(void *ctx)
{
pid_t pid = bpf_get_current_pid_tgid() >> 32;
if (pid_filter && pid != pid_filter)
return 0;
bpf_printk("BPF triggered sys_enter_write from PID %d.\n", pid);
return 0;
}
package main
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go minimal minimal.bpf.c
import (
"log"
"math"
"time"
"github.com/cilium/ebpf/link"
)
func main() {
// Load the compiled eBPF ELF and load it into the kernel.
var objs minimalObjects
if err := loadMinimalObjects(&objs, nil); err != nil {
log.Fatal("Loading eBPF objects:", err)
}
defer objs.Close()
// Attach to the same tracepoint mentioned in minimal.bpf.c
kp, err := link.Tracepoint("syscalls", "sys_enter_write", objs.minimalPrograms.HandleTp, nil)
if err != nil {
log.Fatalf("opening tracepoint: %s", err)
}
defer kp.Close()
// Waiting for events...
log.Println("Waiting for events..")
time.Sleep(math.MaxInt64)
} Firstly, it refuses to run without mounting the debugfs/tracefs, so I mounted them:
services:
cli:
image: "ghcr.io/easy-ebpf/tutorial-minimal-example:latest"
privileged: false
cap_add:
- SYS_ADMIN
volumes:
- ..:/workspaces/cli
- ./fish:/root/.config/fish
- /sys/kernel/tracing:/sys/kernel/tracing:ro
- /sys/kernel/debug:/sys/kernel/debug:ro
After successfully running the eBPF program, I found out that my program also includes the info from my host system, which is not very good for demonstration purposes. (e.g. Hyprland and other desktop stuff will show up, which shouldn't be running inside the container) Is there any way to solve this? This is my repository that has the preceding issue:https://github.com/easy-ebpf/tutorial-minimal-example You can try it out quickly by creating the codespace, and it'll show all the processes calling the Makefile contains 2 commands to quickly execute the program and read the trace: Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
eBPF programs are attached to events in the Linux kernel. Container environments (e.g. docker) often share the kernel with the host environment. In such scenarios the described behavior is expected. To limit the eBPF program to a specified virtualized environment, you could check the cgroup of the environment, communicate this cgroup to the eBPF program (e.g. via eBPF maps), and check at the beginning of the eBPF program the cgroup. If the cgroup from user space matches the cgroup from |
Beta Was this translation helpful? Give feedback.
eBPF programs are attached to events in the Linux kernel. Container environments (e.g. docker) often share the kernel with the host environment. In such scenarios the described behavior is expected.
To limit the eBPF program to a specified virtualized environment, you could check the cgroup of the environment, communicate this cgroup to the eBPF program (e.g. via eBPF maps), and check at the beginning of the eBPF program the cgroup. If the cgroup from user space matches the cgroup from
bpf_get_current_cgroup_id
then continue your program, otherwise return early.