@cryptotaxi247 / netdata-1 / commits / 63258aa52

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;