inspektor-gadget

Форк
0
207 строк · 5.9 Кб
1
// Copyright 2022-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 linux
16
// +build linux
17

18
package tracer_test
19

20
import (
21
	"fmt"
22
	"os"
23
	"path"
24
	"syscall"
25
	"testing"
26
	"time"
27

28
	"github.com/stretchr/testify/require"
29
	"golang.org/x/sys/unix"
30

31
	utilstest "github.com/inspektor-gadget/inspektor-gadget/internal/test"
32
	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/signal/tracer"
33
	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/signal/types"
34
	eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
35
)
36

37
func TestSignalTracerCreate(t *testing.T) {
38
	t.Parallel()
39

40
	utilstest.RequireRoot(t)
41

42
	tracer := createTracer(t, &tracer.Config{}, func(*types.Event) {})
43
	require.NotNil(t, tracer, "Returned tracer was nil")
44
}
45

46
func TestSignalTracerStopIdempotent(t *testing.T) {
47
	t.Parallel()
48

49
	utilstest.RequireRoot(t)
50

51
	tracer := createTracer(t, &tracer.Config{}, func(*types.Event) {})
52

53
	// Check that a double stop doesn't cause issues
54
	tracer.Stop()
55
	tracer.Stop()
56
}
57

58
func TestSignalTracer(t *testing.T) {
59
	t.Parallel()
60

61
	utilstest.RequireRoot(t)
62

63
	const unprivilegedUID = int(1435)
64
	const unprivilegedGID = int(6789)
65

66
	type testDefinition struct {
67
		getTracerConfig func(info *utilstest.RunnerInfo) *tracer.Config
68
		runnerConfig    *utilstest.RunnerConfig
69
		signalToSend    syscall.Signal
70
		generateEvent   func(syscall.Signal) (uint32, error)
71
		validateEvent   func(t *testing.T, info *utilstest.RunnerInfo, childPid uint32, events []types.Event)
72
	}
73

74
	tests := map[string]testDefinition{
75
		"captures_events_with_matching_filter": {
76
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
77
				return &tracer.Config{
78
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
79
				}
80
			},
81
			signalToSend:  syscall.SIGKILL,
82
			generateEvent: generateEvent,
83
			validateEvent: utilstest.ExpectOneEvent(func(info *utilstest.RunnerInfo, childPid uint32) *types.Event {
84
				return &types.Event{
85
					Event: eventtypes.Event{
86
						Type: eventtypes.NORMAL,
87
					},
88
					Pid:           uint32(info.Pid),
89
					Comm:          path.Base(os.Args[0]),
90
					Signal:        unix.SignalName(syscall.SIGKILL),
91
					TargetPid:     childPid,
92
					Retval:        0,
93
					Uid:           uint32(info.Uid),
94
					Gid:           uint32(info.Gid),
95
					WithMountNsID: eventtypes.WithMountNsID{MountNsID: info.MountNsID},
96
				}
97
			}),
98
		},
99
		"event_has_UID_and_GID_of_user_generating_event": {
100
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
101
				return &tracer.Config{
102
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
103
				}
104
			},
105
			runnerConfig: &utilstest.RunnerConfig{
106
				Uid: unprivilegedUID,
107
				Gid: unprivilegedGID,
108
			},
109
			signalToSend:  syscall.SIGKILL,
110
			generateEvent: generateEvent,
111
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, _ uint32, events []types.Event) {
112
				require.Len(t, events, 1, "One event expected")
113
				require.Equal(t, uint32(info.Uid), events[0].Uid, "Event has bad UID")
114
				require.Equal(t, uint32(info.Gid), events[0].Gid, "Event has bad GID")
115
			},
116
		},
117
	}
118

119
	for sig := syscall.SIGABRT; sig <= syscall.SIGXFSZ; sig++ {
120
		signal := sig
121
		tests[fmt.Sprintf("send_%s", unix.SignalName(signal))] = testDefinition{
122
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
123
				return &tracer.Config{
124
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
125
				}
126
			},
127
			signalToSend:  signal,
128
			generateEvent: generateEvent,
129
			validateEvent: utilstest.ExpectAtLeastOneEvent(func(info *utilstest.RunnerInfo, childPid uint32) *types.Event {
130
				return &types.Event{
131
					Event: eventtypes.Event{
132
						Type: eventtypes.NORMAL,
133
					},
134
					Pid:           uint32(info.Pid),
135
					Comm:          path.Base(os.Args[0]),
136
					Signal:        unix.SignalName(signal),
137
					TargetPid:     childPid,
138
					Retval:        0,
139
					Uid:           uint32(info.Uid),
140
					Gid:           uint32(info.Gid),
141
					WithMountNsID: eventtypes.WithMountNsID{MountNsID: info.MountNsID},
142
				}
143
			}),
144
		}
145
	}
146

147
	for name, test := range tests {
148
		test := test
149

150
		t.Run(name, func(t *testing.T) {
151
			t.Parallel()
152

153
			events := []types.Event{}
154
			eventCallback := func(event *types.Event) {
155
				// normalize
156
				event.Timestamp = 0
157

158
				events = append(events, *event)
159
			}
160

161
			runner := utilstest.NewRunnerWithTest(t, test.runnerConfig)
162

163
			createTracer(t, test.getTracerConfig(runner.Info), eventCallback)
164

165
			var childPid uint32
166

167
			utilstest.RunWithRunner(t, runner, func() error {
168
				var err error
169
				childPid, err = test.generateEvent(test.signalToSend)
170
				return err
171
			})
172

173
			// Give some time for the tracer to capture the events
174
			time.Sleep(100 * time.Millisecond)
175

176
			test.validateEvent(t, runner.Info, childPid, events)
177
		})
178
	}
179
}
180

181
func createTracer(
182
	t *testing.T, config *tracer.Config, callback func(*types.Event),
183
) *tracer.Tracer {
184
	t.Helper()
185

186
	tracer, err := tracer.NewTracer(config, nil, callback)
187
	require.Nil(t, err, "Error creating tracer: %s", err)
188
	t.Cleanup(tracer.Stop)
189

190
	return tracer
191
}
192

193
func generateEvent(signal syscall.Signal) (uint32, error) {
194
	childPid, err := syscall.ForkExec("/bin/sleep", []string{"inf"}, nil)
195
	if err != nil {
196
		return 0, fmt.Errorf("spawning child process: %w", err)
197
	}
198

199
	// We only test kill and not tkill or tgkill as this is a pain to deal with
200
	// pthread in golang.
201
	err = syscall.Kill(childPid, signal)
202
	if err != nil {
203
		return 0, fmt.Errorf("sending signal %d to process %d: %w", signal, childPid, err)
204
	}
205

206
	return uint32(childPid), nil
207
}
208

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

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

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

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