Detect a buggy Ubuntu kernel (#9648)
Vladimir Kobal committed
Aug 4, 2020 at 22:54 UTC
63258aa524f3c876a5a9c8524af9d0989788086b
4 files changed
+82
-3
collectors/ebpf.plugin/Makefile.am
+1
@@ -21,4 +21,5 @@ dist_noinst_DATA = \
21
22
dist_libconfig_DATA = \
23
ebpf.conf \
24
+ ebpf_kernel_reject_list.txt \
25
$(NULL)
collectors/ebpf.plugin/ebpf_kernel_reject_list.txt
new
+1
@@ -0,0 +1 @@
1
+Ubuntu 4.18.0-13.
libnetdata/ebpf/ebpf.c
+77
-3
@@ -4,6 +4,7 @@
4
#include <sys/stat.h>
5
#include <fcntl.h>
6
#include <dlfcn.h>
7
+#include <sys/utsname.h>
8
9
#include "../libnetdata.h"
10
@@ -61,7 +62,7 @@ int clean_kprobe_events(FILE *out, int pid, netdata_ebpf_events_t *ptr)
62
int get_kernel_version(char *out, int size)
63
{
64
char major[16], minor[16], patch[16];
64
- char ver[256];
65
+ char ver[VERSION_STRING_LEN];
66
char *version = ver;
67
68
out[0] = '\0';
@@ -107,14 +108,14 @@ int get_kernel_version(char *out, int size)
108
109
int get_redhat_release()
110
{
110
- char buffer[256];
111
+ char buffer[VERSION_STRING_LEN + 1];
112
int major, minor;
113
FILE *fp = fopen("/etc/redhat-release", "r");
114
115
if (fp) {
116
major = 0;
117
minor = -1;
117
- size_t length = fread(buffer, sizeof(char), 255, fp);
118
+ size_t length = fread(buffer, sizeof(char), VERSION_STRING_LEN, fp);
119
if (length > 4) {
120
buffer[length] = '\0';
121
char *end = strchr(buffer, '.');
@@ -146,8 +147,81 @@ int get_redhat_release()
147
}
148
}
149
150
+/**
151
+ * Check if the kernel is in a list of rejected ones
152
+ *
153
+ * @return Returns 1 if the kernel is rejected, 0 otherwise.
154
+ */
155
+static int kernel_is_rejected()
156
+{
157
+ // Get kernel version from system
158
+ char version_string[VERSION_STRING_LEN + 1];
159
+ int version_string_len = 0;
160
+
161
+ if (read_file("/proc/version_signature", version_string, VERSION_STRING_LEN)) {
162
+ if (read_file("/proc/version", version_string, VERSION_STRING_LEN)) {
163
+ struct utsname uname_buf;
164
+ if (!uname(&uname_buf)) {
165
+ info("Cannot check kernel version");
166
+ return 0;
167
+ }
168
+ version_string_len =
169
+ snprintfz(version_string, VERSION_STRING_LEN, "%s %s", uname_buf.release, uname_buf.version);
170
+ }
171
+ }
172
+
173
+ if (!version_string_len)
174
+ version_string_len = strlen(version_string);
175
+
176
+ // Open a file with a list of rejected kernels
177
+ char *config_dir = getenv("NETDATA_USER_CONFIG_DIR");
178
+ if (config_dir == NULL) {
179
+ config_dir = CONFIG_DIR;
180
+ }
181
+
182
+ char filename[FILENAME_MAX + 1];
183
+ snprintfz(filename, FILENAME_MAX, "%s/%s", config_dir, EBPF_KERNEL_REJECT_LIST_FILE);
184
+ FILE *kernel_reject_list = fopen(filename, "r");
185
+
186
+ if (!kernel_reject_list) {
187
+ config_dir = getenv("NETDATA_STOCK_CONFIG_DIR");
188
+ if (config_dir == NULL) {
189
+ config_dir = LIBCONFIG_DIR;
190
+ }
191
+
192
+ snprintfz(filename, FILENAME_MAX, "%s/%s", config_dir, EBPF_KERNEL_REJECT_LIST_FILE);
193
+ kernel_reject_list = fopen(filename, "r");
194
+
195
+ if (!kernel_reject_list)
196
+ return 0;
197
+ }
198
+
199
+ // Find if the kernel is in the reject list
200
+ char *reject_string = NULL;
201
+ size_t buf_len = 0;
202
+ ssize_t reject_string_len;
203
+ while ((reject_string_len = getline(&reject_string, &buf_len, kernel_reject_list) - 1) > 0) {
204
+ if (version_string_len >= reject_string_len) {
205
+ if (!strncmp(version_string, reject_string, reject_string_len)) {
206
+ info("A buggy kernel is detected");
207
+ fclose(kernel_reject_list);
208
+ freez(reject_string);
209
+ return 1;
210
+ }
211
+ }
212
+ }
213
+
214
+ fclose(kernel_reject_list);
215
+ freez(reject_string);
216
+
217
+ return 0;
218
+}
219
+
220
static int has_ebpf_kernel_version(int version)
221
{
222
+ if (kernel_is_rejected())
223
+ return 0;
224
+
225
// Kernel 4.11.0 or RH > 7.5
226
return (version >= NETDATA_MINIMUM_EBPF_KERNEL || get_redhat_release() >= NETDATA_MINIMUM_RH_VERSION);
227
}
libnetdata/ebpf/ebpf.h
+3
@@ -52,6 +52,9 @@
52
*/
53
#define NETDATA_EBPF_KERNEL_4_11 264960
54
55
+#define VERSION_STRING_LEN 256
56
+#define EBPF_KERNEL_REJECT_LIST_FILE "ebpf_kernel_reject_list.txt"
57
+
58
typedef struct netdata_ebpf_events {
59
char type;
60
char *name;