added checksum to detect corruption in netdev rename tasks (#20048)
Costa Tsaousis committed
Apr 3, 2025 at 18:06 UTC
62ea17c887f0e3a7633517a723a0b13dcbb4f116
3 files changed
+94
-49
src/collectors/proc.plugin/proc_net_dev.c
+53
-46
@@ -317,60 +317,65 @@ static void netdev_charts_release(struct netdev *d) {
317
}
318
319
static void netdev_free_chart_strings(struct netdev *d) {
320
- freez((void *)d->chart_type_net_bytes);
321
- freez((void *)d->chart_type_net_compressed);
322
- freez((void *)d->chart_type_net_drops);
323
- freez((void *)d->chart_type_net_errors);
324
- freez((void *)d->chart_type_net_events);
325
- freez((void *)d->chart_type_net_fifo);
326
- freez((void *)d->chart_type_net_packets);
327
- freez((void *)d->chart_type_net_speed);
328
- freez((void *)d->chart_type_net_duplex);
329
- freez((void *)d->chart_type_net_operstate);
330
- freez((void *)d->chart_type_net_carrier);
331
- freez((void *)d->chart_type_net_mtu);
332
-
333
- freez((void *)d->chart_id_net_bytes);
334
- freez((void *)d->chart_id_net_compressed);
335
- freez((void *)d->chart_id_net_drops);
336
- freez((void *)d->chart_id_net_errors);
337
- freez((void *)d->chart_id_net_events);
338
- freez((void *)d->chart_id_net_fifo);
339
- freez((void *)d->chart_id_net_packets);
340
- freez((void *)d->chart_id_net_speed);
341
- freez((void *)d->chart_id_net_duplex);
342
- freez((void *)d->chart_id_net_operstate);
343
- freez((void *)d->chart_id_net_carrier);
344
- freez((void *)d->chart_id_net_mtu);
345
-
346
- freez((void *)d->chart_ctx_net_bytes);
347
- freez((void *)d->chart_ctx_net_compressed);
348
- freez((void *)d->chart_ctx_net_drops);
349
- freez((void *)d->chart_ctx_net_errors);
350
- freez((void *)d->chart_ctx_net_events);
351
- freez((void *)d->chart_ctx_net_fifo);
352
- freez((void *)d->chart_ctx_net_packets);
353
- freez((void *)d->chart_ctx_net_speed);
354
- freez((void *)d->chart_ctx_net_duplex);
355
- freez((void *)d->chart_ctx_net_operstate);
356
- freez((void *)d->chart_ctx_net_carrier);
357
- freez((void *)d->chart_ctx_net_mtu);
358
-
359
- freez((void *)d->chart_family);
320
+ freez_and_set_to_null(d->chart_type_net_bytes);
321
+ freez_and_set_to_null(d->chart_type_net_compressed);
322
+ freez_and_set_to_null(d->chart_type_net_drops);
323
+ freez_and_set_to_null(d->chart_type_net_errors);
324
+ freez_and_set_to_null(d->chart_type_net_events);
325
+ freez_and_set_to_null(d->chart_type_net_fifo);
326
+ freez_and_set_to_null(d->chart_type_net_packets);
327
+ freez_and_set_to_null(d->chart_type_net_speed);
328
+ freez_and_set_to_null(d->chart_type_net_duplex);
329
+ freez_and_set_to_null(d->chart_type_net_operstate);
330
+ freez_and_set_to_null(d->chart_type_net_carrier);
331
+ freez_and_set_to_null(d->chart_type_net_mtu);
332
+
333
+ freez_and_set_to_null(d->chart_id_net_bytes);
334
+ freez_and_set_to_null(d->chart_id_net_compressed);
335
+ freez_and_set_to_null(d->chart_id_net_drops);
336
+ freez_and_set_to_null(d->chart_id_net_errors);
337
+ freez_and_set_to_null(d->chart_id_net_events);
338
+ freez_and_set_to_null(d->chart_id_net_fifo);
339
+ freez_and_set_to_null(d->chart_id_net_packets);
340
+ freez_and_set_to_null(d->chart_id_net_speed);
341
+ freez_and_set_to_null(d->chart_id_net_duplex);
342
+ freez_and_set_to_null(d->chart_id_net_operstate);
343
+ freez_and_set_to_null(d->chart_id_net_carrier);
344
+ freez_and_set_to_null(d->chart_id_net_mtu);
345
+
346
+ freez_and_set_to_null(d->chart_ctx_net_bytes);
347
+ freez_and_set_to_null(d->chart_ctx_net_compressed);
348
+ freez_and_set_to_null(d->chart_ctx_net_drops);
349
+ freez_and_set_to_null(d->chart_ctx_net_errors);
350
+ freez_and_set_to_null(d->chart_ctx_net_events);
351
+ freez_and_set_to_null(d->chart_ctx_net_fifo);
352
+ freez_and_set_to_null(d->chart_ctx_net_packets);
353
+ freez_and_set_to_null(d->chart_ctx_net_speed);
354
+ freez_and_set_to_null(d->chart_ctx_net_duplex);
355
+ freez_and_set_to_null(d->chart_ctx_net_operstate);
356
+ freez_and_set_to_null(d->chart_ctx_net_carrier);
357
+ freez_and_set_to_null(d->chart_ctx_net_mtu);
358
+
359
+ freez_and_set_to_null(d->chart_family);
360
}
361
362
static void netdev_free(struct netdev *d) {
363
netdev_charts_release(d);
364
netdev_free_chart_strings(d);
365
+
366
rrdlabels_destroy(d->chart_labels);
367
+ d->chart_labels = NULL;
368
+
369
cgroup_netdev_release(d->cgroup_netdev_link);
370
+ d->cgroup_netdev_link = NULL;
371
+
372
+ freez_and_set_to_null(d->name);
373
+ freez_and_set_to_null(d->filename_speed);
374
+ freez_and_set_to_null(d->filename_duplex);
375
+ freez_and_set_to_null(d->filename_operstate);
376
+ freez_and_set_to_null(d->filename_carrier);
377
+ freez_and_set_to_null(d->filename_mtu);
378
368
- freez((void *)d->name);
369
- freez((void *)d->filename_speed);
370
- freez((void *)d->filename_duplex);
371
- freez((void *)d->filename_operstate);
372
- freez((void *)d->filename_carrier);
373
- freez((void *)d->filename_mtu);
379
freez((void *)d);
380
}
381
@@ -379,6 +384,8 @@ static netdata_mutex_t netdev_mutex = NETDATA_MUTEX_INITIALIZER;
384
// ----------------------------------------------------------------------------
385
386
static inline void netdev_rename(struct netdev *d, struct rename_task *r) {
387
+ rename_task_verify_checksum(r);
388
+
389
collector_info("CGROUP: renaming network interface '%s' as '%s' under '%s'", d->name, r->container_device, r->container_name);
390
391
netdev_charts_release(d);
src/collectors/proc.plugin/proc_net_dev_renames.c
+33
-3
@@ -4,14 +4,40 @@
4
5
DICTIONARY *netdev_renames = NULL;
6
7
+static XXH64_hash_t rename_task_hash(struct rename_task *r) {
8
+ struct rename_task local_copy = *r;
9
+ local_copy.checksum = 0;
10
+ return XXH3_64bits(&local_copy, sizeof(local_copy));
11
+}
12
+
13
+// Set the checksum for a rename_task
14
+static void rename_task_set_checksum(struct rename_task *r) {
15
+ r->checksum = rename_task_hash(r);
16
+}
17
+
18
+// Verify the checksum for a rename_task
19
+void rename_task_verify_checksum(struct rename_task *r) {
20
+ if(r->checksum != rename_task_hash(r))
21
+ fatal("MEMORY CORRUPTION DETECTED in rename_task structure. "
22
+ "Expected checksum: 0x%016" PRIx64 ", "
23
+ "Calculated checksum: 0x%016" PRIx64,
24
+ r->checksum, rename_task_hash(r));
25
+}
26
+
27
static void dictionary_netdev_rename_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
28
struct rename_task *r = value;
29
30
+ rename_task_verify_checksum(r);
31
+
32
cgroup_netdev_release(r->cgroup_netdev_link);
33
+ r->cgroup_netdev_link = NULL;
34
+
35
rrdlabels_destroy(r->chart_labels);
12
- freez((void *) r->container_name);
13
- freez((void *) r->container_device);
14
- freez((void *) r->ctx_prefix);
36
+ r->chart_labels = NULL;
37
+
38
+ freez_and_set_to_null(r->container_name);
39
+ freez_and_set_to_null(r->container_device);
40
+ freez_and_set_to_null(r->ctx_prefix);
41
}
42
43
void netdev_renames_init(void) {
@@ -41,8 +67,12 @@ void cgroup_rename_task_add(
67
.ctx_prefix = strdupz(ctx_prefix),
68
.chart_labels = rrdlabels_create(),
69
.cgroup_netdev_link = cgroup_netdev_link,
70
+ .checksum = 0, // Will be set below
71
};
72
rrdlabels_migrate_to_these(tmp.chart_labels, labels);
73
+
74
+ // Set the checksum after all fields are initialized
75
+ rename_task_set_checksum(&tmp);
76
77
dictionary_set(netdev_renames, host_device, &tmp, sizeof(tmp));
78
}
src/collectors/proc.plugin/proc_net_dev_renames.h
+8
@@ -5,6 +5,11 @@
5
6
#include "plugin_proc.h"
7
8
+#define freez_and_set_to_null(p) do { \
9
+ freez((void *)p); \
10
+ p = NULL; \
11
+} while(0)
12
+
13
extern DICTIONARY *netdev_renames;
14
15
struct rename_task {
@@ -13,10 +18,13 @@ struct rename_task {
18
const char *ctx_prefix;
19
RRDLABELS *chart_labels;
20
const DICTIONARY_ITEM *cgroup_netdev_link;
21
+ XXH64_hash_t checksum;
22
};
23
24
void netdev_renames_init(void);
25
26
+void rename_task_verify_checksum(struct rename_task *r);
27
+
28
void cgroup_netdev_reset_all(void);
29
void cgroup_netdev_release(const DICTIONARY_ITEM *link);
30
const void *cgroup_netdev_dup(const DICTIONARY_ITEM *link);