github.com/cilium/ebpf@v0.10.0/examples/ringbuffer/main.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "log" 8 "os" 9 "os/signal" 10 "syscall" 11 12 "github.com/cilium/ebpf/link" 13 "github.com/cilium/ebpf/ringbuf" 14 "github.com/cilium/ebpf/rlimit" 15 "golang.org/x/sys/unix" 16 ) 17 18 // $BPF_CLANG and $BPF_CFLAGS are set by the Makefile. 19 //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS -type event bpf ringbuffer.c -- -I../headers 20 21 func main() { 22 // Name of the kernel function to trace. 23 fn := "sys_execve" 24 25 // Subscribe to signals for terminating the program. 26 stopper := make(chan os.Signal, 1) 27 signal.Notify(stopper, os.Interrupt, syscall.SIGTERM) 28 29 // Allow the current process to lock memory for eBPF resources. 30 if err := rlimit.RemoveMemlock(); err != nil { 31 log.Fatal(err) 32 } 33 34 // Load pre-compiled programs and maps into the kernel. 35 objs := bpfObjects{} 36 if err := loadBpfObjects(&objs, nil); err != nil { 37 log.Fatalf("loading objects: %v", err) 38 } 39 defer objs.Close() 40 41 // Open a Kprobe at the entry point of the kernel function and attach the 42 // pre-compiled program. Each time the kernel function enters, the program 43 // will emit an event containing pid and command of the execved task. 44 kp, err := link.Kprobe(fn, objs.KprobeExecve, nil) 45 if err != nil { 46 log.Fatalf("opening kprobe: %s", err) 47 } 48 defer kp.Close() 49 50 // Open a ringbuf reader from userspace RINGBUF map described in the 51 // eBPF C program. 52 rd, err := ringbuf.NewReader(objs.Events) 53 if err != nil { 54 log.Fatalf("opening ringbuf reader: %s", err) 55 } 56 defer rd.Close() 57 58 // Close the reader when the process receives a signal, which will exit 59 // the read loop. 60 go func() { 61 <-stopper 62 63 if err := rd.Close(); err != nil { 64 log.Fatalf("closing ringbuf reader: %s", err) 65 } 66 }() 67 68 log.Println("Waiting for events..") 69 70 // bpfEvent is generated by bpf2go. 71 var event bpfEvent 72 for { 73 record, err := rd.Read() 74 if err != nil { 75 if errors.Is(err, ringbuf.ErrClosed) { 76 log.Println("Received signal, exiting..") 77 return 78 } 79 log.Printf("reading from reader: %s", err) 80 continue 81 } 82 83 // Parse the ringbuf event entry into a bpfEvent structure. 84 if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil { 85 log.Printf("parsing ringbuf event: %s", err) 86 continue 87 } 88 89 log.Printf("pid: %d\tcomm: %s\n", event.Pid, unix.ByteSliceToString(event.Comm[:])) 90 } 91 }