inspektor-gadget

Форк
0
181 строка · 4.5 Кб
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
}
182

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.