github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/audit/seccomp/tracer/tracer.go (about) 1 // Copyright 2019-2023 The Inspektor Gadget authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build !withoutebpf 16 17 package tracer 18 19 import ( 20 "errors" 21 "fmt" 22 "os" 23 "unsafe" 24 25 "github.com/cilium/ebpf" 26 "github.com/cilium/ebpf/link" 27 "github.com/cilium/ebpf/perf" 28 29 gadgetcontext "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-context" 30 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets" 31 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/audit/seccomp/types" 32 eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types" 33 ) 34 35 //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -type event -cc clang -cflags ${CFLAGS} auditseccomp ./bpf/audit-seccomp.bpf.c -- -I./bpf/ -D__KERNEL__ 36 37 type Tracer struct { 38 config *Config 39 enricher gadgets.DataEnricherByMntNs 40 eventCallback func(*types.Event) 41 42 objs auditseccompObjects 43 reader *perf.Reader 44 45 // progLink links the BPF program to the tracepoint. 46 // A reference is kept so it can be closed it explicitly, otherwise 47 // the garbage collector might unlink it via the finalizer at any 48 // moment. 49 progLink link.Link 50 } 51 52 type Config struct { 53 MountnsMap *ebpf.Map 54 } 55 56 func NewTracer(config *Config, enricher gadgets.DataEnricherByMntNs, 57 eventCallback func(*types.Event), 58 ) (*Tracer, error) { 59 t := &Tracer{ 60 config: config, 61 enricher: enricher, 62 eventCallback: eventCallback, 63 } 64 65 if err := t.install(); err != nil { 66 t.Close() 67 return nil, err 68 } 69 70 go t.run() 71 72 return t, nil 73 } 74 75 func (t *Tracer) install() error { 76 spec, err := loadAuditseccomp() 77 if err != nil { 78 return fmt.Errorf("loading ebpf program: %w", err) 79 } 80 81 if err := gadgets.LoadeBPFSpec(t.config.MountnsMap, spec, nil, &t.objs); err != nil { 82 return fmt.Errorf("loading ebpf spec: %w", err) 83 } 84 85 t.reader, err = perf.NewReader(t.objs.Events, gadgets.PerfBufferPages*os.Getpagesize()) 86 if err != nil { 87 return fmt.Errorf("getting a perf reader: %w", err) 88 } 89 90 t.progLink, err = link.Kprobe("audit_seccomp", t.objs.IgAuditSecc, nil) 91 if err != nil { 92 return fmt.Errorf("attaching kprobe: %w", err) 93 } 94 95 return nil 96 } 97 98 func (t *Tracer) run() { 99 for { 100 record, err := t.reader.Read() 101 if err != nil { 102 if errors.Is(err, perf.ErrClosed) { 103 // nothing to do, we're done 104 return 105 } 106 107 msg := fmt.Sprintf("Error reading perf ring buffer: %s", err) 108 t.eventCallback(types.Base(eventtypes.Err(msg))) 109 return 110 } 111 112 if record.LostSamples > 0 { 113 msg := fmt.Sprintf("lost %d samples", record.LostSamples) 114 t.eventCallback(types.Base(eventtypes.Warn(msg))) 115 continue 116 } 117 118 eventC := (*auditseccompEvent)(unsafe.Pointer(&record.RawSample[0])) 119 120 event := types.Event{ 121 Event: eventtypes.Event{ 122 Type: eventtypes.NORMAL, 123 Timestamp: gadgets.WallTimeFromBootTime(eventC.Timestamp), 124 }, 125 Pid: uint32(eventC.Pid), 126 WithMountNsID: eventtypes.WithMountNsID{MountNsID: eventC.MntnsId}, 127 Syscall: syscallToName(int(eventC.Syscall)), 128 Code: codeToName(uint(eventC.Code)), 129 Comm: gadgets.FromCString(eventC.Comm[:]), 130 } 131 132 if t.enricher != nil { 133 t.enricher.EnrichByMntNs(&event.CommonData, event.MountNsID) 134 } 135 136 t.eventCallback(&event) 137 } 138 } 139 140 // Close closes the tracer 141 // TODO: Unexport this function when the refactoring is done 142 func (t *Tracer) Close() { 143 t.progLink = gadgets.CloseLink(t.progLink) 144 if t.reader != nil { 145 t.reader.Close() 146 } 147 t.objs.Close() 148 } 149 150 // --- 151 152 func (t *Tracer) Run(gadgetCtx gadgets.GadgetContext) error { 153 defer t.Close() 154 if err := t.install(); err != nil { 155 return fmt.Errorf("installing tracer: %w", err) 156 } 157 158 go t.run() 159 gadgetcontext.WaitForTimeoutOrDone(gadgetCtx) 160 161 return nil 162 } 163 164 func (t *Tracer) SetMountNsMap(mountnsMap *ebpf.Map) { 165 t.config.MountnsMap = mountnsMap 166 } 167 168 func (t *Tracer) SetEventHandler(handler any) { 169 nh, ok := handler.(func(ev *types.Event)) 170 if !ok { 171 panic("event handler invalid") 172 } 173 t.eventCallback = nh 174 } 175 176 func (g *GadgetDesc) NewInstance() (gadgets.Gadget, error) { 177 t := &Tracer{ 178 config: &Config{}, 179 } 180 return t, nil 181 }