inspektor-gadget

Форк
0
177 строк · 4.5 Кб
1
//go:build linux
2
// +build linux
3

4
// Copyright 2023 The Inspektor Gadget authors
5
//
6
// Licensed under the Apache License, Version 2.0 (the "License");
7
// you may not use this file except in compliance with the License.
8
// You may obtain a copy of the License at
9
//
10
//     http://www.apache.org/licenses/LICENSE-2.0
11
//
12
// Unless required by applicable law or agreed to in writing, software
13
// distributed under the License is distributed on an "AS IS" BASIS,
14
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
// See the License for the specific language governing permissions and
16
// limitations under the License.
17

18
// Package host provides ways to access the host filesystem.
19
//
20
// Inspektor Gadget can run either in the host or in a container. When running
21
// in a container, the host filesystem must be available in a specific
22
// directory.
23
package host
24

25
import (
26
	"fmt"
27
	"os"
28
	"path/filepath"
29
	"strings"
30

31
	"github.com/spf13/cobra"
32
)
33

34
var (
35
	HostRoot   string
36
	HostProcFs string
37
)
38

39
func init() {
40
	// Initialize HostRoot and HostProcFs
41
	HostRoot = os.Getenv("HOST_ROOT")
42
	if HostRoot == "" {
43
		HostRoot = "/"
44
	}
45
	HostProcFs = filepath.Join(HostRoot, "/proc")
46
}
47

48
type Config struct {
49
	// AutoMountFilesystems will automatically mount bpffs, debugfs and
50
	// tracefs if they are not already mounted.
51
	//
52
	// This is useful for some environments where those filesystems are not
53
	// mounted by default on the host, such as:
54
	// - minikube with the Docker driver
55
	// - Docker Desktop with WSL2
56
	// - Talos Linux
57
	AutoMountFilesystems bool
58
}
59

60
var (
61
	autoSdUnitRestartFlag    bool
62
	autoMountFilesystemsFlag bool
63
	autoWSLWorkaroundFlag    bool
64

65
	initDone bool
66
)
67

68
func Init(config Config) error {
69
	var err error
70

71
	// Init() is called both from the local runtime and the local manager operator.
72
	// Different gadgets (trace-exec and top-ebpf) have different code paths, and we need both to make both work.
73
	// TODO: understand why we need to call Init() twice and fix it.
74
	if initDone {
75
		return nil
76
	}
77

78
	// Apply systemd workaround first because it might start a new process and
79
	// exit before the other workarounds.
80
	if autoSdUnitRestartFlag {
81
		exit, err := autoSdUnitRestart()
82
		if exit {
83
			if err != nil {
84
				fmt.Fprintf(os.Stderr, "error: %v\n", err)
85
				os.Exit(1)
86
			}
87
			os.Exit(0)
88
		}
89
		if err != nil {
90
			return err
91
		}
92
	} else {
93
		if err := suggestSdUnitRestart(); err != nil {
94
			fmt.Fprintf(os.Stderr, "error: %v\n", err)
95
			os.Exit(1)
96
		}
97
	}
98

99
	// The mount workaround could either be applied unconditionally (in the
100
	// gadget DaemonSet) or with the flag (in ig).
101
	if config.AutoMountFilesystems || autoMountFilesystemsFlag {
102
		_, err = autoMountFilesystems(false)
103
		if err != nil {
104
			return err
105
		}
106
	} else {
107
		mountsSuggested, err := autoMountFilesystems(true)
108
		if err != nil {
109
			fmt.Fprintf(os.Stderr, "error: %v\n", err)
110
			os.Exit(1)
111
		}
112
		if len(mountsSuggested) != 0 {
113
			fmt.Fprintf(os.Stderr, "error: filesystems %s not mounted (did you try --auto-mount-filesystems?)\n", strings.Join(mountsSuggested, ", "))
114
			os.Exit(1)
115
		}
116
	}
117

118
	// The WSL workaround is applied with the flag (in ig).
119
	if autoWSLWorkaroundFlag {
120
		err = autoWSLWorkaround()
121
		if err != nil {
122
			return err
123
		}
124
	} else {
125
		err = suggestWSLWorkaround()
126
		if err != nil {
127
			fmt.Fprintf(os.Stderr, "error: %v\n", err)
128
			os.Exit(1)
129
		}
130
	}
131

132
	initDone = true
133
	return nil
134
}
135

136
// AddFlags adds CLI flags for various workarounds
137
func AddFlags(command *cobra.Command) {
138
	command.PersistentFlags().BoolVarP(
139
		&autoSdUnitRestartFlag,
140
		"auto-sd-unit-restart",
141
		"",
142
		false,
143
		"Automatically run in a privileged systemd unit if lacking enough capabilities",
144
	)
145

146
	// Enable the mount workaround by default when running inside a container.
147
	automountFilesystemsDefault := false
148
	if HostRoot != "" && HostRoot != "/" {
149
		automountFilesystemsDefault = true
150
	}
151
	command.PersistentFlags().BoolVarP(
152
		&autoMountFilesystemsFlag,
153
		"auto-mount-filesystems",
154
		"",
155
		automountFilesystemsDefault,
156
		"Automatically mount bpffs, debugfs and tracefs if they are not already mounted",
157
	)
158
	command.PersistentFlags().BoolVarP(
159
		&autoWSLWorkaroundFlag,
160
		"auto-wsl-workaround",
161
		"",
162
		false,
163
		"Automatically find the host procfs when running in WSL2",
164
	)
165
}
166

167
func GetProcComm(pid int) string {
168
	pidStr := fmt.Sprint(pid)
169
	commBytes, _ := os.ReadFile(filepath.Join(HostProcFs, pidStr, "comm"))
170
	return strings.TrimRight(string(commBytes), "\n")
171
}
172

173
func GetProcCmdline(pid int) []string {
174
	pidStr := fmt.Sprint(pid)
175
	cmdlineBytes, _ := os.ReadFile(filepath.Join(HostProcFs, pidStr, "cmdline"))
176
	return strings.Split(string(cmdlineBytes), "\x00")
177
}
178

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

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

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

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