Skip to content

Commit

Permalink
feat: bpf code refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
c-ravela committed Oct 20, 2023
1 parent 43ba716 commit fb0fde9
Show file tree
Hide file tree
Showing 18 changed files with 1,789 additions and 123 deletions.
39 changes: 6 additions & 33 deletions cmd/tarian_detector/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"time"

"github.com/intelops/tarian-detector/pkg/detector"
"github.com/intelops/tarian-detector/pkg/linker"
bpf "github.com/intelops/tarian-detector/pkg/eBPF"
"k8s.io/client-go/rest"
)

Expand All @@ -27,14 +27,12 @@ func main() {
watcher.Start()
}

// Loads the ebpf programs
bpfLinker, err := LoadPrograms(BpfModules)
BpfModules, err := bpf.GetDetectors()
if err != nil {
log.Fatal(err)
}

// Converts bpf handlers to detectors
eventDetectors, err := GetDetectors(bpfLinker.ProbeHandlers)
detectors, err := BpfModules.Start()
if err != nil {
log.Fatal(err)
}
Expand All @@ -43,7 +41,7 @@ func main() {
eventsDetector := detector.NewEventsDetector()

// Add ebpf programs to detectors
eventsDetector.Add(eventDetectors)
eventsDetector.Add(detectors)

// Start and defer Close
err = eventsDetector.Start()
Expand All @@ -53,7 +51,7 @@ func main() {
defer eventsDetector.Close()

log.Printf("%d detectors running...\n\n", eventsDetector.Count())
defer stats(eventsDetector, bpfLinker)
// defer stats(eventsDetector, bpfLinker)

// Loop read events
go func() {
Expand All @@ -63,7 +61,7 @@ func main() {
fmt.Println(err)
}

k8sCtx, err := GetK8sContext(watcher, e["process_id"].(uint32))
k8sCtx, err := GetK8sContext(watcher, e["host_pid"].(uint32))
if err != nil {
log.Print(err)
e["kubernetes"] = err.Error()
Expand All @@ -90,28 +88,3 @@ func printEvent(data map[string]any) {

log.Printf("%s\n%s%s\n", div, msg, div)
}

func stats(d *detector.EventsDetector, l *linker.Linker) {
// fmt.Print("\033[H\033[2J")
fmt.Printf("\n\n%d detectors running...\n", d.Count())
fmt.Printf("Total Record captured %d\n", d.TotalRecordsCount)

fmt.Printf("Event wise count...\n\n")
countTriggered := 0
for k, v := range l.ProbeIds {
if !v {
// skips the disabled probes
continue
}

_, keyExists := d.ProbeRecordsCount[k]
if keyExists {
countTriggered++
fmt.Printf("%s: %d\n", k, d.ProbeRecordsCount[k])
} else {
fmt.Printf("%s: 0\n", k)
}
}

fmt.Printf("\n%d events triggered in total.\n", countTriggered)
}
167 changes: 167 additions & 0 deletions pkg/eBPF/bpf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Authors of Tarian & the Organization created Tarian

package bpf

import (
"fmt"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/ringbuf"
)

type Module interface {
NewModule() (BpfModule, error) // tells how create a ebpf module.
}

type HookType int

// Predefined hooks
const (
Tracepoint HookType = iota
RawTracepoint
Kprobe
Kretprobe
Cgroup
)

type Hook struct {
Type HookType
Group string // HookType: Tracepoint needs this Field
Name string
Opts any // expected values with relavant hook type: cilium/ebpf/link.*TracepointOptions | RawTracepointOptions | *KprobeOptions | .*KprobeOptions | .KprobeMultiOptions | .*KprobeOptions | .*TracepointOptions
}

type BpfProgram struct {
Id string
Hook Hook
Name *ebpf.Program
ShouldAttach bool
}

type BpfModule struct {
Id string
Programs []BpfProgram
Map *ebpf.Map
}

type Handler struct {
Id string
MapReader *ringbuf.Reader
ProbeLinks []link.Link
}

func NewBpfModule() BpfModule {
return BpfModule{
Programs: make([]BpfProgram, 0),
}
}

func (bp *BpfProgram) AttachProbe() (link.Link, error) {
var l link.Link
var err error

probe := bp.Hook

switch probe.Type {
case Tracepoint:
var opts *link.TracepointOptions
if probe.Opts != nil {
opts = probe.Opts.(*link.TracepointOptions)
} else {
opts = nil
}
l, err = link.Tracepoint(probe.Group, probe.Name, bp.Name, opts)
case RawTracepoint:
var opts link.RawTracepointOptions
if probe.Opts != nil {
opts = probe.Opts.(link.RawTracepointOptions)
} else {
return nil, fmt.Errorf("opts cannot be nil for Hook.Type: RawTracepoint")
}

l, err = link.AttachRawTracepoint(opts)
case Kprobe:
var opts *link.KprobeOptions
if probe.Opts != nil {
opts = probe.Opts.(*link.KprobeOptions)
} else {
opts = nil
}

l, err = link.Kprobe(probe.Name, bp.Name, opts)
case Kretprobe:
var opts *link.KprobeOptions
if probe.Opts != nil {
opts = probe.Opts.(*link.KprobeOptions)
} else {
opts = nil
}

l, err = link.Kretprobe(probe.Name, bp.Name, opts)
case Cgroup:
var opts link.CgroupOptions
if probe.Opts != nil {
opts = probe.Opts.(link.CgroupOptions)
} else {
return nil, fmt.Errorf("opts cannot be nil for Hook.Type: Cgroup")
}

l, err = link.AttachCgroup(opts)
default:
return nil, fmt.Errorf("invalid hook type value: %v", probe.Type)
}

return l, err
}

func (bm *BpfModule) Start() (*Handler, error) {
var handler Handler
var err error

handler.Id = bm.Id
for _, prog := range bm.Programs {
if !prog.ShouldAttach {
continue
}

pL, err := prog.AttachProbe()
if err != nil {
return nil, err
}

handler.ProbeLinks = append(handler.ProbeLinks, pL)
}

handler.MapReader, err = createMapReader(bm.Map)
if err != nil {
return nil, err
}

return &handler, nil
}

func (h *Handler) ReadAsInterface() ([]byte, error) {
record, err := h.MapReader.Read()
if err != nil {
return []byte{}, err
}

return record.RawSample, nil
}

func (h *Handler) Close() error {
for _, link := range h.ProbeLinks {
err := link.Close()
if err != nil {
return err
}
}

return h.MapReader.Close()
}

func createMapReader(name *ebpf.Map) (*ringbuf.Reader, error) {
return ringbuf.NewReader(name)
}
Loading

0 comments on commit fb0fde9

Please sign in to comment.