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