diff --git a/elf/elf.go b/elf/elf.go index f9e0c7ee..9a888112 100644 --- a/elf/elf.go +++ b/elf/elf.go @@ -557,6 +557,7 @@ func (b *Module) Load(parameters map[string]SectionParams) error { isCgroupSock := strings.HasPrefix(secName, "cgroup/sock") isSocketFilter := strings.HasPrefix(secName, "socket") isTracepoint := strings.HasPrefix(secName, "tracepoint/") + isRawTracepoint := strings.HasPrefix(secName, "raw_tracepoint/") isSchedCls := strings.HasPrefix(secName, "sched_cls/") isSchedAct := strings.HasPrefix(secName, "sched_act/") @@ -579,6 +580,8 @@ func (b *Module) Load(parameters map[string]SectionParams) error { progType = uint32(C.BPF_PROG_TYPE_SOCKET_FILTER) case isTracepoint: progType = uint32(C.BPF_PROG_TYPE_TRACEPOINT) + case isRawTracepoint: + progType = uint32(C.BPF_PROG_TYPE_RAW_TRACEPOINT) case isSchedCls: progType = uint32(C.BPF_PROG_TYPE_SCHED_CLS) case isSchedAct: @@ -598,7 +601,7 @@ func (b *Module) Load(parameters map[string]SectionParams) error { } } - if isKprobe || isKretprobe || isUprobe || isUretprobe || isCgroupSkb || isCgroupSock || isSocketFilter || isTracepoint || isSchedCls || isSchedAct { + if isKprobe || isKretprobe || isUprobe || isUretprobe || isCgroupSkb || isCgroupSock || isSocketFilter || isTracepoint || isRawTracepoint || isSchedCls || isSchedAct { rdata, err := rsection.Data() if err != nil { return err @@ -662,6 +665,12 @@ func (b *Module) Load(parameters map[string]SectionParams) error { insns: insns, fd: int(progFd), } + case isRawTracepoint: + b.rawTracepointPrograms[secName] = &RawTracepointProgram{ + Name: secName, + insns: insns, + fd: int(progFd), + } case isSchedCls: fallthrough case isSchedAct: @@ -690,6 +699,7 @@ func (b *Module) Load(parameters map[string]SectionParams) error { isCgroupSock := strings.HasPrefix(secName, "cgroup/sock") isSocketFilter := strings.HasPrefix(secName, "socket") isTracepoint := strings.HasPrefix(secName, "tracepoint/") + isRawTracepoint := strings.HasPrefix(secName, "raw_tracepoint/") isSchedCls := strings.HasPrefix(secName, "sched_cls/") isSchedAct := strings.HasPrefix(secName, "sched_act/") @@ -711,6 +721,8 @@ func (b *Module) Load(parameters map[string]SectionParams) error { progType = uint32(C.BPF_PROG_TYPE_SOCKET_FILTER) case isTracepoint: progType = uint32(C.BPF_PROG_TYPE_TRACEPOINT) + case isRawTracepoint: + progType = uint32(C.BPF_PROG_TYPE_RAW_TRACEPOINT) case isSchedCls: progType = uint32(C.BPF_PROG_TYPE_SCHED_CLS) case isSchedAct: @@ -730,7 +742,7 @@ func (b *Module) Load(parameters map[string]SectionParams) error { } } - if isKprobe || isKretprobe || isUprobe || isUretprobe || isCgroupSkb || isCgroupSock || isSocketFilter || isTracepoint || isSchedCls || isSchedAct { + if isKprobe || isKretprobe || isUprobe || isUretprobe || isCgroupSkb || isCgroupSock || isSocketFilter || isTracepoint || isRawTracepoint || isSchedCls || isSchedAct { data, err := section.Data() if err != nil { return err @@ -789,6 +801,12 @@ func (b *Module) Load(parameters map[string]SectionParams) error { insns: insns, fd: int(progFd), } + case isRawTracepoint: + b.rawTracepointPrograms[secName] = &RawTracepointProgram{ + Name: secName, + insns: insns, + fd: int(progFd), + } case isSchedCls: fallthrough case isSchedAct: diff --git a/elf/module.go b/elf/module.go index 12cb1694..8c8aa171 100644 --- a/elf/module.go +++ b/elf/module.go @@ -88,6 +88,17 @@ int bpf_detach_socket(int sock, int fd) { return setsockopt(sock, SOL_SOCKET, SO_DETACH_BPF, &fd, sizeof(fd)); } + +int bpf_attach_raw_tracepoint(int prog_fd, char *tp_name) +{ + union bpf_attr attr; + + bzero(&attr, sizeof(attr)); + attr.raw_tracepoint.name = (__u64) tp_name; + attr.raw_tracepoint.prog_fd = prog_fd; + + return syscall(__NR_bpf, BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr)); +} */ import "C" @@ -96,14 +107,15 @@ type Module struct { fileReader io.ReaderAt file *elf.File - log []byte - maps map[string]*Map - probes map[string]*Kprobe - uprobes map[string]*Uprobe - cgroupPrograms map[string]*CgroupProgram - socketFilters map[string]*SocketFilter - tracepointPrograms map[string]*TracepointProgram - schedPrograms map[string]*SchedProgram + log []byte + maps map[string]*Map + probes map[string]*Kprobe + uprobes map[string]*Uprobe + cgroupPrograms map[string]*CgroupProgram + socketFilters map[string]*SocketFilter + tracepointPrograms map[string]*TracepointProgram + rawTracepointPrograms map[string]*RawTracepointProgram + schedPrograms map[string]*SchedProgram compatProbe bool // try to be automatically convert function names depending on kernel versions (SyS_ and __x64_sys_) } @@ -154,6 +166,13 @@ type TracepointProgram struct { efd int } +// RawTracepointProgram represents a tracepoint program +type RawTracepointProgram struct { + Name string + insns *C.struct_bpf_insn + fd int +} + // SchedProgram represents a traffic classifier program type SchedProgram struct { Name string @@ -163,13 +182,14 @@ type SchedProgram struct { func newModule() *Module { return &Module{ - probes: make(map[string]*Kprobe), - uprobes: make(map[string]*Uprobe), - cgroupPrograms: make(map[string]*CgroupProgram), - socketFilters: make(map[string]*SocketFilter), - tracepointPrograms: make(map[string]*TracepointProgram), - schedPrograms: make(map[string]*SchedProgram), - log: make([]byte, 524288), + probes: make(map[string]*Kprobe), + uprobes: make(map[string]*Uprobe), + cgroupPrograms: make(map[string]*CgroupProgram), + socketFilters: make(map[string]*SocketFilter), + tracepointPrograms: make(map[string]*TracepointProgram), + rawTracepointPrograms: make(map[string]*RawTracepointProgram), + schedPrograms: make(map[string]*SchedProgram), + log: make([]byte, 524288), } } @@ -352,6 +372,25 @@ func (b *Module) EnableTracepoint(secName string) error { return err } +func (b *Module) AttachRawTracepoint(secName string) error { + prog, ok := b.rawTracepointPrograms[secName] + if !ok { + return fmt.Errorf("no such raw tracepoint program %q", secName) + } + progFd := prog.fd + + name := strings.Split(secName, "raw_tracepoint/") + + tpNameCS := C.CString(name[1]) + res, err := C.bpf_attach_raw_tracepoint(C.int(progFd), tpNameCS) + C.free(unsafe.Pointer(tpNameCS)) + + if res < 0 { + return fmt.Errorf("failed to attach raw tracepoint: %v", err) + } + return nil +} + // IterKprobes returns a channel that emits the kprobes that included in the // module. func (b *Module) IterKprobes() <-chan *Kprobe { @@ -665,6 +704,15 @@ func (b *Module) closeTracepointPrograms() error { return nil } +func (b *Module) closeRawTracepointPrograms() error { + for _, program := range b.rawTracepointPrograms { + if err := syscall.Close(program.fd); err != nil { + return fmt.Errorf("error closing raw tracepoint program fd: %v", err) + } + } + return nil +} + func (b *Module) closeCgroupPrograms() error { for _, program := range b.cgroupPrograms { if err := syscall.Close(program.fd); err != nil { @@ -765,6 +813,9 @@ func (b *Module) CloseExt(options map[string]CloseOptions) error { if err := b.closeTracepointPrograms(); err != nil { return err } + if err := b.closeRawTracepointPrograms(); err != nil { + return err + } if err := b.closeSocketFilters(); err != nil { return err }