Fix potential use after free in RAM mode (#21809)
* cache uuid in mem_metric_handle to avoid dereferencing potentially freed RRDDIM during metric release (ram mode) * release rrddim metrics after querying oldest and latest times to prevent potential resource leaks (ram mode)
Stelios Fragkakis committed
Feb 25, 2026 at 16:46 UTC
c21e5cefba4b4beab106c07b739a2f88cfe9388f
1 file changed
+5
-2
src/database/ram/rrddim_mem.c
+5
-2
@@ -38,6 +38,7 @@ struct mem_metric_handle {
38
time_t last_updated_s;
39
time_t update_every_s;
40
41
+ UUIDMAP_ID uuid_id; // stored locally so cleanup doesn't need rd
42
REFCOUNT refcount;
43
};
44
@@ -66,6 +67,7 @@ STORAGE_METRIC_HANDLE *rrddim_metric_get_or_create(RRDDIM *rd, STORAGE_INSTANCE
67
if(!mh) {
68
mh = callocz(1, sizeof(struct mem_metric_handle));
69
mh->rd = rd;
70
+ mh->uuid_id = rd->uuid;
71
mh->refcount = 1;
72
update_metric_handle_from_rrddim(mh, rd);
73
*PValue = mh;
@@ -132,11 +134,10 @@ void rrddim_metric_release(STORAGE_METRIC_HANDLE *smh) {
134
// we can delete it
135
136
int64_t judy_mem = 0;
135
- RRDDIM *rd = mh->rd;
137
netdata_rwlock_wrlock(&rrddim_Judy_rwlock);
138
{
139
JudyAllocThreadPulseReset();
139
- JudyLDel(&rrddim_Judy_array, rd->uuid, PJE0);
140
+ JudyLDel(&rrddim_Judy_array, mh->uuid_id, PJE0);
141
judy_mem = JudyAllocThreadPulseGetAndReset();
142
}
143
netdata_rwlock_wrunlock(&rrddim_Judy_rwlock);
@@ -153,6 +154,7 @@ bool rrddim_metric_retention_by_uuid(STORAGE_INSTANCE *si __maybe_unused, nd_uui
154
155
*first_entry_s = rrddim_query_oldest_time_s(smh);
156
*last_entry_s = rrddim_query_latest_time_s(smh);
157
+ rrddim_metric_release(smh);
158
159
return true;
160
}
@@ -164,6 +166,7 @@ bool rrddim_metric_retention_by_id(STORAGE_INSTANCE *si __maybe_unused, UUIDMAP_
166
167
*first_entry_s = rrddim_query_oldest_time_s(smh);
168
*last_entry_s = rrddim_query_latest_time_s(smh);
169
+ rrddim_metric_release(smh);
170
171
return true;
172
}